diff --git a/.editorconfig b/.editorconfig index 76edc491c..1059bcdeb 100644 --- a/.editorconfig +++ b/.editorconfig @@ -16,6 +16,17 @@ tab_width = 4 # New line preferences end_of_line = lf insert_final_newline = true +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_explicit_tuple_names = true:suggestion # Markdown, JSON, YAML, props and csproj files [*.{md,json,yml,props,csproj}] @@ -106,7 +117,7 @@ csharp_style_conditional_delegate_call = true:suggestion csharp_prefer_static_local_function = true:suggestion csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:silent csharp_style_prefer_readonly_struct = true -csharp_style_prefer_method_group_conversion = true +csharp_style_prefer_method_group_conversion = true:silent # Code-block preferences csharp_prefer_braces = true:silent @@ -177,9 +188,9 @@ csharp_preserve_single_line_statements = false # Naming rules -dotnet_naming_rule.interfaces_should_be_prefixed_with_I.severity = suggestion +dotnet_naming_rule.interfaces_should_be_prefixed_with_i.severity = suggestion dotnet_naming_rule.interfaces_should_be_prefixed_with_I.symbols = interface -dotnet_naming_rule.interfaces_should_be_prefixed_with_I.style = IPascalCase +dotnet_naming_rule.interfaces_should_be_prefixed_with_i.style = IPascalCase dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion dotnet_naming_rule.types_should_be_pascal_case.symbols = types @@ -236,28 +247,22 @@ dotnet_naming_style.IPascalCase.required_suffix = dotnet_naming_style.IPascalCase.word_separator = dotnet_naming_style.IPascalCase.capitalization = pascal_case -# TODO: -# .NET 8 migration (new warnings are caused by the NET 8 C# compiler and analyzer) -# The following info messages might need to be fixed in the source code instead of hiding the actual message -# Without the following lines, dotnet format would fail -# Disable "Collection initialization can be simplified" +# Other settings +csharp_style_prefer_top_level_statements = true:suggestion +csharp_style_prefer_primary_constructors = false:suggestion +csharp_prefer_system_threading_lock = true:suggestion + + +# Analyzers +dotnet_diagnostic.CA1069.severity = none # CA1069: Enums values should not be duplicated +# Disable Collection initialization can be simplified dotnet_diagnostic.IDE0028.severity = none dotnet_diagnostic.IDE0300.severity = none dotnet_diagnostic.IDE0301.severity = none dotnet_diagnostic.IDE0302.severity = none dotnet_diagnostic.IDE0305.severity = none -# Disable "'new' expression can be simplified" -dotnet_diagnostic.IDE0090.severity = none -# Disable "Use primary constructor" -dotnet_diagnostic.IDE0290.severity = none -# Disable "Member '' does not access instance data and can be marked as static" -dotnet_diagnostic.CA1822.severity = none -# Disable "Change type of field '' from '' to '' for improved performance" -dotnet_diagnostic.CA1859.severity = none -# Disable "Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array" -dotnet_diagnostic.CA1861.severity = none -# Disable "Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'" -dotnet_diagnostic.CA1862.severity = none +dotnet_diagnostic.CS9113.severity = none # CS9113: Parameter 'value' is unread +dotnet_diagnostic.IDE0130.severity = none # IDE0130: Namespace does not match folder structure [src/Ryujinx/UI/ViewModels/**.cs] # Disable "mark members as static" rule for ViewModels diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index 0207442a2..cf250eb08 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -21,60 +21,9 @@ env: DOTNET_CLI_TELEMETRY_OPTOUT: 1 RYUJINX_BASE_VERSION: "1.3" RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "canary" - RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryubing" - RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO: "Ryujinx" - RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Canary-Releases" RELEASE: 1 jobs: - tag: - name: Create tag - runs-on: ubuntu-24.04 - steps: - - name: Get version info - id: version_info - run: | - echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT - echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT - shell: bash - - - name: Install GitLabCli - run: | - mkdir -p $HOME/.bin - gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64' - chmod +x gli - mv gli $HOME/.bin/ - echo "$HOME/.bin" >> $GITHUB_PATH - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Create GitLab tag - run: gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateTag "Canary-${{ steps.version_info.outputs.build_version }}|master" - - - name: Create release - uses: ncipollo/release-action@v1 - with: - name: "Canary ${{ steps.version_info.outputs.build_version }}" - tag: ${{ steps.version_info.outputs.build_version }} - body: | - # Canary builds: - - These builds are experimental and may sometimes not work, use [regular builds](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/Stable-Releases/releases/latest) instead if that sounds like something you don't want to deal with. - - | Platform | Artifact | - |--|--| - | Windows 64-bit | [Canary Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) | - | Windows ARM 64-bit | [Canary Windows ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_arm64.zip) | - | Linux 64-bit | [Canary Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) | - | Linux ARM 64-bit | [Canary Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) | - | macOS | [Canary macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) | - - **[Full Changelog](https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }})** - omitBodyDuringUpdate: true - owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }} - repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }} - token: ${{ secrets.RELEASE_TOKEN }} - release: name: Release for ${{ matrix.platform.name }} runs-on: ${{ matrix.platform.os }} @@ -82,7 +31,7 @@ jobs: matrix: platform: - { name: win-x64, os: windows-latest, zip_os_name: win_x64 } - - { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 } + #- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 } - { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 } - { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 } steps: @@ -108,11 +57,8 @@ jobs: sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place '/^Name=Ryujinx$/s/Name=Ryujinx/Name=Ryujinx-Canary/' distribution/linux/Ryujinx.desktop + sed -r --in-place '/^Name=Ryujinx$/s/Name=Ryujinx/Name=Ryujinx-Canary/' distribution/linux/Ryujinx.desktop shell: bash - name: Create output dir @@ -129,7 +75,24 @@ jobs: rm libarmeilleure-jitsupport.dylib 7z a ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish popd + + gh release download -R GreemDev/GLI -O gli.exe -p 'GitLabCli-win_x64.exe' + + ./gli.exe --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip" shell: bash + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install GitLabCli + if: matrix.platform.os == 'ubuntu-latest' + run: | + mkdir -p $HOME/.bin + gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64' + chmod +x gli + mv gli $HOME/.bin/ + echo "$HOME/.bin" >> $GITHUB_PATH + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Packing Linux builds if: matrix.platform.os == 'ubuntu-latest' @@ -139,6 +102,8 @@ jobs: chmod +x Ryujinx.sh Ryujinx tar -czvf ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish popd + + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz" shell: bash - name: Build AppImage (Linux) @@ -169,41 +134,17 @@ jobs: exit 1 fi - export UFLAG="gh-releases-zsync|${{ github.repository_owner }}|Canary-Releases|latest|*-$ARCH_NAME.AppImage.zsync" + export UFLAG="gh-releases-zsync|${{ secrets.RC_OWNER }}${{ secrets.RC_CANARY_NAME }}|latest|*-$ARCH_NAME.AppImage.zsync" BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh pushd publish_appimage mv Ryujinx.AppImage ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage mv Ryujinx.AppImage.zsync ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync - popd - shell: bash - - - name: Pushing new release - uses: ncipollo/release-action@v1 - with: - name: ${{ steps.version_info.outputs.build_version }} - artifacts: "release_output/*.tar.gz,release_output/*.zip,release_output/*AppImage*" - tag: ${{ steps.version_info.outputs.build_version }} - body: | - # Canary builds: - - These builds are experimental and may sometimes not work, use [regular builds](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/latest) instead if that sounds like something you don't want to deal with. - - | Platform | Artifact | - |--|--| - | Windows 64-bit | [Canary Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) | - | Windows ARM 64-bit | [Canary Windows ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_arm64.zip) | - | Linux 64-bit | [Canary Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) | - | Linux ARM 64-bit | [Canary Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) | - | macOS | [Canary macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) | - - **[Full Changelog](https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }})** - omitBodyDuringUpdate: true - allowUpdates: true - replacesArtifacts: true - owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }} - repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }} - token: ${{ secrets.RELEASE_TOKEN }} + 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: name: Release MacOS universal @@ -220,6 +161,16 @@ jobs: wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh sudo ./llvm.sh 17 + + - name: Install GitLabCli + run: | + mkdir -p $HOME/.bin + gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64' + chmod +x gli + mv gli $HOME/.bin/ + echo "$HOME/.bin" >> $GITHUB_PATH + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Install rcodesign run: | @@ -246,24 +197,53 @@ jobs: sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs shell: bash - name: Publish macOS Ryujinx run: | ./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish_ava ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 1 + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|publish_ava/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz" - - name: Pushing new release - uses: ncipollo/release-action@v1 - with: - name: "Canary ${{ steps.version_info.outputs.build_version }}" - artifacts: "publish_ava/*.tar.gz" - tag: ${{ steps.version_info.outputs.build_version }} - body: "" - omitBodyDuringUpdate: true - allowUpdates: true - replacesArtifacts: true - owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }} - repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }} - token: ${{ secrets.RELEASE_TOKEN }} + create_gitlab_release: + name: Create GitLab Release + runs-on: ubuntu-24.04 + needs: + - macos_release + - release + steps: + - uses: actions/checkout@v4 + + - name: Get version info + id: version_info + run: | + echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT + echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT + echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT + shell: bash + + - name: Install GitLabCli + run: | + mkdir -p $HOME/.bin + gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64' + chmod +x gli + mv gli $HOME/.bin/ + echo "$HOME/.bin" >> $GITHUB_PATH + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Create tag + run: | + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateTag "Canary-${{ steps.version_info.outputs.build_version }}|${{ steps.version_info.outputs.git_short_hash }}" + + - name: Create release + run: | + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=CreateReleaseFromGenericPackageFiles "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|main|Canary ${{ steps.version_info.outputs.build_version }}|**Full Changelog:** [${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}](https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }})" + + - name: Send notification webhook + run: | + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=SendUpdateMessage "${{ steps.version_info.outputs.build_version }}|FF4500|${{ secrets.CANARY_DISCORD_WEBHOOK }}|https://avatars.githubusercontent.com/u/192939710?s=200&v=4|false" + + - name: Notify update server of new builds + run: | + curl 'https://update.ryujinx.app/api/v1/admin/refresh_cache?rc=canary' -X PATCH -H 'accept: */*' -H 'Authorization: ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }}' diff --git a/.github/workflows/debug_release.yml b/.github/workflows/debug_release.yml new file mode 100644 index 000000000..b166adb61 --- /dev/null +++ b/.github/workflows/debug_release.yml @@ -0,0 +1,224 @@ +name: Release job (Debug) + +on: + workflow_dispatch: + inputs: {} + +concurrency: release + +env: + POWERSHELL_TELEMETRY_OPTOUT: 1 + DOTNET_CLI_TELEMETRY_OPTOUT: 1 + RYUJINX_BASE_VERSION: "1.3" + RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release" + RELEASE: 1 + +jobs: + release: + name: Release for ${{ matrix.platform.name }} + runs-on: ${{ matrix.platform.os }} + strategy: + matrix: + platform: + - { name: win-x64, os: windows-latest, zip_os_name: win_x64 } + #- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 } + - { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 } + - { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 } + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-dotnet@v4 + with: + global-json-file: global.json + + - name: Overwrite csc problem matcher + run: echo "::add-matcher::.github/csc.json" + + - name: Get version info + id: version_info + run: | + echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} + 10))" >> $GITHUB_OUTPUT + echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT + echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT + shell: bash + + - name: Configure for release + run: | + sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs + shell: bash + + - name: Create output dir + run: "mkdir release_output" + + - name: Publish + run: | + dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained + + - name: Packing Windows builds + if: matrix.platform.os == 'windows-latest' + run: | + pushd publish + rm libarmeilleure-jitsupport.dylib + 7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish + popd + + gh release download -R GreemDev/GLI -O gli.exe -p 'GitLabCli-win_x64.exe' + + ./gli.exe --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip" + shell: bash + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install GitLabCli + if: matrix.platform.os == 'ubuntu-latest' + run: | + mkdir -p $HOME/.bin + gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64' + chmod +x gli + mv gli $HOME/.bin/ + echo "$HOME/.bin" >> $GITHUB_PATH + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Packing Linux builds + if: matrix.platform.os == 'ubuntu-latest' + run: | + pushd publish + rm libarmeilleure-jitsupport.dylib + chmod +x Ryujinx.sh Ryujinx + tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish + popd + + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz" + shell: bash + + - name: Build AppImage (Linux) + if: matrix.platform.os == 'ubuntu-latest' + run: | + BUILD_VERSION="${{ steps.version_info.outputs.build_version }}" + PLATFORM_NAME="${{ matrix.platform.name }}" + + sudo apt install -y zsync desktop-file-utils appstream + + mkdir -p tools + export PATH="$PATH:$(readlink -f tools)" + + # Setup appimagetool + wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage" + chmod +x tools/appimagetool + chmod +x distribution/linux/appimage/build-appimage.sh + + # Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name) + if [ "$PLATFORM_NAME" = "linux-x64" ]; then + ARCH_NAME=x64 + export ARCH=x86_64 + elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then + ARCH_NAME=arm64 + export ARCH=aarch64 + else + echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME"" + exit 1 + fi + + export UFLAG="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|*-$ARCH_NAME.AppImage.zsync" + BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh + + pushd publish_appimage + mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage + mv Ryujinx.AppImage.zsync ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync + popd + + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage" + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync" + shell: bash + + macos_release: + name: Release MacOS universal + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-dotnet@v4 + with: + global-json-file: global.json + + - name: Setup LLVM 17 + run: | + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh 17 + + - name: Install GitLabCli + run: | + mkdir -p $HOME/.bin + gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64' + chmod +x gli + mv gli $HOME/.bin/ + echo "$HOME/.bin" >> $GITHUB_PATH + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install rcodesign + run: | + mkdir -p $HOME/.bin + gh release download -R indygreg/apple-platform-rs -O apple-codesign.tar.gz -p 'apple-codesign-*-x86_64-unknown-linux-musl.tar.gz' + tar -xzvf apple-codesign.tar.gz --wildcards '*/rcodesign' --strip-components=1 + rm apple-codesign.tar.gz + mv rcodesign $HOME/.bin/ + echo "$HOME/.bin" >> $GITHUB_PATH + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get version info + id: version_info + run: | + echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} + 10))" >> $GITHUB_OUTPUT + echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT + echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT + + - name: Configure for release + run: | + sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs + shell: bash + + - name: Publish macOS Ryujinx + run: | + ./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0 + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|publish/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz" + + create_gitlab_release: + name: Create GitLab Release + runs-on: ubuntu-24.04 + needs: + - macos_release + - release + steps: + - uses: actions/checkout@v4 + + - name: Get version info + id: version_info + run: | + echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} + 10))" >> $GITHUB_OUTPUT + echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT + echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT + shell: bash + + - name: Install GitLabCli + run: | + mkdir -p $HOME/.bin + gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64' + chmod +x gli + mv gli $HOME/.bin/ + echo "$HOME/.bin" >> $GITHUB_PATH + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Create release + run: | + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateReleaseFromGenericPackageFiles "Ryubing|${{ steps.version_info.outputs.build_version }}|${{ steps.version_info.outputs.git_short_hash }}|test|THIS IS NOT INTENDED FOR END USER USAGE" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a0901cfa9..9f2099719 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,57 +11,9 @@ env: DOTNET_CLI_TELEMETRY_OPTOUT: 1 RYUJINX_BASE_VERSION: "1.3" RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release" - RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryubing" - RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO: "Ryujinx" - RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Stable-Releases" RELEASE: 1 jobs: - tag: - name: Create tag - runs-on: ubuntu-24.04 - steps: - - name: Get version info - id: version_info - run: | - echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT - echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT - shell: bash - - - name: Install GitLabCli - run: | - mkdir -p $HOME/.bin - gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64' - chmod +x gli - mv gli $HOME/.bin/ - echo "$HOME/.bin" >> $GITHUB_PATH - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Create GitLab tag - run: gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateTag "${{ steps.version_info.outputs.build_version }}|master" - - - name: Create release - uses: ncipollo/release-action@v1 - with: - name: ${{ steps.version_info.outputs.build_version }} - tag: ${{ steps.version_info.outputs.build_version }} - body: | - # Stable builds: - | Platform | Artifact | - |--|--| - | Windows 64-bit | [Stable Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip) | - | Windows ARM 64-bit | [Stable Windows ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_arm64.zip) | - | Linux 64-bit | [Stable Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) | - | Linux ARM 64-bit | [Stable Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) | - | macOS | [Stable macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) | - - **[Full Changelog](https://git.ryujinx.app/ryubing/ryujinx/-/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }})** - omitBodyDuringUpdate: true - owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }} - repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }} - token: ${{ secrets.RELEASE_TOKEN }} - release: name: Release for ${{ matrix.platform.name }} runs-on: ${{ matrix.platform.os }} @@ -69,7 +21,7 @@ jobs: matrix: platform: - { name: win-x64, os: windows-latest, zip_os_name: win_x64 } - - { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 } + #- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 } - { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 } - { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 } steps: @@ -95,9 +47,6 @@ jobs: sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs shell: bash @@ -115,7 +64,24 @@ jobs: rm libarmeilleure-jitsupport.dylib 7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish popd + + gh release download -R GreemDev/GLI -O gli.exe -p 'GitLabCli-win_x64.exe' + + ./gli.exe --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip" shell: bash + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install GitLabCli + if: matrix.platform.os == 'ubuntu-latest' + run: | + mkdir -p $HOME/.bin + gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64' + chmod +x gli + mv gli $HOME/.bin/ + echo "$HOME/.bin" >> $GITHUB_PATH + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Packing Linux builds if: matrix.platform.os == 'ubuntu-latest' @@ -125,7 +91,11 @@ jobs: chmod +x Ryujinx.sh Ryujinx tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish popd + + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz" shell: bash + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Build AppImage (Linux) if: matrix.platform.os == 'ubuntu-latest' @@ -162,32 +132,11 @@ jobs: mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage mv Ryujinx.AppImage.zsync ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync popd + + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage" + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync" shell: bash - - name: Pushing new release - uses: ncipollo/release-action@v1 - with: - name: ${{ steps.version_info.outputs.build_version }} - artifacts: "release_output/*.tar.gz,release_output/*.zip,release_output/*AppImage*" - tag: ${{ steps.version_info.outputs.build_version }} - body: | - # Stable builds: - | Platform | Artifact | - |--|--| - | Windows 64-bit | [Stable Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip) | - | Windows ARM 64-bit | [Stable Windows ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_arm64.zip) | - | Linux 64-bit | [Stable Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) | - | Linux ARM 64-bit | [Stable Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) | - | macOS | [Stable macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) | - - **[Full Changelog](https://git.ryujinx.app/ryubing/ryujinx/-/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }})** - omitBodyDuringUpdate: true - allowUpdates: true - replacesArtifacts: true - owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }} - repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }} - token: ${{ secrets.RELEASE_TOKEN }} - macos_release: name: Release MacOS universal runs-on: ubuntu-24.04 @@ -203,6 +152,16 @@ jobs: wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh sudo ./llvm.sh 17 + + - name: Install GitLabCli + run: | + mkdir -p $HOME/.bin + gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64' + chmod +x gli + mv gli $HOME/.bin/ + echo "$HOME/.bin" >> $GITHUB_PATH + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Install rcodesign run: | @@ -227,26 +186,49 @@ jobs: sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs shell: bash - name: Publish macOS Ryujinx run: | ./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0 + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|publish/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz" + + create_gitlab_release: + name: Create GitLab Release + runs-on: ubuntu-24.04 + needs: + - macos_release + - release + steps: + - uses: actions/checkout@v4 + + - name: Get version info + id: version_info + run: | + echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT + echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT + echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT + shell: bash - - name: Pushing new release - uses: ncipollo/release-action@v1 - with: - name: ${{ steps.version_info.outputs.build_version }} - artifacts: "publish/*.tar.gz" - tag: ${{ steps.version_info.outputs.build_version }} - body: "" - omitBodyDuringUpdate: true - allowUpdates: true - replacesArtifacts: true - owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }} - repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }} - token: ${{ secrets.RELEASE_TOKEN }} + - name: Install GitLabCli + run: | + mkdir -p $HOME/.bin + gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64' + chmod +x gli + mv gli $HOME/.bin/ + echo "$HOME/.bin" >> $GITHUB_PATH + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Create release + run: | + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateReleaseFromGenericPackageFiles "Ryubing|${{ steps.version_info.outputs.build_version }}|${{ steps.version_info.outputs.git_short_hash }}|${{ steps.version_info.outputs.build_version }}|msd:${{ steps.version_info.outputs.build_version }}" + + - name: Send notification webhook + run: | + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=SendUpdateMessage "${{ steps.version_info.outputs.build_version }}|32cd32|${{ secrets.STABLE_DISCORD_WEBHOOK }}|https://avatars.githubusercontent.com/u/192939710?s=200&v=4|false" + + - name: Notify update server of new builds + run: | + curl 'https://update.ryujinx.app/api/v1/admin/refresh_cache?rc=stable' -X PATCH -H 'accept: */*' -H 'Authorization: ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }}' diff --git a/BuildAndPushLibraries.sh b/BuildAndPushLibraries.sh new file mode 100644 index 000000000..4bd6cfc55 --- /dev/null +++ b/BuildAndPushLibraries.sh @@ -0,0 +1,18 @@ +function pub { + dotnet publish -c release +} + +function package { + cd src/$1 + pub + mv bin/Release/$1.1.0.0.nupkg ../../pkgs/$1.1.0.0.nupkg + cd ../../ +} + +rm -rf pkgs +mkdir pkgs + +package ARMeilleure +package Ryujinx.Memory + +dotnet nuget push pkgs/*.nupkg --source RyubingPkgs \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index dd0f2ccfa..9a2b4ccb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,18 +2,17 @@ All updates to this Ryujinx branch will be documented in this file. +## [1.3.2]() - 2025-06-09 -## [1.2.86]() - 2025-03-13 -A list of notable changes can be found on the release linked in the version number above. +## [1.3.1]() - 2025-04-23 + +## [1.2.86]() - 2025-03-13 ## [1.2.82]() - 2025-02-16 -A list of notable changes can be found on the release linked in the version number above. ## [1.2.80-81]() - 2025-01-22 -A list of notable changes can be found on the release linked in the version number above. ## [1.2.78]() - 2024-12-19 -A list of notable changes can be found on the release linked in the version number above. ## [1.2.73-1.2.76]() - 2024-11-19 A list of notable changes can be found on the release linked in the version number above. @@ -252,4 +251,4 @@ Added Low-power PPTC mode strings to the translation files. - Autoload DLC/Updates from dir ([#12](https://github.com/GreemDev/Ryujinx/pull/12)). - Changed executable icon to rainbow logo. - Extract Data > Logo now also extracts the square thumbnail you see for the game in the UI. -- The "use random UUID hack" checkbox in the Amiibo screen now remembers its last state when you reopen the window in a given session. \ No newline at end of file +- The "use random UUID hack" checkbox in the Amiibo screen now remembers its last state when you reopen the window in a given session. diff --git a/Directory.Packages.props b/Directory.Packages.props index adf48c1de..602295d15 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -23,7 +23,6 @@ - @@ -41,7 +40,10 @@ + + + diff --git a/README.md b/README.md index a02a100e8..a9e04ccf6 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@ # Ryujinx -[![Latest release](https://img.shields.io/github/v/release/Ryubing/Stable-Releases?label=stable)](https://github.com/Ryubing/Stable-Releases/releases/latest) -[![Latest canary release](https://img.shields.io/github/v/release/Ryubing/Canary-Releases?label=canary)](https://github.com/Ryubing/Canary-Releases/releases/latest) +[![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://git.ryujinx.app/ryubing/canary/-/releases)
Discord @@ -31,7 +31,7 @@
This is not a Ryujinx revival project. This is not a Phoenix project.
- Guides and documentation can be found on the
Wiki tab. + Guides and documentation can be found on the Wiki tab.

@@ -49,13 +49,13 @@ Stable builds are made every so often, based on the `master` branch, that then g These stable builds exist so that the end user can get a more **enjoyable and stable experience**. They are released every month or so, to ensure consistent updates, while not being an annoying amount of individual updates to download over the course of that month. -You can find the latest stable release [here](https://github.com/Ryubing/Stable-Releases/releases/latest). +You can find the stable releases [here](https://git.ryujinx.app/ryubing/ryujinx/-/releases). Canary builds are compiled automatically for each commit on the `master` branch. While we strive to ensure optimal stability and performance prior to pushing an update, these builds **may be unstable or completely broken**. These canary builds are only recommended for experienced users. -You can find the latest canary release [here](https://github.com/Ryubing/Canary-Releases/releases/latest). +You can find the canary releases [here](https://git.ryujinx.app/ryubing/canary/-/releases). ## Documentation @@ -111,7 +111,7 @@ See [LICENSE.txt](LICENSE.txt) and [THIRDPARTY.md](distribution/legal/THIRDPARTY ## Credits -- [LibHac](https://github.com/Thealexbarney/LibHac) is used for our file-system. +- [LibHac](https://git.ryujinx.app/ryubing/libhac) is used for our file-system. - [AmiiboAPI](https://www.amiiboapi.com) is used in our Amiibo emulation. - [ldn_mitm](https://github.com/spacemeowx2/ldn_mitm) is used for one of our available multiplayer modes. -- [ShellLink](https://github.com/securifybv/ShellLink) is used for Windows shortcut generation. +- [ShellLink](https://github.com/securifybv/ShellLink) is used for Windows shortcut generation. \ No newline at end of file diff --git a/Ryujinx.sln b/Ryujinx.sln index 9ed282d09..4babf3fb9 100644 --- a/Ryujinx.sln +++ b/Ryujinx.sln @@ -77,6 +77,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Gene EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}" 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}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig @@ -84,10 +86,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .github\workflows\canary.yml = .github\workflows\canary.yml Directory.Packages.props = Directory.Packages.props .github\workflows\release.yml = .github\workflows\release.yml + nuget.config = nuget.config EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.BuildValidationTasks", "src\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj", "{4A89A234-4F19-497D-A576-DDE8CDFC5B22}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/assets/locales.json b/assets/locales.json index e6add8d2a..3a3b4b60b 100644 --- a/assets/locales.json +++ b/assets/locales.json @@ -30,7 +30,7 @@ "el_GR": "Ελληνικά", "en_US": "English (US)", "es_ES": "Español (ES)", - "fr_FR": "Français", + "fr_FR": "Français (FR)", "he_IL": "עִברִית", "it_IT": "Italiano", "ja_JP": "日本語", @@ -55,7 +55,7 @@ "el_GR": "Άνοιγμα Applet", "en_US": "Open Applet", "es_ES": "Abrir applet", - "fr_FR": "Ouvrir un programme", + "fr_FR": "Ouvrir une applet", "he_IL": "פתח יישומון", "it_IT": "Apri applet", "ja_JP": "アプレットを開く", @@ -105,7 +105,7 @@ "el_GR": "Άνοιγμα του Mii Editor Applet σε Αυτόνομη λειτουργία", "en_US": "Open Mii Editor Applet in Standalone mode", "es_ES": "Abre el editor de Mii en modo autónomo", - "fr_FR": "Ouvrir l'éditeur Mii en mode Standalone", + "fr_FR": "Ouvrir l’applet Éditeur Mii en mode autonome", "he_IL": "פתח את יישומון עורך ה- Mii במצב עצמאי", "it_IT": "Apri l'applet Editor Mii in modalità Standalone", "ja_JP": "スタンドアロンモードで Mii エディタアプレットを開きます", @@ -187,7 +187,7 @@ "ko_KR": "소프트웨어", "no_NO": "Programvare", "pl_PL": "Oprogramowanie", - "pt_BR": "", + "pt_BR": "Programa", "ru_RU": "Программное обеспечение", "sv_SE": "Programvara", "th_TH": "ซอฟต์แวร์", @@ -305,7 +305,7 @@ "el_GR": "_Φόρτωση Αρχείου Εφαρμογής", "en_US": "_Load Application From File", "es_ES": "_Cargar aplicación desde un archivo", - "fr_FR": "_Charger un jeu depuis un fichier", + "fr_FR": "_Charger une application à partir d’un fichier", "he_IL": "_טען יישום מקובץ", "it_IT": "_Carica applicazione da un file", "ja_JP": "ファイルからアプリケーションをロード(_L)", @@ -330,7 +330,7 @@ "el_GR": "", "en_US": "No applications found in selected file.", "es_ES": "No se encontraron aplicaciones en el archivo seleccionado.", - "fr_FR": "Aucun jeu trouvé dans le fichier sélectionné", + "fr_FR": "Aucune application trouvée dans le fichier sélectionné.", "he_IL": "", "it_IT": "Nessuna applicazione trovata nel file selezionato.", "ja_JP": "", @@ -355,7 +355,7 @@ "el_GR": "Φόρτωση Απακετάριστου _Παιχνιδιού", "en_US": "Load _Unpacked Game", "es_ES": "Cargar juego _desempaquetado", - "fr_FR": "Charger un jeu extrait", + "fr_FR": "Charger un jeu décompressé", "he_IL": "טען משחק _שאינו ארוז", "it_IT": "Carica _gioco estratto", "ja_JP": "展開されたゲームをロード", @@ -380,7 +380,7 @@ "el_GR": "", "en_US": "Load DLC From Folder", "es_ES": "Cargar DLC Desde Carpeta", - "fr_FR": "Charger les DLC depuis le dossier des DLC", + "fr_FR": "Charger les DLC à partir d’un dossier", "he_IL": "", "it_IT": "Carica DLC da una cartella", "ja_JP": "", @@ -405,7 +405,7 @@ "el_GR": "", "en_US": "Load Title Updates From Folder", "es_ES": "Cargar Actualizaciones de Títulos Desde Carpeta", - "fr_FR": "Charger les mises à jour depuis le dossier des mises à jour", + "fr_FR": "Charger les mises à jour du titre à partir d’un dossier", "he_IL": "", "it_IT": "Carica aggiornamenti da una cartella", "ja_JP": "", @@ -455,7 +455,7 @@ "el_GR": "", "en_US": "Open Screenshots Folder", "es_ES": "", - "fr_FR": "", + "fr_FR": "Ouvrir le dossier des captures d’écran", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -580,7 +580,7 @@ "el_GR": "Εκκίνηση Παιχνιδιών σε Πλήρη Οθόνη", "en_US": "Start Games in Fullscreen Mode", "es_ES": "Iniciar juegos en pantalla completa", - "fr_FR": "Démarrer le jeu en plein écran", + "fr_FR": "Démarrer les jeux en mode plein écran", "he_IL": "התחל משחקים במסך מלא", "it_IT": "Avvia i giochi a schermo intero", "ja_JP": "全画面モードでゲームを開始", @@ -605,7 +605,7 @@ "el_GR": "", "en_US": "Start Games with UI Hidden", "es_ES": "", - "fr_FR": "", + "fr_FR": "Démarrer les jeux avec l’interface cachée", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -680,7 +680,7 @@ "el_GR": "Διαχείριση Προφίλ _Χρηστών", "en_US": "_Manage User Profiles", "es_ES": "_Gestionar perfiles de usuario", - "fr_FR": "_Gérer les profils d'utilisateurs", + "fr_FR": "_Gérer les profils utilisateur", "he_IL": "_נהל פרופילי משתמש", "it_IT": "_Gestisci i profili utente", "ja_JP": "ユーザプロファイルを管理(_M)", @@ -855,7 +855,7 @@ "el_GR": "Εγκατάσταση Firmware από τοποθεσία", "en_US": "Install a firmware from a directory", "es_ES": "Instalar firmware desde una carpeta", - "fr_FR": "Installer un firmware depuis un dossier", + "fr_FR": "Installer un firmware à partir d’un dossier", "he_IL": "התקן קושחה מתוך תקייה", "it_IT": "Installa un firmware da una cartella", "ja_JP": "ディレクトリからファームウェアをインストール", @@ -905,7 +905,7 @@ "el_GR": "", "en_US": "Install keys from KEYS or ZIP", "es_ES": "Instalar keys de KEYS o ZIP", - "fr_FR": "Installer des clés à partir de .KEYS or .ZIP", + "fr_FR": "Installer des clés à partir de .KEYS ou .ZIP", "he_IL": "", "it_IT": "Installa chiavi da file KEYS o ZIP", "ja_JP": "", @@ -980,7 +980,7 @@ "el_GR": "Εγκαταστήσετε τύπους αρχείων.", "en_US": "Install file types", "es_ES": "Instalar tipos de archivo", - "fr_FR": "Installer les types de fichiers", + "fr_FR": "Installer des types de fichiers", "he_IL": "סוגי קבצי התקנה", "it_IT": "Installa i tipi di file", "ja_JP": "ファイル形式をインストール", @@ -1005,7 +1005,7 @@ "el_GR": "Απεγκαταστήσετε τύπους αρχείων", "en_US": "Uninstall file types", "es_ES": "Desinstalar tipos de archivo", - "fr_FR": "Désinstaller les types de fichiers", + "fr_FR": "Désinstaller des types de fichiers", "he_IL": "סוגי קבצי הסרה", "it_IT": "Disinstalla i tipi di file", "ja_JP": "ファイル形式をアンインストール", @@ -1280,7 +1280,7 @@ "el_GR": "", "en_US": "FAQ & Troubleshooting Page", "es_ES": "", - "fr_FR": "Page de FAQ et de dépannage", + "fr_FR": "FAQ et Dépannage", "he_IL": "", "it_IT": "Domande frequenti e risoluzione dei problemi", "ja_JP": "", @@ -1305,7 +1305,7 @@ "el_GR": "", "en_US": "Opens the FAQ and Troubleshooting page on the official Ryujinx wiki", "es_ES": "", - "fr_FR": "Ouvre la page de FAQ et de dépannage sur le wiki officiel de Ryujinx", + "fr_FR": "Ouvre la page FAQ et Dépannage sur le wiki officiel de Ryujinx", "he_IL": "", "it_IT": "Apre la pagina della wiki ufficiale di Ryujinx relativa alle domande frequenti e alla risoluzione dei problemi", "ja_JP": "", @@ -1555,7 +1555,7 @@ "el_GR": "", "en_US": "Developed by {0}", "es_ES": "", - "fr_FR": "", + "fr_FR": "Développé par {0}", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -1655,7 +1655,7 @@ "el_GR": "Κατάληξη: {0}", "en_US": "Extension: {0}", "es_ES": "Extensión: {0}", - "fr_FR": "Extension du Fichier: {0}", + "fr_FR": "Extension du fichier: {0}", "he_IL": "", "it_IT": "Estensione: {0}", "ja_JP": "ファイル拡張子: {0}", @@ -1680,7 +1680,7 @@ "el_GR": "Μέγεθος Αρχείου: {0}", "en_US": "File Size: {0}", "es_ES": "Tamaño del archivo: {0}", - "fr_FR": "Taille du Fichier: {0}", + "fr_FR": "Taille du fichier: {0}", "he_IL": "", "it_IT": "Dimensione file: {0}", "ja_JP": "ファイルサイズ: {0}", @@ -1780,7 +1780,7 @@ "el_GR": "Κατάληξη", "en_US": "File Ext", "es_ES": "Extensión", - "fr_FR": "Extension du Fichier", + "fr_FR": "Extension du fichier", "he_IL": "סיומת קובץ", "it_IT": "Estensione", "ja_JP": "ファイル拡張子", @@ -1805,7 +1805,7 @@ "el_GR": "Μέγεθος Αρχείου", "en_US": "File Size", "es_ES": "Tamaño del archivo", - "fr_FR": "Taille du Fichier", + "fr_FR": "Taille du fichier", "he_IL": "גודל הקובץ", "it_IT": "Dimensione file", "ja_JP": "ファイルサイズ", @@ -1847,6 +1847,131 @@ "zh_TW": "路徑" } }, + { + "ID": "GameListSortStatusNameAscending", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "Όνομα: A-Z", + "en_US": "Title: A-Z", + "es_ES": "Título: A-Z", + "fr_FR": "Titre : A-Z", + "he_IL": "", + "it_IT": "Titolo: A-Z", + "ja_JP": "タイトル:A-Z", + "ko_KR": "제목: A-Z", + "no_NO": "Tittel: A-Z", + "pl_PL": "Tytuł: A-Z", + "pt_BR": "Título: A-Z", + "ru_RU": "Название: А-Z", + "sv_SE": "Titel: A-Z", + "th_TH": "ชื่อเรื่อง: A-Z", + "tr_TR": "Başlık: A-Z", + "uk_UA": "Назва: A-Z", + "zh_CN": "标题:A-Z", + "zh_TW": "標題:A-Z" + } + }, + { + "ID": "GameListSortStatusNameDescending", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "Τίτλος: Z-A", + "en_US": "Title: Z-A", + "es_ES": "Título: Z-A", + "fr_FR": "Titre : Z-A", + "he_IL": "", + "it_IT": "Titolo: Z-A", + "ja_JP": "タイトル:Z-A", + "ko_KR": "제목: Z-A", + "no_NO": "Tittel: Z-A", + "pl_PL": "Tytuł: Z-A", + "pt_BR": "Título: Z-A", + "ru_RU": "Название: Z-A", + "sv_SE": "Titel: Z-A", + "th_TH": "ชื่อเรื่อง: Z-A", + "tr_TR": "Başlık: Z-A", + "uk_UA": "Назва: Z-A", + "zh_CN": "标题:Z-A", + "zh_TW": "標題:Z-A" + } + }, + { + "ID": "GameListSortStatusDisable", + "Translations": { + "ar_SA": "", + "de_DE": "Status: Deaktiviert", + "el_GR": "Κατάσταση: Απενεργοποιημένο", + "en_US": "Status: Disabled", + "es_ES": "Estado: Desactivado", + "fr_FR": "Statut : Désactivé", + "he_IL": "", + "it_IT": "Stato: Disabilitato", + "ja_JP": "ステータス:無効", + "ko_KR": "상태: 비활성화됨", + "no_NO": "Status: Deaktivert", + "pl_PL": "Status: Wyłączony", + "pt_BR": "Status: Desativado", + "ru_RU": "Статус: Отключено", + "sv_SE": "Status: Inaktiverad", + "th_TH": "", + "tr_TR": "Durum: Devre Dışı", + "uk_UA": "Статус: Вимкнено", + "zh_CN": "状态:禁用", + "zh_TW": "狀態:停用" + } + }, + { + "ID": "GameListSortStatusAscending", + "Translations": { + "ar_SA": "الحالة: تصاعدي", + "de_DE": "Status: Aufsteigend", + "el_GR": "Κατάσταση: Αναγόμενη", + "en_US": "Status: Ascending", + "es_ES": "", + "fr_FR": "Statut : Croissant", + "he_IL": "סטטוס: עולה", + "it_IT": "Stato: Crescente", + "ja_JP": "ステータス:昇順", + "ko_KR": "상태: 오름차순", + "no_NO": "Status: Stigende", + "pl_PL": "Stan: Rosnący", + "pt_BR": "Status: Crescente", + "ru_RU": "Статус: По возрастанию", + "sv_SE": "Status: Stigande", + "th_TH": "สถานะ: เพิ่มขึ้น", + "tr_TR": "Durum: Artan", + "uk_UA": "Статус: Зростання", + "zh_CN": "状态:升序", + "zh_TW": "狀態:遞增" + } + }, + { + "ID": "GameListSortStatusDescending", + "Translations": { + "ar_SA": "الحالة: تنازلي", + "de_DE": "Status: Absteigend", + "el_GR": "Κατάσταση: Καθοδική", + "en_US": "Status: Descending", + "es_ES": "", + "fr_FR": "Statut : Décroissant", + "he_IL": "סטטוס: יורד", + "it_IT": "Stato: Decrescente", + "ja_JP": "ステータス:降順", + "ko_KR": "상태: 내림차순", + "no_NO": "Status: Synkende", + "pl_PL": "Stan: Malejący", + "pt_BR": "Status: Decrescente", + "ru_RU": "Статус: По Убыванию", + "sv_SE": "Status: Fallande", + "th_TH": "สถานะ: ลดลง", + "tr_TR": "Durum: Azalan", + "uk_UA": "Статус: Зменшення", + "zh_CN": "状态:降序", + "zh_TW": "狀態:遞減" + } + }, { "ID": "GameListHeaderCompatibilityStatus", "Translations": { @@ -1855,7 +1980,7 @@ "el_GR": "", "en_US": "Compatibility:", "es_ES": "", - "fr_FR": "", + "fr_FR": "Compatibilité :", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -1880,7 +2005,7 @@ "el_GR": "", "en_US": "Title ID:", "es_ES": "", - "fr_FR": "", + "fr_FR": "ID du titre :", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -1905,7 +2030,7 @@ "el_GR": "", "en_US": "Hosted Games: {0}", "es_ES": "", - "fr_FR": "", + "fr_FR": "Jeux hébergés : {0}", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -1930,7 +2055,7 @@ "el_GR": "", "en_US": "Online Players: {0}", "es_ES": "", - "fr_FR": "", + "fr_FR": "Joueurs en ligne : {0}", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -1947,6 +2072,31 @@ "zh_TW": "LDN 上在線的玩家數量: {0}" } }, + { + "ID": "GameListLabelTotalTimePlayed", + "Translations": { + "ar_SA": "", + "de_DE": "Gesamte Spielzeit: {0}", + "el_GR": "Συνολικός χρόνος παιχνιδιού: {0}", + "en_US": "Total Play Time: {0}", + "es_ES": "Tiempo total de juego: {0}", + "fr_FR": "Temps de jeu total: {0}", + "he_IL": "", + "it_IT": "Tempo totale di gioco: {0}", + "ja_JP": "", + "ko_KR": "총 플레이 시간 : {0}", + "no_NO": "", + "pl_PL": "Całkowity czas gry: {0}", + "pt_BR": "Tempo total de jogo: {0}", + "ru_RU": "", + "sv_SE": "Total speltid: {0}", + "th_TH": "", + "tr_TR": "Toplam Oyun Süresi: {0}", + "uk_UA": "", + "zh_CN": "总游戏时间: {0}", + "zh_TW": "總遊戲時間: {0}" + } + }, { "ID": "GameListContextMenuOpenUserSaveDirectory", "Translations": { @@ -1980,7 +2130,7 @@ "el_GR": "Ανοίγει την τοποθεσία που περιέχει την Αποθήκευση Χρήστη της εφαρμογής", "en_US": "Opens the directory which contains Application's User Save", "es_ES": "Abre la carpeta que contiene la partida guardada del usuario para esta aplicación", - "fr_FR": "Ouvre le dossier contenant la sauvegarde utilisateur du jeu", + "fr_FR": "Ouvre le dossier contenant la sauvegarde utilisateur de l’application", "he_IL": "פותח את תקיית השמור של המשתמש ביישום הנוכחי", "it_IT": "Apre la cartella che contiene i dati di salvataggio dell'utente", "ja_JP": "アプリケーションのユーザセーブデータを格納するディレクトリを開きます", @@ -2005,7 +2155,7 @@ "el_GR": "Άνοιγμα Τοποθεσίας Συσκευής Χρήστη", "en_US": "Open Device Save Directory", "es_ES": "Abrir carpeta de guardado del sistema para el usuario actual", - "fr_FR": "Ouvrir le dossier de sauvegarde console", + "fr_FR": "Ouvrir le dossier de sauvegarde de l’appareil", "he_IL": "פתח את תקיית השמור של המכשיר", "it_IT": "Apri la cartella dei salvataggi del dispositivo", "ja_JP": "デバイスディレクトリを開く", @@ -2030,7 +2180,7 @@ "el_GR": "Ανοίγει την τοποθεσία που περιέχει την Αποθήκευση Συσκευής της εφαρμογής", "en_US": "Opens the directory which contains Application's Device Save", "es_ES": "Abre la carpeta que contiene la partida guardada del sistema para esta aplicación", - "fr_FR": "Ouvre le dossier contenant la sauvegarde console du jeu", + "fr_FR": "Ouvre le dossier contenant la sauvegarde locale de l’application", "he_IL": "פותח את הספרייה המכילה את שמור המכשיר של היישום", "it_IT": "Apre la cartella che contiene i dati di salvataggio del dispositivo", "ja_JP": "アプリケーションのデバイスセーブデータを格納するディレクトリを開きます", @@ -2080,7 +2230,7 @@ "el_GR": "Ανοίγει την τοποθεσία που περιέχει την Αποθήκευση BCAT της εφαρμογής", "en_US": "Opens the directory which contains Application's BCAT Save", "es_ES": "Abrir la carpeta que contiene el guardado BCAT de esta aplicación", - "fr_FR": "Ouvre le dossier contenant la sauvegarde BCAT du jeu", + "fr_FR": "Ouvre le dossier contenant la sauvegarde BCAT de l’application", "he_IL": "פותח את תקיית שמור ה-BCAT של היישום", "it_IT": "Apre la cartella che contiene il salvataggio BCAT dell'applicazione", "ja_JP": "アプリケーションの BCAT セーブデータを格納するディレクトリを開きます", @@ -2105,7 +2255,7 @@ "el_GR": "Διαχείριση Ενημερώσεων Παιχνιδιού", "en_US": "Manage Title Updates", "es_ES": "Gestionar actualizaciones del juego", - "fr_FR": "Gérer les mises à jour", + "fr_FR": "Gérer les mises à jour du titre", "he_IL": "מנהל עדכוני משחקים", "it_IT": "Gestisci aggiornamenti del gioco", "ja_JP": "アップデートを管理", @@ -2130,7 +2280,7 @@ "el_GR": "Ανοίγει το παράθυρο διαχείρισης Ενημερώσεων Παιχνιδιού", "en_US": "Opens the Title Update management window", "es_ES": "Abrir la ventana de gestión de actualizaciones de esta aplicación", - "fr_FR": "Ouvre la fenêtre de gestion des mises à jour du jeu", + "fr_FR": "Ouvre la fenêtre de gestion des mises à jour du titre", "he_IL": "פותח את חלון מנהל עדכוני המשחקים", "it_IT": "Apre la finestra di gestione aggiornamenti del gioco", "ja_JP": "タイトルのアップデート管理ウインドウを開きます", @@ -2230,7 +2380,7 @@ "el_GR": "Εκκαθάριση Προσωρινής Μνήμης PPTC", "en_US": "Queue PPTC Rebuild", "es_ES": "Reconstruir PPTC en cola", - "fr_FR": "Reconstruction du PPTC", + "fr_FR": "Reconstruire le cache PPTC", "he_IL": "הוסף PPTC לתור בנייה מחדש", "it_IT": "Accoda rigenerazione della cache PPTC", "ja_JP": "PPTC を再構築", @@ -2255,7 +2405,7 @@ "el_GR": "Διαγράφει την προσωρινή μνήμη PPTC της εφαρμογής", "en_US": "Trigger PPTC to rebuild at boot time on the next game launch", "es_ES": "Elimina la caché de PPTC de esta aplicación", - "fr_FR": "Effectuer une reconstruction du PPTC au prochain démarrage du jeu", + "fr_FR": "Déclencher la reconstruction du cache PPTC au prochain démarrage du jeu", "he_IL": "גרום ל-PPTC להבנות מחדש בפתיחה הבאה של המשחק", "it_IT": "Esegue la rigenerazione della cache PPTC al prossimo avvio del gioco", "ja_JP": "次回のゲーム起動時に PPTC を再構築します", @@ -2280,7 +2430,7 @@ "el_GR": "", "en_US": "Purge PPTC cache", "es_ES": "", - "fr_FR": "", + "fr_FR": "Purger le cache PPTC", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -2305,7 +2455,7 @@ "el_GR": "", "en_US": "Deletes all PPTC cache files for the Application", "es_ES": "", - "fr_FR": "", + "fr_FR": "Supprime tous les fichiers de cache PPTC de l’application", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -2330,7 +2480,7 @@ "el_GR": "Εκκαθάριση Προσωρινής Μνήμης Shader", "en_US": "Purge Shader Cache", "es_ES": "Limpiar caché de sombreadores", - "fr_FR": "Purger les shaders", + "fr_FR": "Purger le cache des shaders", "he_IL": "ניקוי מטמון הצללות", "it_IT": "Elimina la cache degli shader", "ja_JP": "シェーダーキャッシュを破棄", @@ -2355,7 +2505,7 @@ "el_GR": "Διαγράφει την προσωρινή μνήμη Shader της εφαρμογής", "en_US": "Deletes Application's shader cache", "es_ES": "Eliminar la caché de sombreadores de esta aplicación", - "fr_FR": "Supprime les shaders du jeu", + "fr_FR": "Supprime le cache des shaders de l’application", "he_IL": "מוחק את מטמון ההצללות של היישום", "it_IT": "Elimina la cache degli shader dell'applicazione", "ja_JP": "アプリケーションのシェーダーキャッシュを破棄します", @@ -2380,14 +2530,14 @@ "el_GR": "Άνοιγμα Τοποθεσίας PPTC", "en_US": "Open PPTC Directory", "es_ES": "Abrir carpeta de PPTC", - "fr_FR": "Ouvrir le dossier du PPTC", + "fr_FR": "Ouvrir le dossier PPTC", "he_IL": "פתח את תקיית PPTC", "it_IT": "Apri la cartella della cache PPTC", "ja_JP": "PPTC ディレクトリを開く", "ko_KR": "PPTC 디렉터리 열기", "no_NO": "Åpne PPTC mappe", "pl_PL": "Otwórz katalog PPTC", - "pt_BR": "Abrir Diretório de PPTC Cache", + "pt_BR": "Abrir Diretório de Cache PPTC", "ru_RU": "Открыть папку PPTC", "sv_SE": "Öppna PPTC-katalog", "th_TH": "เปิดไดเรกทอรี่ PPTC", @@ -2405,7 +2555,7 @@ "el_GR": "Ανοίγει την τοποθεσία που περιέχει τη προσωρινή μνήμη PPTC της εφαρμογής", "en_US": "Opens the directory which contains Application's PPTC cache", "es_ES": "Abrir la carpeta que contiene la caché de PPTC de esta aplicación", - "fr_FR": "Ouvre le dossier contenant le PPTC du jeu", + "fr_FR": "Ouvre le dossier contenant le cache PPTC de l’application", "he_IL": "פותח את התקייה של מטמון ה-PPTC של האפליקציה", "it_IT": "Apre la cartella che contiene la cache PPTC dell'applicazione", "ja_JP": "アプリケーションの PPTC キャッシュを格納するディレクトリを開きます", @@ -2430,7 +2580,7 @@ "el_GR": "Άνοιγμα τοποθεσίας προσωρινής μνήμης Shader", "en_US": "Open Shader Cache Directory", "es_ES": "Abrir carpeta de caché de sombreadores", - "fr_FR": "Ouvrir le dossier des shaders", + "fr_FR": "Ouvrir le dossier du cache des shaders", "he_IL": "פתח את תקיית המטמון של ההצללות", "it_IT": "Apri la cartella della cache degli shader", "ja_JP": "シェーダーキャッシュディレクトリを開く", @@ -2455,7 +2605,7 @@ "el_GR": "Ανοίγει την τοποθεσία που περιέχει την προσωρινή μνήμη Shader της εφαρμογής", "en_US": "Opens the directory which contains Application's shader cache", "es_ES": "Abrir la carpeta que contiene la caché de sombreadores de esta aplicación", - "fr_FR": "Ouvre le dossier contenant les shaders du jeu", + "fr_FR": "Ouvre le dossier contenant le cache des shaders de l’application", "he_IL": "פותח את תקיית מטמון ההצללות של היישום", "it_IT": "Apre la cartella che contiene la cache degli shader dell'applicazione", "ja_JP": "アプリケーションのシェーダーキャッシュを格納するディレクトリを開きます", @@ -2530,7 +2680,7 @@ "el_GR": "Εξαγωγή της ενότητας ExeFS από την τρέχουσα διαμόρφωση της εφαρμογής (συμπεριλαμβανομένου ενημερώσεων)", "en_US": "Extract the ExeFS section from Application's current config (including updates)", "es_ES": "Extraer la sección ExeFS de la configuración actual de la aplicación (incluyendo actualizaciones)", - "fr_FR": "Extrait la section ExeFS du jeu (mise à jour incluse)", + "fr_FR": "Extraire la section ExeFS de la configuration actuelle de l’application (mises à jour incluses)", "he_IL": "חלץ את קטע ה-ExeFS מתצורת היישום הנוכחית (כולל עדכונים)", "it_IT": "Estrae la sezione ExeFS dall'attuale configurazione dell'applicazione (inclusi gli aggiornamenti)", "ja_JP": "現在のアプリケーション設定(アップデート含む)から ExeFS セクションを展開します", @@ -2580,7 +2730,7 @@ "el_GR": "Εξαγωγή της ενότητας RomFS από την τρέχουσα διαμόρφωση της εφαρμογής (συμπεριλαμβανομένου ενημερώσεων)", "en_US": "Extract the RomFS section from Application's current config (including updates)", "es_ES": "Extraer la sección RomFS de la configuración actual de la aplicación (incluyendo actualizaciones)", - "fr_FR": "Extrait la section RomFS du jeu (mise à jour incluse)", + "fr_FR": "Extraire la section RomFS de la configuration actuelle de l’application (mises à jour incluses)", "he_IL": "חלץ את קטע ה-RomFS מתצורת היישום הנוכחית (כולל עדכונים)", "it_IT": "Estrae la sezione RomFS dall'attuale configurazione dell'applicazione (inclusi gli aggiornamenti)", "ja_JP": "現在のアプリケーション設定(アップデート含む)から RomFS セクションを展開します", @@ -2605,7 +2755,7 @@ "el_GR": "", "en_US": "DLC RomFS", "es_ES": "", - "fr_FR": "RomFS de DLC", + "fr_FR": "RomFS du DLC", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -2630,7 +2780,7 @@ "el_GR": "", "en_US": "Extract the RomFS from a selected DLC file", "es_ES": "", - "fr_FR": "Extraire les RomFS d'un fichier DLC choisi", + "fr_FR": "Extraire la RomFS du fichier DLC sélectionné", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -2680,7 +2830,7 @@ "el_GR": "Εξαγωγή της ενότητας Logo από την τρέχουσα διαμόρφωση της εφαρμογής (συμπεριλαμβανομένου ενημερώσεων)", "en_US": "Extract the Logo section from Application's current config (including updates)", "es_ES": "Extraer la sección Logo de la configuración actual de la aplicación (incluyendo actualizaciones)", - "fr_FR": "Extrait la section Logo du jeu (mise à jour incluse)", + "fr_FR": "Extraire la section Logo de la configuration actuelle de l’application (mises à jour incluses)", "he_IL": "חלץ את קטע ה-Logo מתצורת היישום הנוכחית (כולל עדכונים)", "it_IT": "Estrae la sezione Logo dall'attuale configurazione dell'applicazione (inclusi gli aggiornamenti)", "ja_JP": "現在のアプリケーション設定(アップデート含む)からロゴセクションを展開します", @@ -2705,7 +2855,7 @@ "el_GR": "Δημιουργία Συντόμευσης Εφαρμογής", "en_US": "Create Application Shortcut", "es_ES": "Crear acceso directo de aplicación", - "fr_FR": "Créer un raccourci", + "fr_FR": "Créer un raccourci de l’application", "he_IL": "ליצור קיצור דרך לאפליקציה", "it_IT": "Crea collegamento", "ja_JP": "アプリケーションのショートカットを作成", @@ -2730,7 +2880,7 @@ "el_GR": "Δημιουργία συντόμευσης επιφάνειας εργασίας που ανοίγει την επιλεγμένη εφαρμογή", "en_US": "Create a Desktop Shortcut that launches the selected Application", "es_ES": "Crear un acceso directo en el escritorio que lance la aplicación seleccionada", - "fr_FR": "Créer un raccourci sur le bureau qui lance le jeu sélectionné", + "fr_FR": "Créer un raccourci sur le bureau qui lance l’application sélectionnée", "he_IL": "ליצור קיצור דרך בשולחן העבודה שיפתח את אפליקציה זו", "it_IT": "Crea un collegamento sul desktop che avvia l'applicazione selezionata", "ja_JP": "選択したアプリケーションを起動するデスクトップショートカットを作成します", @@ -2755,14 +2905,14 @@ "el_GR": "", "en_US": "Create Custom Configuration", "es_ES": "", - "fr_FR": "", + "fr_FR": "Créer une configuration personnalisée", "he_IL": "", "it_IT": "", "ja_JP": "", "ko_KR": "사용자 정의 구성 만들기", "no_NO": "Opprett egendefinert konfigurasjon", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Criar Configuração Custumizada", "ru_RU": "Задать индивидуальные параметры", "sv_SE": "Skapa anpassad konfiguration", "th_TH": "", @@ -2780,14 +2930,14 @@ "el_GR": "", "en_US": "Edit Custom Configuration", "es_ES": "", - "fr_FR": "", + "fr_FR": "Modifier la configuration personnalisée", "he_IL": "", "it_IT": "", "ja_JP": "", "ko_KR": "사용자 정의 구성 편집", "no_NO": "Rediger egendefinert konfigurasjon", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Editar Configuração Customizada", "ru_RU": "Изменить индивидуальные параметры", "sv_SE": "Redigera anpassad konfiguration", "th_TH": "", @@ -2805,7 +2955,7 @@ "el_GR": "", "en_US": "Create a shortcut in macOS's Applications folder that launches the selected Application", "es_ES": "Crea un acceso directo en la carpeta de Aplicaciones de macOS que inicie la Aplicación seleccionada", - "fr_FR": "Créer un raccourci dans le dossier Applications de macOS qui lance le jeu sélectionné", + "fr_FR": "Créer un raccourci dans le dossier Applications de macOS qui lance l’application sélectionnée", "he_IL": "ליצור קיצור דרך בתיקיית האפליקציות של macOS שיפתח את אפליקציה זו", "it_IT": "Crea un collegamento nella cartella Applicazioni di macOS che avvia l'applicazione selezionata", "ja_JP": "選択したアプリケーションを起動する ショートカットを macOS の Applications フォルダに作成します", @@ -2830,7 +2980,7 @@ "el_GR": "Δημιουργεί μια ανεξάρτητη διαμόρφωση για το τρέχον παιχνίδι", "en_US": "Creates an independent configuration for the selected game", "es_ES": "Crea una configuración independiente para el juego actual", - "fr_FR": "Crée une configuration indépendante pour le jeu en cours", + "fr_FR": "Crée une configuration indépendante pour le jeu sélectionné", "he_IL": "יוצר תצורה עצמאית למשחק הנוכחי", "it_IT": "Crea una configurazione indipendente per il gioco attuale", "ja_JP": "現在のゲーム用の独立した設定を作成します", @@ -2855,14 +3005,14 @@ "el_GR": "", "en_US": "Edit your existing independent configuration for the selected game", "es_ES": "", - "fr_FR": "", + "fr_FR": "Modifier votre configuration indépendante existante pour le jeu sélectionné", "he_IL": "", "it_IT": "", "ja_JP": "", "ko_KR": "선택한 게임에 대한 기존 독립 구성 편집", "no_NO": "Rediger din eksisterende uavhengige konfigurasjon for det valgte spillet", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Editar sua configuração independente existente para o jogo selecionado", "ru_RU": "Отредактировать существующие независимые параметры для выбранной игры.", "sv_SE": "Redigera din befintliga oberoende konfiguration för det valda spelet", "th_TH": "", @@ -2880,7 +3030,7 @@ "el_GR": "", "en_US": "Show Compatibility Entry", "es_ES": "", - "fr_FR": "", + "fr_FR": "Afficher l’entrée de compatibilité", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -2905,7 +3055,7 @@ "el_GR": "", "en_US": "Show the selected game in the Compatibility List you can normally access via the Help menu.", "es_ES": "", - "fr_FR": "", + "fr_FR": "Afficher le jeu sélectionné dans la liste de compatibilité accessible normalement via le menu Aide.", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -2930,7 +3080,7 @@ "el_GR": "", "en_US": "Show Game Info", "es_ES": "", - "fr_FR": "", + "fr_FR": "Afficher les informations du jeu", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -2955,7 +3105,7 @@ "el_GR": "", "en_US": "Show stats & details about the currently selected game.", "es_ES": "", - "fr_FR": "", + "fr_FR": "Afficher les statistiques et les détails sur le jeu actuellement sélectionné.", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -3005,14 +3155,14 @@ "el_GR": "", "en_US": "Opens the directory which contains Application's Mods", "es_ES": "Abre el directorio que contiene los Mods de la Aplicación.", - "fr_FR": "Ouvre le dossier contenant les mods du jeu", + "fr_FR": "Ouvre le dossier contenant les mods de l’application", "he_IL": "פותח את התיקייה שמכילה מודים של האפליקציה", "it_IT": "Apre la cartella che contiene le mod dell'applicazione", "ja_JP": "アプリケーションの Mod データを格納するディレクトリを開きます", "ko_KR": "앱의 모드가 포함된 디렉터리 열기", "no_NO": "Åpner mappen som inneholder programmets modifikasjoner", "pl_PL": "Otwiera katalog zawierający mody dla danej aplikacji", - "pt_BR": "Abre a pasta que contém os mods da aplicação ", + "pt_BR": "Abre a pasta que contém os mods da aplicação", "ru_RU": "Открывает папку, содержащую моды для приложений и игр", "sv_SE": "Öppnar katalogen som innehåller applikationens Mods", "th_TH": "เปิดไดเร็กทอรี่ Mods ของแอปพลิเคชัน", @@ -3055,7 +3205,7 @@ "el_GR": "", "en_US": "Opens the alternative SD card Atmosphere directory which contains Application's Mods. Useful for mods that are packaged for real hardware.", "es_ES": "Abre el directorio alternativo de la tarjeta SD de Atmosphere que contiene los Mods de la Aplicación. Útil para los mods que están empaquetados para el hardware real.", - "fr_FR": "Ouvre le dossier alternatif de la carte SD Atmosphère qui contient les mods de l'application. Utile pour les mods conçus pour console.", + "fr_FR": "Ouvre le dossier Atmosphere d’une carte SD alternative contenant les mods de l’application. Utile pour les mods conçus pour fonctionner sur un matériel réel.", "he_IL": "פותח את תיקיית כרטיס ה-SD החלופית של Atmosphere המכילה את המודים של האפליקציה. שימושי עבור מודים שארוזים עבור חומרה אמיתית.", "it_IT": "Apre la cartella alternativa di Atmosphere sulla scheda SD che contiene le mod dell'applicazione. Utile per le mod create per funzionare sull'hardware reale.", "ja_JP": "アプリケーションの Mod データを格納する SD カードの Atmosphere ディレクトリを開きます. 実際のハードウェア用に作成された Mod データに有用です.", @@ -3080,7 +3230,7 @@ "el_GR": "", "en_US": "Check and Trim XCI File", "es_ES": "Verificar y recortar archivo XCI", - "fr_FR": "Vérifier et réduire les fichiers XCI", + "fr_FR": "Vérifier et réduire le fichier XCI", "he_IL": "", "it_IT": "Controlla e riduci la dimensione del file XCI", "ja_JP": "", @@ -3105,7 +3255,7 @@ "el_GR": "", "en_US": "Check and Trim XCI File to Save Disk Space", "es_ES": "Verificar y recortar archivo XCI para ahorrar espacio en disco", - "fr_FR": "Vérifier et réduire les fichiers XCI pour économiser de l'espace", + "fr_FR": "Vérifier et découper le fichier XCI pour économiser de l’espace disque", "he_IL": "", "it_IT": "Controlla e riduci la dimensione del file XCI per risparmiare spazio su disco", "ja_JP": "", @@ -3134,7 +3284,7 @@ "he_IL": "{1}/{0} משחקים נטענו", "it_IT": "{0}/{1} giochi caricati", "ja_JP": "{0}/{1} ゲーム", - "ko_KR": "{0}/{1}개의 게임 불러옴", + "ko_KR": "{0}/{1}개의 게임 타이틀", "no_NO": "{0}/{1} Spill Lastet", "pl_PL": "{0}/{1} Załadowane gry", "pt_BR": "{0}/{1} Jogos Carregados", @@ -3155,7 +3305,7 @@ "el_GR": "", "en_US": "Firmware Version: {0}", "es_ES": "", - "fr_FR": "Version du Firmware: {0}", + "fr_FR": "Version du firmware: {0}", "he_IL": "", "it_IT": "Versione firmware: {0}", "ja_JP": "", @@ -3205,7 +3355,7 @@ "el_GR": "Εντοπίστηκε χαμηλό όριο για αντιστοιχίσεις μνήμης", "en_US": "Low limit for memory mappings detected", "es_ES": "Límite inferior para mapeos de memoria detectado", - "fr_FR": "Limite basse pour les mappings mémoire détectée", + "fr_FR": "Limite basse pour les mappages mémoire détectée", "he_IL": "זוהתה מגבלה נמוכה עבור מיפויי זיכרון", "it_IT": "Rilevato limite basso per le mappature di memoria", "ja_JP": "メモリマッピング上限値が小さすぎます", @@ -3255,7 +3405,7 @@ "el_GR": "Μερικά παιχνίδια μπορεί να προσπαθήσουν να δημιουργήσουν περισσότερες αντιστοιχίσεις μνήμης από αυτές που επιτρέπονται τώρα. Ο Ryujinx θα καταρρεύσει μόλις ξεπεραστεί αυτό το όριο.", "en_US": "Some games might try to create more memory mappings than currently allowed. Ryujinx will crash as soon as this limit gets exceeded.", "es_ES": "Algunos juegos podrían intentar crear más mapeos de memoria de los permitidos. Ryujinx se bloqueará tan pronto como se supere este límite.", - "fr_FR": "Certains jeux peuvent essayer de créer plus de mappings mémoire que ce qui est actuellement autorisé. Ryujinx plantera dès que cette limite sera dépassée.", + "fr_FR": "Certains jeux peuvent tenter de créer plus de mappages mémoire que ce qui est actuellement autorisé. Ryujinx plantera dès que cette limite sera dépassée.", "he_IL": "משחקים מסוימים עלולים לייצר עוד מיפויי זיכרון ממה שמתאפשר. Ryujinx יקרוס ברגע שהמגבלה תחרוג.", "it_IT": "Alcuni giochi potrebbero provare a creare più mappature di memoria di quanto sia attualmente consentito. Ryujinx si bloccherà non appena questo limite viene superato.", "ja_JP": "ゲームによっては, 現在許可されているサイズより大きなメモリマッピングを作成しようとすることがあります. この制限を超えると, Ryjinx はすぐにクラッシュします.", @@ -3330,7 +3480,7 @@ "el_GR": "Ο μέγιστος αριθμός αντιστοιχίσεων μνήμης είναι μικρότερος από τον συνιστώμενο.", "en_US": "Max amount of memory mappings is lower than recommended.", "es_ES": "La cantidad máxima de mapeos de memoria es menor de lo recomendado.", - "fr_FR": "La quantité maximale de mappings mémoire est inférieure à la valeur recommandée.", + "fr_FR": "La quantité maximale de mappages mémoire est inférieure à la valeur recommandée.", "he_IL": "הכמות המירבית של מיפויי הזיכרון נמוכה מהמומלץ.", "it_IT": "La quantità massima di mappature di memoria è inferiore a quella consigliata.", "ja_JP": "メモリマッピングの最大量が推奨値よりも小さいです.", @@ -3355,7 +3505,7 @@ "el_GR": "Η τρέχουσα τιμή του vm.max_map_count ({0}) είναι χαμηλότερη από {1}. Ορισμένα παιχνίδια μπορεί να προσπαθήσουν να δημιουργήσουν περισσότερες αντιστοιχίσεις μνήμης από αυτές που επιτρέπονται τώρα. Ο Ryujinx θα συντριβεί μόλις ξεπεραστεί το όριο.\n\nΜπορεί να θέλετε είτε να αυξήσετε χειροκίνητα το όριο ή να εγκαταστήσετε το pkexec, το οποίο επιτρέπει Ryujinx να βοηθήσει με αυτό.", "en_US": "The current value of vm.max_map_count ({0}) is lower than {1}. Some games might try to create more memory mappings than currently allowed. Ryujinx will crash as soon as this limit gets exceeded.\n\nYou might want to either manually increase the limit or install pkexec, which allows Ryujinx to assist with that.", "es_ES": "El valor actual de vm.max_map_count ({0}) es menor que {1}. Algunos juegos podrían intentar crear más mapeos de memoria de los permitidos actualmente. Ryujinx se bloqueará tan pronto como se supere este límite.\n\nPuede que desee aumentar manualmente el límite o instalar pkexec, lo que permite a Ryujinx ayudar con eso.", - "fr_FR": "La valeur actuelle de vm.max_map_count ({0}) est inférieure à {1}. Certains jeux peuvent essayer de créer plus de mappings mémoire que ceux actuellement autorisés. Ryujinx plantera dès que cette limite sera dépassée.\n\nVous pouvez soit augmenter manuellement la limite, soit installer pkexec, ce qui permet à Ryujinx de l'aider.", + "fr_FR": "La valeur actuelle de vm.max_map_count ({0}) est inférieure à {1}. Certains jeux pourraient tenter de créer plus de mappages mémoire que ce qui est actuellement autorisé. Ryujinx plantera dès que cette limite sera dépassée.\n\nVous pouvez soit augmenter manuellement cette limite, soit installer pkexec, qui permet à Ryujinx de vous aider dans cette opération.", "he_IL": "הערך הנוכחי של vm.max_map_count {0} נמוך מ{1}. משחקים מסוימים עלולים לייצר עוד מיפוי זיכרון ממה שמתאפשר.Ryujinx יקרוס ברגע שהמגבלה תחרוג.\n\nיתכן ותרצה להעלות את המגבלה הנוכחית או להתקין את pkexec, אשר יאפשר לRyujinx לסייע בכך.", "it_IT": "Il valore corrente di vm.max_map_count ({0}) è inferiore a {1}. Alcuni giochi potrebbero provare a creare più mappature di memoria di quanto sia attualmente consentito. Ryujinx si bloccherà non appena questo limite viene superato.\n\nPotresti voler aumentare manualmente il limite o installare pkexec, il che permette a Ryujinx di assisterlo.", "ja_JP": "vm.max_map_count の現在値 {0} は {1} よりも小さいです. ゲームによっては現在許可されている値よりも大きなメモリマッピングを作成しようとする場合があります. 上限を越えた場合, Ryujinx はクラッシュします.", @@ -3505,7 +3655,7 @@ "el_GR": "", "en_US": "Check for Updates:", "es_ES": "", - "fr_FR": "", + "fr_FR": "Vérifier les mises à jour : ", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -3530,7 +3680,7 @@ "el_GR": "", "en_US": "Off", "es_ES": "", - "fr_FR": "", + "fr_FR": "Désactivé", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -3580,7 +3730,7 @@ "el_GR": "", "en_US": "Background", "es_ES": "", - "fr_FR": "", + "fr_FR": "En arrière-plan", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -3605,7 +3755,7 @@ "el_GR": "", "en_US": "On Emulator Focus Lost:", "es_ES": "", - "fr_FR": "", + "fr_FR": "Lorsque l’émulateur perd le focus :", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -3630,7 +3780,7 @@ "el_GR": "", "en_US": "Do Nothing", "es_ES": "", - "fr_FR": "", + "fr_FR": "Ne rien faire", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -3655,7 +3805,7 @@ "el_GR": "", "en_US": "Block Input", "es_ES": "", - "fr_FR": "", + "fr_FR": "Bloquer la saisie", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -3680,7 +3830,7 @@ "el_GR": "", "en_US": "Mute Volume", "es_ES": "", - "fr_FR": "", + "fr_FR": "Couper le son", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -3705,7 +3855,7 @@ "el_GR": "", "en_US": "Block Input & Mute Volume", "es_ES": "", - "fr_FR": "", + "fr_FR": "Bloquer la saisie & couper le son", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -3730,7 +3880,7 @@ "el_GR": "", "en_US": "Pause Emulation", "es_ES": "", - "fr_FR": "", + "fr_FR": "Mettre l’émulation en pause", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -3805,7 +3955,7 @@ "el_GR": "", "en_US": "Disable Input when Out of Focus", "es_ES": "", - "fr_FR": "", + "fr_FR": "Désactiver la saisie en cas de perte de focus", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -3830,14 +3980,14 @@ "el_GR": "", "en_US": "Show Original UI Style (Requires restart)", "es_ES": "", - "fr_FR": "", + "fr_FR": "Afficher le style d’interface original (redémarrage requis)", "he_IL": "", "it_IT": "", "ja_JP": "", "ko_KR": "원래 UI 스타일 표시(다시 시작 필요)", "no_NO": "Vis original UI-stil (krever omstart)", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Mostrar Estilo Original da Interface (Requer Reinicialização)", "ru_RU": "Включить оригинальный интерфейса (требуется перезагрузка)", "sv_SE": "Visa ursprunglig gränssnittsstil (kräver omstart)", "th_TH": "", @@ -3855,14 +4005,14 @@ "el_GR": "", "en_US": "Show the older Avalonia Ryujinx UI reminiscent of Ryujinx 1.1.1403. This is enabled by default on platforms that are not Windows.\nThe classic-style title bar is back and major window layout reworkings are reversed; such as the settings navigation placement above this tooltip.", "es_ES": "", - "fr_FR": "", + "fr_FR": "Afficher l’ancienne interface Avalonia Ryujinx, rappelant Ryujinx 1.1.1403. Cette option est activée par défaut sur les plateformes autres que Windows.\nLa barre de titre au style classique est de retour et les modifications majeures de la disposition des fenêtres sont annulées, comme le placement de la navigation des paramètres au-dessus de cette infobulle.", "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "Ryujinx 1.1.1403을 연상시키는 이전 Avalonia Ryujinx UI를 표시합니다. 이 기능은 Windows가 아닌 플랫폼에서는 기본적으로 활성화됩니다.\n 클래식 스타일의 타이틀 바가 돌아왔고 주요 창 레이아웃 재작업이 역전되었습니다. 이 툴팁 위의 설정 탐색 배치와 같은 작업입니다.", + "ko_KR": "Ryujinx 1.1.1403을 연상시키는 이전 Avalonia Ryujinx UI를 표시합니다. 이 기능은 윈도가 아닌 플랫폼에서는 기본적으로 활성화됩니다.\n 클래식 스타일의 타이틀 바가 돌아왔고 주요 창 레이아웃 변경 사항이 원래대로 적용됩니다. 이 툴팁 위의 설정 탐색 배치와 같은 경우입니다.", "no_NO": "Vis det eldre Avalonia Ryujinx-grensesnittet som minner om Ryujinx 1.1.1403. Dette er aktivert som standard på plattformer som ikke er Windows.\nTittellinjen i klassisk stil er tilbake, og store omarbeidinger av vindusoppsettet er reversert, for eksempel plasseringen av innstillingsnavigasjonen over dette verktøytipset.", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Mostrar a Interface Avalonia antiga do Ryujinx 1.1.1403. Esta versão é ativada por padrão nas plataformas que não sejam Windows. \nO estilo clássico da Barra de Título retorna e grande parte das mudanças do Layout de janela são revertidas; assim como as configurações de posicionamento da navegação acima dessa descrição.", "ru_RU": "Показать старый пользовательский интерфейс Avalonia Ryujinx, напоминающий Ryujinx 1.1.1403. Включено по умолчанию на платформах, отличных от Windows.\nСтрока заголовка в классическом стиле вернётся на место, а основные изменения в оформлении окна будут отменены; например, расположение навигации по настройкам над этой всплывающей подсказкой.", "sv_SE": "Visa det gamla Ryuijinx-gränssnittet baserat på Avalonia som påminner om version 1.1.1403. Detta är aktiverat som standard på plattformat som inte är Windows.\nDen klassiska titelfältet är tillbaka och de stora omarbetningarna av fönsterlayouten är omvända, till exempel placeringen av inställningsnavigeringen ovanför detta verktygstips.", "th_TH": "", @@ -3930,7 +4080,7 @@ "el_GR": "Απόκρυψη Δρομέα στην Αδράνεια", "en_US": "On Idle", "es_ES": "Ocultar cursor cuando esté inactivo", - "fr_FR": "Masquer le curseur si inactif", + "fr_FR": "Si inactif", "he_IL": "במצב סרק", "it_IT": "Quando è inattivo", "ja_JP": "アイドル時", @@ -4005,7 +4155,7 @@ "el_GR": "", "en_US": "Autoload DLC/Updates Directories", "es_ES": "Carpetas de DLC/Actualizaciones para Carga Automática", - "fr_FR": "Dossiers des mises à jour/DLC", + "fr_FR": "Charger automatiquement les dossiers de DLC/mises à jour", "he_IL": "", "it_IT": "Cartelle di caricamento automatico di DLC/aggiornamenti", "ja_JP": "", @@ -4030,7 +4180,7 @@ "el_GR": "", "en_US": "DLC and Updates which refer to missing files will be unloaded automatically", "es_ES": "DLC y Actualizaciones que hacen referencia a archivos ausentes serán desactivado automáticamente", - "fr_FR": "Les DLC et les mises à jour faisant référence aux fichiers manquants seront automatiquement déchargés.", + "fr_FR": "Les DLC et mises à jour faisant référence à des fichiers manquants seront déchargés automatiquement.", "he_IL": "", "it_IT": "Aggiornamenti e DLC che fanno riferimento a file mancanti verranno disabilitati automaticamente", "ja_JP": "", @@ -4130,7 +4280,7 @@ "el_GR": "Πυρήνας", "en_US": "Core", "es_ES": "Núcleo", - "fr_FR": "Cœur", + "fr_FR": "Paramètres généraux", "he_IL": "ליבה", "it_IT": "Principale", "ja_JP": "コア", @@ -4855,7 +5005,7 @@ "el_GR": "", "en_US": "Match System Time", "es_ES": "", - "fr_FR": "", + "fr_FR": "Synchroniser avec l’heure du système", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -4905,7 +5055,7 @@ "el_GR": "Low-power PPTC", "en_US": "Low-power PPTC cache", "es_ES": "Cache PPTC de bajo consumo", - "fr_FR": "PPTC à faible puissance", + "fr_FR": "Cache PPTC de faible puissance", "he_IL": "Low-power PPTC", "it_IT": "Caricamento PPTC a basso consumo energetico", "ja_JP": "Low-power PPTC", @@ -4937,7 +5087,7 @@ "ko_KR": "터보 모드 배수 :", "no_NO": "Multiplikator i turbomodus:", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Multiplicador do Modo Turbo", "ru_RU": "", "sv_SE": "Multiplikator för turboläge:", "th_TH": "", @@ -4955,14 +5105,14 @@ "el_GR": "", "en_US": "The Turbo mode multiplier target value.\n\nLeave at 200 if unsure.", "es_ES": "", - "fr_FR": "La valeur souhaitée du multiplicateur du Mode Turbo.\n\nGarder à 200 si incertain.", + "fr_FR": "La valeur souhaitée du multiplicateur du mode Turbo.\n\nLaissez à 200 si vous n'êtes pas sûr.", "he_IL": "", "it_IT": "", "ja_JP": "", "ko_KR": "터보 모드 배수 목표 값입니다.\n\n모르면 200으로 두세요.", "no_NO": "Målverdien for multiplikatoren i turbomodus. \n\nLa syå på 200 hvis du er usikker.", "pl_PL": "", - "pt_BR": "", + "pt_BR": "O valor do Multiplicador do Modo Turbo. Deixe em 200 se não tiver certeza.", "ru_RU": "", "sv_SE": "Målvärdet för multiplikatorn i turboläget. \n\nLämna den på 200 om du är osäker.", "th_TH": "", @@ -4980,14 +5130,14 @@ "el_GR": "", "en_US": "Turbo mode is an emulator feature which effectively causes speed up or slow down when a game is not frame-rate sensitive.\nYou can toggle this feature in-game with a hotkey, configurable in Ryujinx Keyboard Hotkeys settings.\n\nLeave at 200 if unsure.", "es_ES": "", - "fr_FR": "Le Mode Turbo est une fonctionnalité de l'émulateur qui accélère ou ralentit le jeu lorsque ce dernier n'est pas sensible au framerate.\nVous pouvez changer cette option en jeu avec un raccourci clavier, configurable dans les paramètres de Raccourcis clavier de Ryujinx.\n\nGarder à 200 si incertain.", + "fr_FR": "Le Mode Turbo est une fonctionnalité de l’émulateur qui permet d’accélérer ou de ralentir le jeu lorsque celui-ci n’est pas sensible au taux de rafraîchissement.\nVous pouvez activer ou désactiver cette fonction en jeu via un raccourci clavier, configurable dans les paramètres des raccourcis clavier de Ryujinx.\n\nLaissez à 200 si vous n’êtes pas sûr.", "he_IL": "", "it_IT": "", "ja_JP": "", "ko_KR": "터보 모드는 게임이 프레임 속도에 민감하지 않을 때 효과적으로 속도를 높이거나 낮추는 에뮬레이터 기능입니다.\n이 기능은 Ryujinx 키보드 단축키 설정에서 구성할 수 있는 단축키를 사용하여 게임 내에서 전환할 수 있습니다.\n\n모르면 200으로 두세요.", "no_NO": "Turbo-modus er en emulatorfunksjon som effektivt øker eller senker hastigheten når et spill ikke er følsom for bildefrekvens.\nDu kan slå på denne funksjonen i spillet med en hurtigtast, som kan konfigureres i Ryujinx Keyboard Hotkeys-innstillingene.\n\nLa den stå på 200 hvis du er usikker.", "pl_PL": "", - "pt_BR": "", + "pt_BR": "O Modo Turbo é um recurso do emulador que efetivamente aumenta ou dimimui a velocidade de um jogo quando o mesmo não é sensivel à taxa de quadros. \nVocê pode ativar esse recurso dentro do jogo com uma tecla de atalho, configurável nas Configurações de Teclas de Atalho do Ryujinx. \n\nDeixe em 200 se não tiver certeza.", "ru_RU": "", "sv_SE": "Turboläget är en emulatorfunktion som effektivt ökar eller sänker hastigheten när ett spel inte är känsligt för bildfrekvens.\nDu kan växla denna funktion i spelet med en snabbtangent, konfigurerbar i Ryujinx inställningar för snabbtangenter.\n\nLämna den på 200 om du är osäker.", "th_TH": "", @@ -5005,7 +5155,7 @@ "el_GR": "Ενεργοποίηση Ελέγχων Ακεραιότητας FS", "en_US": "FS Integrity Checks", "es_ES": "Comprobar integridad de los archivos", - "fr_FR": "Activer la vérification de l'intégrité du système de fichiers", + "fr_FR": "Vérification de l’intégrité du système de fichiers (FS)", "he_IL": "FS בדיקות תקינות", "it_IT": "Attiva controlli d'integrità FS", "ja_JP": "ファイルシステム整合性チェック", @@ -5162,7 +5312,7 @@ "ko_KR": "핵", "no_NO": "", "pl_PL": "Hacki", - "pt_BR": "", + "pt_BR": "Trapaças", "ru_RU": "Хаки", "sv_SE": "Hack", "th_TH": "แฮ็ก", @@ -5180,7 +5330,7 @@ "el_GR": " (Μπορεί να προκαλέσουν αστάθεια)", "en_US": "May cause instability", "es_ES": " (Pueden causar inestabilidad)", - "fr_FR": "Cela peut causer des instabilités", + "fr_FR": "Peut causer des instabilités", "he_IL": "עלול לגרום לאי יציבות", "it_IT": "Possono causare instabilità", "ja_JP": " (挙動が不安定になる可能性があります)", @@ -5355,7 +5505,7 @@ "el_GR": "", "en_US": "Ignore Controller Applet", "es_ES": "", - "fr_FR": "", + "fr_FR": "Ignorer l’applet de contrôleur", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -5380,7 +5530,7 @@ "el_GR": "Παράκαμψη διαλόγου 'Διαχείριση Προφίλ _Χρηστών'", "en_US": "Skip dialog 'Manage User Profiles'", "es_ES": "Omitir el diálogo 'Gestionar perfiles de usuario'", - "fr_FR": "Ignorer le dialogue 'Gérer les profils d'utilisateurs'", + "fr_FR": "Ignorer la boîte de dialogue « Gérer les profils utilisateur »", "he_IL": "דילוג על הדיאלוג 'נהל פרופילי משתמש'", "it_IT": "Salta la finestra di dialogo 'Gestisci i profili utente'", "ja_JP": "「ユーザプロファイルを管理」ダイアログをスキップ", @@ -5425,26 +5575,26 @@ { "ID": "SettingsTabGraphicsAPI", "Translations": { - "ar_SA": "API الرسومات ", - "de_DE": "Grafik-API", - "el_GR": "API Γραφικά", - "en_US": "Graphics API", - "es_ES": "API de gráficos", - "fr_FR": "API Graphique", - "he_IL": "ממשק גראפי", - "it_IT": "API grafica", - "ja_JP": "グラフィックスAPI", - "ko_KR": "그래픽 API", - "no_NO": "Grafikk API", - "pl_PL": "Graficzne API", - "pt_BR": "API gráfica", - "ru_RU": "Графические API", - "sv_SE": "Grafik-API", - "th_TH": "API กราฟฟิก", - "tr_TR": "Grafikler API", - "uk_UA": "Графічний API", - "zh_CN": "图形 API", - "zh_TW": "圖形 API" + "ar_SA": "API الرسومات و تحسين", + "de_DE": "Grafik-API & Optimierung", + "el_GR": "API Γραφικά & Βελτιστοποίηση", + "en_US": "Graphics API & Optimization", + "es_ES": "API de gráficos & Optimización", + "fr_FR": "API Graphique & Optimisation", + "he_IL": "ממשק גראפי & אופטימיזציה", + "it_IT": "API grafica & Ottimizzazione", + "ja_JP": "グラフィックスAPI&最適化", + "ko_KR": "그래픽 API & 최적화", + "no_NO": "Grafikk-API & Optimalisering", + "pl_PL": "Graficzne API & Optymalizacja", + "pt_BR": "API gráfica & Otimização", + "ru_RU": "Графический API & Оптимизация", + "sv_SE": "Grafik-API & Optimering", + "th_TH": "API กราฟฟิก & การเพิ่มประสิทธิภาพ", + "tr_TR": "Grafikler API & Optimizasyon", + "uk_UA": "Графічний API & Оптимізація", + "zh_CN": "图形 API & 优化", + "zh_TW": "圖形 API & 優化" } }, { @@ -5655,7 +5805,7 @@ "el_GR": "Προσαρμοσμένο (Δεν συνιστάται)", "en_US": "Custom (Not recommended)", "es_ES": "Personalizada (no recomendado)", - "fr_FR": "Personnalisée (Non recommandée)", + "fr_FR": "Personnalisée (non recommandée)", "he_IL": "מותאם אישית (לא מומלץ)", "it_IT": "Personalizzata (Non raccomandata)", "ja_JP": "カスタム (非推奨)", @@ -5755,7 +5905,7 @@ "el_GR": "", "en_US": "4x (2880p/4320p) (Not recommended)", "es_ES": "4x (2880p/4320p) (no recomendado)", - "fr_FR": "x4 (2880p/4320p) (Non recommandé)", + "fr_FR": "x4 (2880p/4320p) (non recommandé)", "he_IL": "4x (2880p/4320p) (לא מומלץ)", "it_IT": "4x (2880p/4320p) (Non consigliato)", "ja_JP": "4x (2880p/4320p) (非推奨)", @@ -5780,7 +5930,7 @@ "el_GR": "Αναλογία Απεικόνισης:", "en_US": "Aspect Ratio:", "es_ES": "Relación de aspecto:", - "fr_FR": "Format d'affichage :", + "fr_FR": "Format d'image :", "he_IL": "יחס גובה-רוחב:", "it_IT": "Rapporto d'aspetto:", "ja_JP": "アスペクト比:", @@ -5930,7 +6080,7 @@ "el_GR": "Έκταση σε όλο το παράθυρο", "en_US": "Stretch to Fit Window", "es_ES": "Estirar a la ventana", - "fr_FR": "Étirer pour remplir la fenêtre", + "fr_FR": "Ajuster à la taille de la fenêtre", "he_IL": "מתח לגודל חלון", "it_IT": "Adatta alla finestra", "ja_JP": "ウインドウサイズに合わせる", @@ -5955,14 +6105,14 @@ "el_GR": "Επιλογές Προγραμματιστή", "en_US": "Developer Options", "es_ES": "Opciones de desarrollador", - "fr_FR": "Options développeur", + "fr_FR": "Options pour les développeurs", "he_IL": "אפשרויות מפתח", "it_IT": "Opzioni per sviluppatori", "ja_JP": "開発者向けオプション", "ko_KR": "개발자 옵션", "no_NO": "Utvikleralternativer", "pl_PL": "Opcje programisty", - "pt_BR": "Opções do desenvolvedor", + "pt_BR": "Opções do Desenvolvedor", "ru_RU": "Параметры разработчика", "sv_SE": "Utvecklarinställningar", "th_TH": "ตัวเลือกนักพัฒนา", @@ -5980,7 +6130,7 @@ "el_GR": "Τοποθεσία Shaders Γραφικών:", "en_US": "Graphics Shader Dump Path:", "es_ES": "Directorio de volcado de sombreadores:", - "fr_FR": "Chemin du dossier de copie des shaders :", + "fr_FR": "Chemin de vidage des shaders graphiques :", "he_IL": "", "it_IT": "Percorso di dump degli shader:", "ja_JP": "グラフィックス シェーダー ダンプパス:", @@ -6005,7 +6155,7 @@ "el_GR": "Καταγραφή", "en_US": "Logging", "es_ES": "Registros", - "fr_FR": "Journaux", + "fr_FR": "Journalisation", "he_IL": "רישום", "it_IT": "Log", "ja_JP": "ロギング", @@ -6030,7 +6180,7 @@ "el_GR": "Καταγραφή", "en_US": "Logging", "es_ES": "Registros", - "fr_FR": "Journaux", + "fr_FR": "Journalisation", "he_IL": "רישום", "it_IT": "Log", "ja_JP": "ロギング", @@ -6055,7 +6205,7 @@ "el_GR": "Ενεργοποίηση Καταγραφής Αρχείου", "en_US": "Enable Logging to File", "es_ES": "Habilitar registro a archivo", - "fr_FR": "Activer la sauvegarde des journaux vers un fichier", + "fr_FR": "Activer la journalisation dans un fichier", "he_IL": "אפשר רישום לקובץ", "it_IT": "Salva i log su file", "ja_JP": "ファイルへのロギングを有効にする", @@ -6087,7 +6237,7 @@ "ko_KR": "조각 기록 활성화", "no_NO": "Aktiver Stub-logger", "pl_PL": "Wlącz Skróty Logów", - "pt_BR": "Habilitar logs de Stub", + "pt_BR": "Habilitar Logs de Stub", "ru_RU": "Включить журнал-заглушку", "sv_SE": "Aktivera stubbloggar", "th_TH": "เปิดใช้งานการบันทึกประวัติ", @@ -6112,7 +6262,7 @@ "ko_KR": "정보 기록 활성화", "no_NO": "Aktiver informasjonslogger", "pl_PL": "Włącz Logi Informacyjne", - "pt_BR": "Habilitar logs de Informação", + "pt_BR": "Habilitar Logs de Informação", "ru_RU": "Включить информационный журнал", "sv_SE": "Aktivera informationsloggar", "th_TH": "เปิดใช้งานการบันทึกประวัติการใช้งาน", @@ -6180,7 +6330,7 @@ "el_GR": "Ενεργοποίηση Καταγραφής Ιχνών", "en_US": "Enable Trace Logs", "es_ES": "Habilitar registros de Rastro", - "fr_FR": "Activer les journaux d'erreurs Trace", + "fr_FR": "Activer les journaux de trace", "he_IL": "הפעל רישום מעקבי", "it_IT": "Attiva log di trace", "ja_JP": "Trace ログを有効にする", @@ -6205,7 +6355,7 @@ "el_GR": "Ενεργοποίηση Καταγραφής Επισκεπτών", "en_US": "Enable Guest Logs", "es_ES": "Habilitar registros de Guest", - "fr_FR": "Activer les journaux du programme simulé", + "fr_FR": "Activer les journaux invités", "he_IL": "הפעל רישום מארח", "it_IT": "Attiva log del guest", "ja_JP": "Guest ログを有効にする", @@ -6230,7 +6380,7 @@ "el_GR": "", "en_US": "Enable UI Logs", "es_ES": "", - "fr_FR": "", + "fr_FR": "Activer les journaux UI", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -6280,7 +6430,7 @@ "el_GR": "Λειτουργία Καταγραφής Καθολικής Πρόσβασης FS:", "en_US": "Fs Global Access Log Mode:", "es_ES": "Modo de registros Fs Global Access:", - "fr_FR": "Niveau des journaux d'accès au système de fichiers :", + "fr_FR": "Mode global des journaux d’accès FS", "he_IL": "מצב רישום גלובלי של גישת קבצי מערכת", "it_IT": "Modalità log di accesso globale FS:", "ja_JP": "Fs グローバルアクセスログモード:", @@ -6305,14 +6455,14 @@ "el_GR": "Επιλογές Προγραμματιστή (ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Η απόδοση Θα μειωθεί)", "en_US": "Developer Options", "es_ES": "Opciones de desarrollador (ADVERTENCIA: empeorarán el rendimiento)", - "fr_FR": "Options développeur", + "fr_FR": "Options pour les développeurs", "he_IL": "אפשרויות מפתח", "it_IT": "Opzioni per sviluppatori", "ja_JP": "開発者オプション", "ko_KR": "개발자 옵션", "no_NO": "Utvikleralternativer", "pl_PL": "Opcje programisty (UWAGA: wpływa na wydajność)", - "pt_BR": "Opções do desenvolvedor", + "pt_BR": "Opções do Desenvolvedor", "ru_RU": "Параметры разработчика", "sv_SE": "Utvecklarinställningar", "th_TH": "ตัวเลือกนักพัฒนา", @@ -6355,7 +6505,7 @@ "el_GR": "Επίπεδο Καταγραφής Διεπαφής Γραφικών:", "en_US": "Graphics Backend Log Level:", "es_ES": "Nivel de registro de backend gráficos:", - "fr_FR": "Niveau du journal du backend graphique :", + "fr_FR": "Niveau de journalisation du backend graphique :", "he_IL": "רישום גרפיקת קצה אחורי:", "it_IT": "Livello di log del backend grafico:", "ja_JP": "グラフィックスバックエンド ログレベル:", @@ -6480,7 +6630,7 @@ "el_GR": "Ενεργοποίηση Αρχείων Καταγραφής Εντοπισμού Σφαλμάτων", "en_US": "Enable Debug Logs", "es_ES": "Habilitar registros de debug", - "fr_FR": "Activer les journaux de debug", + "fr_FR": "Activer les journaux de débogage", "he_IL": "אפשר רישום ניפוי באגים", "it_IT": "Attiva log di debug", "ja_JP": "デバッグログを有効にする", @@ -6522,6 +6672,31 @@ "zh_TW": "輸入" } }, + { + "ID": "SettingsTabInputUseGlobalInput", + "Translations": { + "ar_SA": "إدخال عالمي", + "de_DE": "Globale Eingabe", + "el_GR": "Παγκόσμια εισαγωγή", + "en_US": "Global Input", + "es_ES": "Entrada Global", + "fr_FR": "Saisie Globale", + "he_IL": "קלט גלובלי", + "it_IT": "Input Globale", + "ja_JP": "グローバル入力", + "ko_KR": "글로벌 입력", + "no_NO": "Global Inndata", + "pl_PL": "Globalny Wpis", + "pt_BR": "Entrada Global", + "ru_RU": "Глобальный Ввод", + "sv_SE": "Global Input", + "th_TH": "การป้อนข้อมูลแบบโกลบอล", + "tr_TR": "Küresel Girdi", + "uk_UA": "Глобальний Ввід", + "zh_CN": "全局输入", + "zh_TW": "全域輸入" + } + }, { "ID": "SettingsTabInputEnableDockedMode", "Translations": { @@ -6530,7 +6705,7 @@ "el_GR": "Ενεργοποίηση Docked Mode", "en_US": "Docked Mode", "es_ES": "Modo dock/TV", - "fr_FR": "Active le mode station d'accueil", + "fr_FR": "Mode Docké", "he_IL": "מצב עגינה", "it_IT": "Attiva modalità TV", "ja_JP": "ドッキングモード", @@ -6630,7 +6805,7 @@ "el_GR": "", "en_US": "Reset Settings", "es_ES": "", - "fr_FR": "", + "fr_FR": "Réinitialiser les paramètres", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -6655,7 +6830,7 @@ "el_GR": "", "en_US": "I want to reset my settings.", "es_ES": "", - "fr_FR": "", + "fr_FR": "Je veux réinitialiser mes paramètres.", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -7005,7 +7180,7 @@ "el_GR": "Συσκευή Χειρισμού", "en_US": "Input Device", "es_ES": "Dispositivo de entrada", - "fr_FR": "Périphériques", + "fr_FR": "Périphérique", "he_IL": "מכשיר קלט", "it_IT": "Dispositivo di input", "ja_JP": "入力デバイス", @@ -7030,21 +7205,21 @@ "el_GR": "", "en_US": "Configuration found:\n\nName:\t{0}\nGUID:\t{1}\n\n Waiting for controller connection...", "es_ES": "", - "fr_FR": "", + "fr_FR": "Configuration trouvée:\n\nNom:\t{0}\nGUID:\t{1}\n\nEn attente de la connexion de la manette...", "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "발견된 구성 :\n\n이름 : \t{0}\n가이드 : \t{1}\n\n 컨트롤러 연결 대기 중...", "no_NO": "", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Configuração encontrada:\n\nNome:\t{0}\nGUID:\t{1}\n\n Aguardando conexão do controle...", "ru_RU": "", - "sv_SE": "", + "sv_SE": "Konfiguration hittad:\n\nNamn:\t{0}\nGUID:\t{1}\n\n Väntar på anslutning till kontroller...", "th_TH": "", "tr_TR": "", "uk_UA": "", "zh_CN": "发现配置:\n\n名称:\t{0}\nGUID:\t{1}\n\n 正在等待控制器连接...", - "zh_TW": "" + "zh_TW": "找到控制器的配置:\n\n名稱:\t{0}\nGUID:\t{1}\n\n 正在等待控制器連線..." } }, { @@ -7084,7 +7259,7 @@ "he_IL": "מושבת", "it_IT": "Disabilitato", "ja_JP": "無効", - "ko_KR": "비활성화됨", + "ko_KR": "비활성화", "no_NO": "Deaktivert", "pl_PL": "Wyłączone", "pt_BR": "Desabilitado", @@ -7380,7 +7555,7 @@ "el_GR": "Η διαχείριση έχει ρυθμιστεί.\n\nΑναμένεται σύνδεση του χειριστηρίου...", "en_US": "Control configured.\n\nWaiting for controller connection...", "es_ES": "Control configurado.\n\nEsperando la conexión del controlador...", - "fr_FR": "Contrôle configuré.\n\nEn attente de la connexion du contrôleur...", + "fr_FR": "Contrôle configuré.\n\nEn attente de la connexion de la manette...", "he_IL": "השליטה הוגדרה.\n\nממתין לחיבור הבקר...", "it_IT": "Controllo configurato.\n\nIn attesa della connessione del controller...", "ja_JP": "コントロールが設定されました。\n\nコントローラーの接続を待っています...", @@ -8030,7 +8205,7 @@ "el_GR": "Αριστερή Σκανδάλη", "en_US": "Triggers Left", "es_ES": "Gatillos izquierdos", - "fr_FR": "Gachettes Gauche", + "fr_FR": "Gâchettes Gauche", "he_IL": "הדק שמאלי", "it_IT": "Grilletto sinistro", "ja_JP": "左トリガー", @@ -8055,7 +8230,7 @@ "el_GR": "Δεξιά Σκανδάλη", "en_US": "Triggers Right", "es_ES": "Gatillos derechos", - "fr_FR": "Gachettes Droite", + "fr_FR": "Gâchettes Droite", "he_IL": "הדק ימני", "it_IT": "Grilletto destro", "ja_JP": "右トリガー", @@ -8080,7 +8255,7 @@ "el_GR": "Αριστερά Κουμπιά Σκανδάλης", "en_US": "Trigger Buttons Left", "es_ES": "Botones de gatillo izquierdos", - "fr_FR": "Boutons Gachettes Gauche", + "fr_FR": "Boutons Gâchettes Gauche", "he_IL": "כפתור הדק שמאלי", "it_IT": "Pulsante dorsale sinistro", "ja_JP": "左トリガーボタン", @@ -8105,7 +8280,7 @@ "el_GR": "Δεξιά Κουμπιά Σκανδάλης", "en_US": "Trigger Buttons Right", "es_ES": "Botones de gatillo derechos", - "fr_FR": "Boutons Gachettes Droite", + "fr_FR": "Boutons Gâchettes Droite", "he_IL": "כפתור הדק ימני", "it_IT": "Pulsante dorsale destro", "ja_JP": "右トリガーボタン", @@ -8130,7 +8305,7 @@ "el_GR": "Σκανδάλες", "en_US": "Triggers", "es_ES": "Gatillos", - "fr_FR": "Gachettes", + "fr_FR": "Gâchettes", "he_IL": "הדקים", "it_IT": "Grilletti", "ja_JP": "トリガー", @@ -8430,7 +8605,7 @@ "el_GR": "Κατώφλι Σκανδάλης:", "en_US": "Trigger Threshold:", "es_ES": "Límite de gatillos:", - "fr_FR": "Seuil de gachettes :", + "fr_FR": "Seuil de déclenchement :", "he_IL": "סף הדק:", "it_IT": "Sensibilità dei grilletti:", "ja_JP": "トリガーしきい値:", @@ -8480,7 +8655,7 @@ "el_GR": "Κίνηση συμβατή με CemuHook", "en_US": "Use CemuHook compatible motion", "es_ES": "Usar movimiento compatible con CemuHook", - "fr_FR": "Utiliser un capteur de mouvements CemuHook", + "fr_FR": "Utiliser la détection de mouvements compatible CemuHook", "he_IL": "השתמש בתנועת CemuHook תואמת ", "it_IT": "Usa sensore compatibile con CemuHook", "ja_JP": "CemuHook 互換モーションを使用", @@ -8680,7 +8855,7 @@ "el_GR": "", "en_US": "Disable", "es_ES": "", - "fr_FR": "", + "fr_FR": "Désactiver", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -8705,7 +8880,7 @@ "el_GR": "", "en_US": "Rainbow", "es_ES": "", - "fr_FR": "", + "fr_FR": "Arc-en-ciel", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -8730,7 +8905,7 @@ "el_GR": "", "en_US": "Rainbow Speed", "es_ES": "", - "fr_FR": "", + "fr_FR": "Vitesse des couleurs", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -8755,7 +8930,7 @@ "el_GR": "", "en_US": "Color", "es_ES": "", - "fr_FR": "", + "fr_FR": "Couleur", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -8830,7 +9005,7 @@ "el_GR": "", "en_US": "Unknown", "es_ES": "Desconocido", - "fr_FR": "Touche inconnue", + "fr_FR": "Inconnu", "he_IL": "", "it_IT": "Sconosciuto", "ja_JP": "", @@ -9430,7 +9605,7 @@ "el_GR": "", "en_US": "Backspace", "es_ES": "", - "fr_FR": "Supprimer", + "fr_FR": "Retour arrière", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -9455,7 +9630,7 @@ "el_GR": "", "en_US": "Insert", "es_ES": "", - "fr_FR": "Ins", + "fr_FR": "Inser", "he_IL": "", "it_IT": "Ins", "ja_JP": "", @@ -9480,7 +9655,7 @@ "el_GR": "", "en_US": "Delete", "es_ES": "", - "fr_FR": "Sup", + "fr_FR": "Suppr", "he_IL": "", "it_IT": "Canc", "ja_JP": "", @@ -9505,7 +9680,7 @@ "el_GR": "", "en_US": "Page Up", "es_ES": "", - "fr_FR": "", + "fr_FR": "Pg.Préc", "he_IL": "", "it_IT": "Pag. Su", "ja_JP": "", @@ -9530,7 +9705,7 @@ "el_GR": "", "en_US": "Page Down", "es_ES": "", - "fr_FR": "", + "fr_FR": "Pg.Suiv", "he_IL": "", "it_IT": "Pag. Giù", "ja_JP": "", @@ -10737,7 +10912,7 @@ "ko_KR": "좌측 스틱 버튼", "no_NO": "Venstre Styrespak Trykk", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Botão Analógico Esquerdo", "ru_RU": "Кнопка лев. стика", "sv_SE": "L-spakknapp", "th_TH": "", @@ -10762,7 +10937,7 @@ "ko_KR": "우측 스틱 버튼", "no_NO": "Høyre Styrespak Trykk", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Botão Analógico Direito", "ru_RU": "Кнопка пр. стика", "sv_SE": "R-spakknapp", "th_TH": "", @@ -10780,14 +10955,14 @@ "el_GR": "", "en_US": "Left Shoulder", "es_ES": "", - "fr_FR": "Bouton Gachette G.", + "fr_FR": "Bouton Gâchette G.", "he_IL": "", "it_IT": "Pulsante dorsale sinistro", "ja_JP": "", "ko_KR": "좌측 숄더", "no_NO": "Venstre Skulder", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Ombro Esquerdo", "ru_RU": "Левый бампер", "sv_SE": "Vänster kantknapp", "th_TH": "", @@ -10805,14 +10980,14 @@ "el_GR": "", "en_US": "Right Shoulder", "es_ES": "", - "fr_FR": "Bouton Gachette D.", + "fr_FR": "Bouton Gâchette D.", "he_IL": "", "it_IT": "Pulsante dorsale destro", "ja_JP": "", "ko_KR": "우측 숄더", "no_NO": "Høyre Skulder", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Ombro Direito", "ru_RU": "Правый бампер", "sv_SE": "Höger kantknapp", "th_TH": "", @@ -10830,14 +11005,14 @@ "el_GR": "", "en_US": "Left Trigger", "es_ES": "", - "fr_FR": "Gachette Gauche", + "fr_FR": "Gâchette Gauche", "he_IL": "", "it_IT": "Grilletto sinistro", "ja_JP": "", "ko_KR": "좌측 트리거", "no_NO": "Venstre utløser", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Gatilho Esquerdo", "ru_RU": "Левый триггер", "sv_SE": "Vänster avtryckare", "th_TH": "", @@ -10855,14 +11030,14 @@ "el_GR": "", "en_US": "Right Trigger", "es_ES": "", - "fr_FR": "Gachette Droite", + "fr_FR": "Gâchette Droite", "he_IL": "", "it_IT": "Grilletto destro", "ja_JP": "", "ko_KR": "우측 트리거", "no_NO": "Høyre utløser", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Gatilho Direito", "ru_RU": "Правый триггер", "sv_SE": "Höger avtryckare", "th_TH": "", @@ -10887,7 +11062,7 @@ "ko_KR": "↑", "no_NO": "Opp", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Cima", "ru_RU": "Вверх", "sv_SE": "Upp", "th_TH": "", @@ -10912,7 +11087,7 @@ "ko_KR": "↓", "no_NO": "Ned", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Baixo", "ru_RU": "Вниз", "sv_SE": "Ner", "th_TH": "", @@ -10937,7 +11112,7 @@ "ko_KR": "←", "no_NO": "Venstre", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Esquerda", "ru_RU": "Влево", "sv_SE": "Vänster", "th_TH": "", @@ -10962,7 +11137,7 @@ "ko_KR": "→", "no_NO": "Høyre", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Direita", "ru_RU": "Вправо", "sv_SE": "Höger", "th_TH": "", @@ -11037,7 +11212,7 @@ "ko_KR": "가이드", "no_NO": "Veiledning", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Guia", "ru_RU": "Кнопка меню", "sv_SE": "", "th_TH": "", @@ -11180,7 +11355,7 @@ "el_GR": "", "en_US": "Touchpad", "es_ES": "", - "fr_FR": "", + "fr_FR": "Pavé tactile", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -11205,14 +11380,14 @@ "el_GR": "", "en_US": "Left Trigger 0", "es_ES": "", - "fr_FR": "Gachette Gauche 0", + "fr_FR": "Gâchette Gauche 0", "he_IL": "", "it_IT": "Grilletto sinistro 0", "ja_JP": "", "ko_KR": "좌측 트리거 0", "no_NO": "Venstre utløser 0", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Gatilho Esquerdo 0", "ru_RU": "Левый триггер 0", "sv_SE": "Vänster avtryckare 0", "th_TH": "", @@ -11230,14 +11405,14 @@ "el_GR": "", "en_US": "Right Trigger 0", "es_ES": "", - "fr_FR": "Gachette Droite 0", + "fr_FR": "Gâchette Droite 0", "he_IL": "", "it_IT": "Grilletto destro 0", "ja_JP": "", "ko_KR": "우측 트리거 0", "no_NO": "Høyre utløser 0", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Gatilho Direito 0", "ru_RU": "Правый триггер 0", "sv_SE": "Höger avtryckare 0", "th_TH": "", @@ -11255,14 +11430,14 @@ "el_GR": "", "en_US": "Left Trigger 1", "es_ES": "", - "fr_FR": "Gachette Gauche 1", + "fr_FR": "Gâchette Gauche 1", "he_IL": "", "it_IT": "Grilletto sinistro 1", "ja_JP": "", "ko_KR": "좌측 트리거 1", "no_NO": "Venstre utløser 1", "pl_PL": "", - "pt_BR": "", + "pt_BR": " Gatilho Esquerdo 1", "ru_RU": "Левый триггер 1", "sv_SE": "Vänster avtryckare 1", "th_TH": "", @@ -11280,14 +11455,14 @@ "el_GR": "", "en_US": "Right Trigger 1", "es_ES": "", - "fr_FR": "Gachette Droite 1", + "fr_FR": "Gâchette Droite 1", "he_IL": "", "it_IT": "Grilletto destro 1", "ja_JP": "", "ko_KR": "우측 트리거 1", "no_NO": "Høyre utløser 1", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Gatilho Direito 1", "ru_RU": "Правый триггер 1", "sv_SE": "Höger avtryckare 1", "th_TH": "", @@ -11312,7 +11487,7 @@ "ko_KR": "좌측 스틱", "no_NO": "Venstre styrespak", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Analógico Esquerdo", "ru_RU": "Левый стик", "sv_SE": "Vänster spak", "th_TH": "", @@ -11337,7 +11512,7 @@ "ko_KR": "우측 스틱", "no_NO": "Høyre styrespak", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Analógico Direito", "ru_RU": "Правый стик", "sv_SE": "Höger spak", "th_TH": "", @@ -11605,14 +11780,14 @@ "el_GR": "Μπορείτε να εισαγάγετε μία προσαρμοσμένη εικόνα προφίλ ή να επιλέξετε ένα avatar από το Firmware", "en_US": "You may import a custom profile image, or select an avatar from system firmware", "es_ES": "Puedes importar una imagen de perfil personalizada, o seleccionar un avatar del firmware de sistema", - "fr_FR": "Vous pouvez importer une image de profil personnalisée ou sélectionner un avatar à partir du firmware", + "fr_FR": "Vous pouvez importer une image de profil personnalisée ou sélectionner un avatar depuis le firmware système", "he_IL": "אתם יכולים לייבא תמונת פרופיל מותאמת אישית, או לבחור אווטאר מקושחת המערכת", "it_IT": "Puoi importare un'immagine profilo personalizzata o selezionare un avatar dal firmware del sistema", "ja_JP": "カスタム画像をインポート, またはファームウェア内のアバターを選択できます", "ko_KR": "사용자 지정 프로필 이미지를 가져오거나 시스템 펌웨어에서 아바타 선택 가능", "no_NO": "Du kan importere et tilpasset profilbilde, eller velge en avatar fra system fastvare", "pl_PL": "Możesz zaimportować niestandardowy obraz profilu lub wybrać awatar z firmware'u systemowego", - "pt_BR": "Você pode importar uma imagem customizada, ou selecionar um avatar do firmware", + "pt_BR": "Você pode importar uma imagem customizada, ou selecionar um avatar do Firmware", "ru_RU": "Вы можете импортировать собственное изображение или выбрать аватар из системной прошивки.", "sv_SE": "Du kan importera en anpassad profilbild eller välja en avatar från systemets firmware", "th_TH": "คุณสามารถนำเข้ารูปโปรไฟล์ที่กำหนดเองได้ หรือ เลือกรูปที่มีจากระบบ", @@ -11680,7 +11855,7 @@ "el_GR": "Διάλογος Εισαγωγής", "en_US": "Input Dialog", "es_ES": "Cuadro de diálogo de entrada", - "fr_FR": "Fenêtre d'entrée de texte", + "fr_FR": "Boîte de saisie", "he_IL": "דיאלוג קלט", "it_IT": "Finestra di input", "ja_JP": "入力ダイアログ", @@ -11830,7 +12005,7 @@ "el_GR": "Εισαγωγή Ονόματος Προφίλ", "en_US": "Please Enter a Profile Name", "es_ES": "Por favor elige un nombre de usuario", - "fr_FR": "Merci d'entrer un nom de profil", + "fr_FR": "Veuillez saisir un nom de profil.", "he_IL": "אנא הזינו שם לפרופיל", "it_IT": "Digita un nome profilo", "ja_JP": "プロファイル名を入力してください", @@ -12180,7 +12355,7 @@ "el_GR": "Εναλλαγή Αγαπημένου", "en_US": "Toggle Favorite", "es_ES": "Marcar favorito", - "fr_FR": "Ajouter/Retirer des favoris", + "fr_FR": "Basculer favori", "he_IL": "למתג העדפה", "it_IT": "Preferito", "ja_JP": "お気に入りを切り替え", @@ -12205,7 +12380,7 @@ "el_GR": "Εναλλαγή της Κατάστασης Αγαπημένο του Παιχνιδιού", "en_US": "Toggle Favorite status of Game", "es_ES": "Marca o desmarca el juego como favorito", - "fr_FR": "Définis un jeu comme faisant parti des favoris ou non", + "fr_FR": "Basculer le statut favori du jeu", "he_IL": "למתג סטטוס העדפה של משחק", "it_IT": "Segna il gioco come preferito", "ja_JP": "ゲームをお気に入りに含めるかどうかを切り替えます", @@ -12355,7 +12530,7 @@ "el_GR": "Δόνηση", "en_US": "Rumble", "es_ES": "Vibración", - "fr_FR": "Vibreur", + "fr_FR": "Vibration", "he_IL": "רטט", "it_IT": "Vibrazione", "ja_JP": "振動", @@ -12912,7 +13087,7 @@ "ko_KR": "업데이트가 취소되었습니다!", "no_NO": "Avbryter oppdatering!", "pl_PL": "Anulowanie aktualizacji!", - "pt_BR": "Cancelando atualização!", + "pt_BR": "Atualização Cancelada!", "ru_RU": "Отмена обновления...", "sv_SE": "Avbryter uppdatering!", "th_TH": "ยกเลิกการอัพเดต!", @@ -12930,7 +13105,7 @@ "el_GR": "Χρησιμοποιείτε ήδη την πιο ενημερωμένη έκδοση του Ryujinx!", "en_US": "You are already using the latest version of Ryujinx!", "es_ES": "¡Ya tienes la versión más reciente de Ryujinx!", - "fr_FR": "Vous utilisez déjà la version la plus récente de Ryujinx !", + "fr_FR": "Vous utilisez déjà la dernière version de Ryujinx !", "he_IL": "אתם כבר משתמשים בגרסה המעודכנת ביותר של ריוג'ינקס!", "it_IT": "Stai già usando la versione più recente di Ryujinx!", "ja_JP": "最新バージョンの Ryujinx を使用中です!", @@ -12948,53 +13123,28 @@ } }, { - "ID": "DialogUpdaterFailedToGetVersionMessage", + "ID": "DialogUpdaterConvertFailedServerMessage", "Translations": { - "ar_SA": "حدث خطأ أثناء محاولة الحصول على معلومات الإصدار من إصدار غيت هاب. يمكن أن يحدث هذا إذا تم تجميع إصدار جديد بواسطة إجراءات غيت هاب. جرب مجددا بعد دقائق.", - "de_DE": "Beim Versuch, Veröffentlichungs-Info von GitHub Release zu erhalten, ist ein Fehler aufgetreten. Dies kann aufgrund einer neuen Veröffentlichung, die gerade von GitHub Actions kompiliert wird, verursacht werden.", - "el_GR": "Προέκυψε ένα σφάλμα στη λήψη πληροφοριών έκδοσης από τα GitHub Releases. Αυτό δύναται να συμβεί αν μία έκδοση χτίζεται αυτή τη στιγμή στα GitHub Actions. Παρακαλούμε προσπαθήστε αργότερα.", - "en_US": "An error occurred while trying to retrieve release information from GitHub. This may happen if a new release is currently being compiled by GitHub Actions. Please try again in a few minutes.", - "es_ES": "Se ha producido un error al intentar obtener información de liberación de GitHub Release. Esto puede ser causado si una nueva versión está siendo compilada por GitHub Actions. Inténtalo de nuevo en unos minutos.", - "fr_FR": "Une erreur s'est produite lors de la tentative d'obtention des informations de publication de la version GitHub. Cela peut survenir lorsqu'une nouvelle version est en cours de compilation par GitHub Actions. Réessayez dans quelques minutes.", - "he_IL": "אירעה שגיאה בעת ניסיון לקבל עדכונים מ-גיטהב. זה יכול להיגרם אם הגרסה המעודכנת האחרונה נוצרה על ידי פעולות של גיטהב. נסה שוב בעוד מספר דקות.", - "it_IT": "Si è verificato un errore durante il tentativo di recuperare le informazioni sulla versione da GitHub Release. Ciò può verificarsi se una nuova versione è in fase di compilazione da GitHub Actions. Riprova tra qualche minuto.", - "ja_JP": "Github からのリリース情報取得時にエラーが発生しました. Github Actions でリリースファイルを作成中かもしれません. 後ほどもう一度試してみてください.", - "ko_KR": "GitHub에서 릴리스 정보를 검색하는 동안 오류가 발생했습니다. 현재 GitHub Actions에서 새 릴리스를 컴파일하는 중일 때 발생할 수 있습니다. 몇 분 후에 다시 시도해 주세요.", - "no_NO": "En feil oppstod ved forsøk på å få utgivelsesinformasjon fra GitHub Utgivelse. Dette kan forårsakes hvis en ny utgave blir samlet av GitHub Handlinger. Prøv igjen om noen minutter.", - "pl_PL": "Wystąpił błąd podczas próby uzyskania informacji o obecnej wersji z GitHub Release. Może to być spowodowane nową wersją kompilowaną przez GitHub Actions. Spróbuj ponownie za kilka minut.", - "pt_BR": "Ocorreu um erro ao tentar obter as informações de atualização do GitHub Release. Isso pode ser causado se uma nova versão estiver sendo compilado pelas Ações do GitHub. Tente novamente em alguns minutos.", - "ru_RU": "Произошла ошибка при попытке получить информацию о выпуске от GitHub Release. Это может быть вызвано тем, что в данный момент в GitHub Actions компилируется новый релиз. Повторите попытку позже.", - "sv_SE": "Ett fel inträffade vid försök att hämta information om utgåvan från GitHub. Detta kan hända om en ny utgåva har kompilerats av GitHub Actions. Försök igen om några minuter.", - "th_TH": "เกิดข้อผิดพลาดขณะพยายามรับข้อมูลเวอร์ชั่นจาก GitHub Release ปัญหานี้อาจเกิดขึ้นได้หากมีการรวบรวมเวอร์ชั่นใหม่โดย GitHub โปรดลองอีกครั้งในอีกไม่กี่นาทีข้างหน้า", - "tr_TR": "GitHub tarafından sürüm bilgileri alınırken bir hata oluştu. Eğer yeni sürüm için hazırlıklar yapılıyorsa bu hatayı almanız olasıdır. Lütfen birkaç dakika sonra tekrar deneyiniz.", - "uk_UA": "Під час спроби отримати інформацію про випуск із GitHub Release сталася помилка. Це може бути спричинено, якщо новий випуск компілюється GitHub Actions. Повторіть спробу через кілька хвилин.", - "zh_CN": "尝试从 Github 获取版本信息时无效,可能由于 GitHub Actions 正在编译新版本。\n请过一会再试。", - "zh_TW": "嘗試從 GitHub Release 取得發布資訊時發生錯誤。如果 GitHub Actions 正在編譯新版本,則可能會出現這種情況。請幾分鐘後再試一次。" - } - }, - { - "ID": "DialogUpdaterConvertFailedGithubMessage", - "Translations": { - "ar_SA": "فشل تحويل إصدار ريوجينكس المستلم من إصدار غيت هاب.", - "de_DE": "Fehler beim Konvertieren der erhaltenen Ryujinx-Version von GitHub Release.", - "el_GR": "Αποτυχία μετατροπής της ληφθείσας έκδοσης Ryujinx από την έκδοση GitHub.", - "en_US": "Failed to convert the Ryujinx version received from GitHub.", - "es_ES": "No se pudo convertir la versión de Ryujinx recibida de GitHub Release.", - "fr_FR": "Impossible de convertir la version reçue de Ryujinx depuis GitHub Release.", - "he_IL": "המרת גרסת ריוג'ינקס שהתקבלה מ-עדכון הגרסאות של גיטהב נכשלה.", - "it_IT": "La conversione della versione di Ryujinx ricevuta da GitHub Release è fallita.", - "ja_JP": "Github から取得した Ryujinx バージョンの変換に失敗しました.", - "ko_KR": "GitHub에서 받은 Ryujinx 버전을 변환하지 못했습니다.", - "no_NO": "Kan ikke konvertere mottatt Ryujinx-versjon fra GitHub Utgivelse.", - "pl_PL": "Nie udało się przekonwertować otrzymanej wersji Ryujinx z Github Release.", - "pt_BR": "Falha ao converter a versão Ryujinx recebida do GitHub.", - "ru_RU": "Не удалось преобразовать полученную версию Ryujinx из GitHub Release.", - "sv_SE": "Misslyckades med att konvertera mottagen Ryujinx-version från GitHub.", - "th_TH": "ไม่สามารถแปลงเวอร์ชั่น Ryujinx ที่ได้รับจาก GitHub Release", - "tr_TR": "Github Release'den alınan Ryujinx sürümü dönüştürülemedi.", - "uk_UA": "Не вдалося конвертувати отриману версію Ryujinx із випуску GitHub.", - "zh_CN": "无法切换至从 GitHub 接收到的新版 Ryujinx 模拟器。", - "zh_TW": "無法轉換從 GitHub Release 接收到的 Ryujinx 版本。" + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Failed to convert the Ryujinx version received from the update server.", + "es_ES": "", + "fr_FR": "Échec de la conversion de la version de Ryujinx reçue du serveur de mise à jour.", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "업데이트 서버에서 받은 Ryujinx 버전을 변환하는 데 실패했습니다.", + "no_NO": "Kunne ikke konvertere Ryujinx-versjonen som ble mottatt fra oppdateringsserveren.", + "pl_PL": "", + "pt_BR": "Falha em atualizar a versão do Ryujinx recebida do servidor de atualização.", + "ru_RU": "", + "sv_SE": "Det gick inte att konvertera Ryujinx-versionen som mottogs från uppdateringsservern.", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "无法转换从更新服务器接收的 Ryujinx 版本。", + "zh_TW": "無法轉換從更新伺服器接收的 Ryujinx 版本。" } }, { @@ -13030,7 +13180,7 @@ "el_GR": "Παρακαλώ περιμένετε, ο εξομοιωτής επανεκκινείται", "en_US": "Please wait, the emulator is restarting", "es_ES": "Por favor, espere, el emulador se está reiniciando", - "fr_FR": "Veuillez patienter, l'émulateur est en train de redémarrer", + "fr_FR": "Veuillez patienter, l’émulateur redémarre", "he_IL": "אנא המתן, המחקה מתארגן מחדש", "it_IT": "Attendere prego, l'emulatore si sta riavviando", "ja_JP": "お待ちください、エミュレーターが再起動しています", @@ -13230,7 +13380,7 @@ "el_GR": "Επαληθεύστε ότι έχετε σύνδεση στο Διαδίκτυο που λειτουργεί!", "en_US": "Please verify that you have a working Internet connection!", "es_ES": "¡Por favor, verifica que tu conexión a Internet funciona!", - "fr_FR": "Veuillez vérifier que vous disposez d'une connexion Internet fonctionnelle !", + "fr_FR": "Veuillez vérifier que vous avez une connexion Internet fonctionnelle !", "he_IL": "אנא ודא שיש לך חיבור אינטרנט תקין!", "it_IT": "Verifica di avere una connessione ad Internet funzionante!", "ja_JP": "インターネット接続が正常動作しているか確認してください!", @@ -13355,7 +13505,7 @@ "el_GR": "Θέλετε να κάνετε επανεκκίνηση", "en_US": "Do you want to restart", "es_ES": "¿Quieres reiniciar?", - "fr_FR": "Voulez-vous redémarrer", + "fr_FR": "Voulez-vous redémarrer ?", "he_IL": "האם ברצונך להפעיל מחדש?", "it_IT": "Vuoi riavviare?", "ja_JP": "再起動しますか", @@ -13580,7 +13730,7 @@ "el_GR": "Άνοιγμα Παραθύρου Ρυθμίσεων", "en_US": "Open Settings Window", "es_ES": "Abrir ventana de opciones", - "fr_FR": "Ouvrir la fenêtre de configuration", + "fr_FR": "Ouvrir la fenêtre des paramètres", "he_IL": "פתח את חלון ההגדרות", "it_IT": "Apri finestra delle impostazioni", "ja_JP": "設定ウインドウを開く", @@ -13930,7 +14080,7 @@ "el_GR": "Διαγραφή Προφίλ", "en_US": "Deleting Profile", "es_ES": "Eliminando perfil", - "fr_FR": "Supprimer le profil", + "fr_FR": "Suppression du profil", "he_IL": "מוחק פרופיל", "it_IT": "Eliminazione profilo", "ja_JP": "プロファイルを削除中", @@ -14005,7 +14155,7 @@ "el_GR": "Πρόκειται να διαγράψετε την προσωρινή μνήμη PPTC για :\n\n{0}\n\nΕίστε βέβαιοι ότι θέλετε να συνεχίσετε;", "en_US": "You are about to queue a PPTC rebuild on the next boot of:\n\n{0}\n\nAre you sure you want to proceed?", "es_ES": "Vas a borrar la caché de PPTC para:\n\n{0}\n\n¿Estás seguro de querer continuar?", - "fr_FR": "Vous êtes sur le point de mettre en file d'attente une reconstruction PPTC au prochain démarrage de :\n\n{0}\n\nÊtes-vous sûr de vouloir continuer ?", + "fr_FR": "Vous êtes sur le point de programmer une reconstruction PPTC au prochain démarrage de :\n\n{0}\n\nÊtes-vous sûr de vouloir continuer ?", "he_IL": "אם תמשיכו אתם עומדים לגרום לבנייה מחדש של מטמון ה-PPTC עבור:\n\n{0}", "it_IT": "Stai per accodare la rigenerazione della cache PPTC al prossimo avvio per:\n\n{0}\n\nSei sicuro di voler proseguire?", "ja_JP": "次回起動時に PPTC を再構築します:\n\n{0}\n\n実行してよろしいですか?", @@ -14055,7 +14205,7 @@ "el_GR": "", "en_US": "You are about to purge all PPTC data from:\n\n{0}\n\nAre you sure you want to proceed?", "es_ES": "", - "fr_FR": "", + "fr_FR": "Vous êtes sur le point de supprimer toutes les données PPTC de :\n\n{0}\n\nÊtes-vous sûr de vouloir continuer ?", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -14080,7 +14230,7 @@ "el_GR": "Πρόκειται να διαγράψετε την προσωρινή μνήμη Shader για :\n\n{0}\n\nΕίστε βέβαιοι ότι θέλετε να συνεχίσετε;", "en_US": "You are about to delete the Shader cache for :\n\n{0}\n\nAre you sure you want to proceed?", "es_ES": "Vas a borrar la caché de sombreadores para:\n\n{0}\n\n¿Estás seguro de querer continuar?", - "fr_FR": "Vous êtes sur le point de supprimer le cache du Shader pour :\n\n{0}\n\nÊtes-vous sûr de vouloir continuer ?", + "fr_FR": "Vous êtes sur le point de supprimer le cache des shaders pour :\n\n{0}\n\nÊtes-vous sûr de vouloir continuer ?", "he_IL": "אם תמשיכו אתם עומדים למחוק את מטמון ההצללות עבור:\n\n{0}", "it_IT": "Stai per eliminare la cache degli shader per:\n\n{0}\n\nSei sicuro di voler proseguire?", "ja_JP": "シェーダーキャッシュを破棄しようとしています:\n\n{0}\n\n実行してよろしいですか?", @@ -14105,7 +14255,7 @@ "el_GR": "Σφάλμα κατά την εκκαθάριση προσωρινής μνήμης Shader στο {0}: {1}", "en_US": "Error purging Shader cache at {0}: {1}", "es_ES": "Error purgando la caché de sombreadores en {0}: {1}", - "fr_FR": "Erreur lors de la purge du cache du Shader à {0}: {1}", + "fr_FR": "Erreur lors de l’élimination du cache des shaders à {0} : {1}", "he_IL": "שגיאה בניקוי מטמון ההצללות ב-{0}: {1}", "it_IT": "Errore nell'eliminazione della cache degli shader a {0}: {1}", "ja_JP": "シェーダーキャッシュ破棄エラー {0}: {1}", @@ -14430,7 +14580,7 @@ "el_GR": "", "en_US": "\n\nThis may replace some of the current installed Keys.", "es_ES": "\n\nEsto puede reemplazar algunas de las Keys actualmente instaladas.", - "fr_FR": "\n\nCela pourrait remplacer les clés qui sont installés.", + "fr_FR": "\n\nCela peut remplacer certaines des clés actuellement installées.", "he_IL": "", "it_IT": "\n\nAlcune delle chiavi già installate potrebbero essere sovrascritte.", "ja_JP": "", @@ -14455,7 +14605,7 @@ "el_GR": "", "en_US": "\n\nDo you want to continue?", "es_ES": "\n\nDeseas continuar?", - "fr_FR": "\n\nVoulez-vous continuez ?", + "fr_FR": "\n\nVoulez-vous continuer ?", "he_IL": "", "it_IT": "\n\nVuoi continuare?", "ja_JP": "", @@ -14605,7 +14755,7 @@ "el_GR": "Έχετε κάνει αλλαγές σε αυτό το προφίλ χρήστη που δεν έχουν αποθηκευτεί.", "en_US": "You have made changes to this user profile that have not been saved.", "es_ES": "Ha realizado cambios en este perfil de usuario que no han sido guardados.", - "fr_FR": "Vous avez effectué des modifications sur ce profil d'utilisateur qui n'ont pas été enregistrées.", + "fr_FR": "Vous avez apporté des modifications à ce profil utilisateur qui n'ont pas été enregistrées.", "he_IL": "ביצעת שינויים בפרופיל משתמש זה שלא נשמרו.", "it_IT": "Hai apportato modifiche a questo profilo utente che non sono state salvate.", "ja_JP": "保存されていないユーザプロファイルを変更しました.", @@ -14630,7 +14780,7 @@ "el_GR": "Θέλετε να απορρίψετε τις αλλαγές σας;", "en_US": "Do you want to discard your changes?", "es_ES": "¿Quieres descartar los cambios realizados?", - "fr_FR": "Voulez-vous annuler les modifications ?", + "fr_FR": "Voulez-vous annuler vos modifications ?", "he_IL": "האם ברצונך למחוק את השינויים האחרונים?", "it_IT": "Vuoi scartare le modifiche?", "ja_JP": "変更を破棄しますか?", @@ -14705,7 +14855,7 @@ "el_GR": "", "en_US": "{0}. Errored File: {1}", "es_ES": "{0}. Archivo con error: {1}", - "fr_FR": "{0}. Fichier erroné : {1}", + "fr_FR": "{0}. Fichier avec erreur : {1}", "he_IL": "{0}. קובץ שגוי: {1}", "it_IT": "{0}. Errore file: {1}", "ja_JP": "{0}. エラー発生ファイル: {1}", @@ -14780,7 +14930,7 @@ "el_GR": "", "en_US": "Failed to Delete: Could not find the parent directory for mod \"{0}\"!", "es_ES": "Error al eliminar: ¡No se pudo encontrar el directorio principal para el mod \"{0}\"!", - "fr_FR": "Impossible de supprimer : impossible de trouver le répertoire parent pour le mod \"{0} \" !", + "fr_FR": "Échec de la suppression : impossible de trouver le répertoire parent du mod \"{0} \" !", "he_IL": "נכשל למחוק: לא היה ניתן למצוא את תיקיית האב למוד \"{0}\"!\n", "it_IT": "Eliminazione non riuscita: impossibile trovare la directory superiore per la mod \"{0}\"!", "ja_JP": "削除に失敗しました: Mod \"{0}\" の親ディレクトリが見つかりませんでした!", @@ -14855,7 +15005,7 @@ "el_GR": "Για βέλτιστη απόδοση, συνιστάται η απενεργοποίηση καταγραφής εντοπισμού σφαλμάτων. Θέλετε να απενεργοποιήσετε την καταγραφή τώρα;", "en_US": "For optimal performance, it's recommended to disable trace logging. Would you like to disable trace logging now?", "es_ES": "Para un rendimiento óptimo, se recomienda deshabilitar los registros debug. ¿Quieres deshabilitarlos ahora?", - "fr_FR": "Pour des performances optimales, il est recommandé de désactiver la journalisation des traces. Souhaitez-vous désactiver la journalisation des traces maintenant ?", + "fr_FR": "Pour des performances optimales, il est recommandé de désactiver la journalisation de trace. Souhaitez-vous désactiver la journalisation de trace maintenant ?", "he_IL": "לביצועים מיטביים, מומלץ להשבית את רישום המעקב. האם ברצונך להשבית את רישום המעקב כעת?", "it_IT": "Per prestazioni ottimali, si raccomanda di disabilitare il trace logging. Vuoi disabilitarlo adesso?", "ja_JP": "パフォーマンス最適化のためには,トレースロギングを無効にすることを推奨します. トレースロギングを無効にしてよろしいですか?", @@ -15030,7 +15180,7 @@ "el_GR": "Το Ryujinx πρέπει να επανεκκινηθεί αφού αλλάξει αυτή η επιλογή για να εφαρμοστεί πλήρως. Ανάλογα με την πλατφόρμα σας, μπορεί να χρειαστεί να απενεργοποιήσετε με μη αυτόματο τρόπο το multithreading του ίδιου του προγράμματος οδήγησης όταν χρησιμοποιείτε το Ryujinx.", "en_US": "Ryujinx must be restarted after changing this option for it to apply fully. Depending on your platform, you may need to manually disable your driver's own multithreading when using Ryujinx's.", "es_ES": "Ryujinx debe reiniciarse para aplicar este cambio. Dependiendo de tu plataforma, puede que tengas que desactivar manualmente la optimización enlazada de tus controladores gráficos para usar el multihilo de Ryujinx.", - "fr_FR": "Ryujinx doit être redémarré après avoir changé cette option pour qu'elle s'applique complètement. Selon votre plate-forme, vous devrez peut-être désactiver manuellement le multithreading de votre pilote lorsque vous utilisez Ryujinx.", + "fr_FR": "Ryujinx doit être redémarré après avoir modifié cette option pour que les changements soient pleinement pris en compte. Selon votre plateforme, il se peut que vous deviez désactiver manuellement le multithreading propre à votre pilote lorsque vous utilisez celui de Ryujinx", "he_IL": "יש להפעיל מחדש את ריוג'ינקס לאחר שינוי אפשרות זו כדי שהיא תחול במלואה. בהתאם לפלטפורמה שלך, ייתכן שיהיה עליך להשבית ידנית את ריבוי ההליכים של ההתקן שלך בעת השימוש ב-ריוג'ינקס.", "it_IT": "Ryujinx deve essere riavviato dopo aver cambiato questa opzione per applicarla completamente. A seconda della tua piattaforma, potrebbe essere necessario disabilitare manualmente il multithreading del driver quando usi quello di Ryujinx.", "ja_JP": "このオプションの変更を完全に適用するには Ryujinx の再起動が必要です. プラットフォームによっては, Ryujinx のものを使用する前に手動でドライバ自身のマルチスレッディングを無効にする必要があるかもしれません.", @@ -15305,7 +15455,7 @@ "el_GR": "Παύση", "en_US": "Pause", "es_ES": "Pausar", - "fr_FR": "Suspendre", + "fr_FR": "", "he_IL": "הפסק", "it_IT": "Metti in pausa", "ja_JP": "一時停止", @@ -15355,7 +15505,7 @@ "el_GR": "Κάντε κλικ για να ανοίξετε τον ιστότοπο Ryujinx στο προεπιλεγμένο πρόγραμμα περιήγησης.", "en_US": "Click to open the Ryujinx website in your default browser.", "es_ES": "Haz clic para abrir el sitio web de Ryujinx en tu navegador predeterminado.", - "fr_FR": "Cliquez pour ouvrir le site de Ryujinx dans votre navigateur par défaut.", + "fr_FR": "Cliquez pour ouvrir le site de Ryujinx dans votre navigateur par défaut", "he_IL": "לחץ כדי לפתוח את אתר ריוג'ינקס בדפדפן ברירת המחדל שלך.", "it_IT": "Clicca per aprire il sito web di Ryujinx nel tuo browser predefinito.", "ja_JP": "クリックするとデフォルトのブラウザで Ryujinx のウェブサイトを開きます.", @@ -15380,7 +15530,7 @@ "el_GR": "Το Ryujinx δεν είναι συνδεδεμένο με τη Nintendo™,\nούτε με κανέναν από τους συνεργάτες της, με οποιονδήποτε τρόπο.", "en_US": "Ryujinx is not affiliated with Nintendo™,\nor any of its partners, in any way.", "es_ES": "Ryujinx no tiene afiliación alguna con Nintendo™,\nni con ninguno de sus socios.", - "fr_FR": "Ryujinx n'est pas affilié à Nintendo™,\nou à aucun de ses partenaires, de quelque manière que ce soit.", + "fr_FR": "Ryujinx n’est en aucun cas affilié à Nintendo™,\nni à aucun de ses partenaires, de quelque manière que ce soit.", "he_IL": "ריוג'ינקס אינה מזוהת עם נינטנדו,\nאו שוטפייה בכל דרך שהיא.", "it_IT": "Ryujinx non è affiliato con Nintendo™,\no i suoi partner, in alcun modo.", "ja_JP": "Ryujinx は Nintendo™ および\nそのパートナー企業とは一切関係ありません.", @@ -15503,23 +15653,23 @@ "ar_SA": "", "de_DE": "", "el_GR": "", - "en_US": "Ryujinx is an emulator for the Nintendo Switch™.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.", + "en_US": "Ryujinx is an emulator for the Nintendo Switch™ 1.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitLab or Discord.", "es_ES": "", - "fr_FR": "Ryujinx est un émulateur pour la Nintendo Switch™.\nObtenez le dernières nouvelles sur le Discord.\nLes développeurs qui veulent contribuer peuvent en savoir plus sur notre GitHub ou Discord.", + "fr_FR": "Ryujinx est un émulateur pour la Nintendo Switch™ 1.\nObtenez les dernières nouvelles sur notre Discord.\nLes développeurs souhaitant contribuer peuvent en savoir plus sur notre GitLab ou Discord.", "he_IL": "", - "it_IT": "Ryujinx è un emulatore della console Nintendo Switch™.\nRimani aggiornato sulle ultime novità nel nostro server Discord.\nGli sviluppatori interessati a contribuire possono trovare maggiori informazioni su Discord o sulla nostra pagina GitHub.", + "it_IT": "Ryujinx è un emulatore della console Nintendo Switch™ 1.\nRimani aggiornato sulle ultime novità nel nostro server Discord.\nGli sviluppatori interessati a contribuire possono trovare maggiori informazioni su Discord o sulla nostra pagina GitLab.", "ja_JP": "", - "ko_KR": "Ryujinx는 Nintendo Switch™용 에뮬레이터입니다.\n모든 최신 소식을 Discord에서 확인하세요.\n기여에 관심이 있는 개발자는 GitHub 또는 Discord에서 자세한 내용을 확인할 수 있습니다.", - "no_NO": "Ryujinx er en emulator for Nintendo SwitchTM.\nVennligst støtt oss på Patreon.\nFå alle de siste nyhetene på vår Twitter eller Discord.\nUtviklere som er interessert i å bidra kan finne ut mer på GitHub eller Discord.", + "ko_KR": "Ryujinx는 Nintendo Switch™ 1용 에뮬레이터입니다.\n모든 최신 소식을 Discord에서 확인하세요.\n기여에 관심이 있는 개발자는 GitLab 또는 Discord에서 자세한 내용을 확인할 수 있습니다.", + "no_NO": "Ryujinx er en emulator for Nintendo Switch™ 1\nVennligst støtt oss på Patreon.\nFå alle de siste nyhetene på vår Twitter eller Discord.\nUtviklere som er interessert i å bidra kan finne ut mer på GitLab eller Discord.", "pl_PL": "", - "pt_BR": "Ryujinx é um emulador de Nintendo Switch™.\nReceba todas as últimas notícias em nosso Discord.\nDesenvolvedores interessados em contribuir podem descobrir mais em nosso GitHub ou Discord.", - "ru_RU": "Ryujinx - это эмулятор для Nintendo Switch™.\nПолучайте все последние новости разработки в нашем Discord.\nРазработчики, заинтересованные в участии, могут узнать больше на нашем GitHub или Discord.", - "sv_SE": "Ryujinx är en emulator för Nintendo Switch™.\nFå de senaste nyheterna via vår Discord.\nUtvecklare som är intresserade att bidra kan hitta mer info på vår GitHub eller Discord.", + "pt_BR": "Ryujinx é um emulador de Nintendo Switch™ 1.\nReceba todas as últimas notícias em nosso Discord.\nDesenvolvedores interessados em contribuir podem descobrir mais em nosso GitLab ou Discord.", + "ru_RU": "Ryujinx - это эмулятор для Nintendo Switch™ 1.\nПолучайте все последние новости разработки в нашем Discord.\nРазработчики, заинтересованные в участии, могут узнать больше на нашем GitLab или Discord.", + "sv_SE": "Ryujinx är en emulator för Nintendo Switch™ 1.\nFå de senaste nyheterna via vår Discord.\nUtvecklare som är intresserade att bidra kan hitta mer info på vår GitLab eller Discord.", "th_TH": "", "tr_TR": "", - "uk_UA": "Ryujinx — це емулятор для Nintendo Switch™.\nОстанні новини можна отримати в нашому Discord.\nРозробники, що бажають долучитись до розробки та зробити свій внесок, можуть отримати більше інформації на нашому GitHub або в Discord.", - "zh_CN": "Ryujinx 是一个 Nintendo Switch™ 模拟器。\n有兴趣做出贡献的开发者可以在我们的 GitHub 或 Discord 上了解更多信息。\n", - "zh_TW": "Ryujinx 是一款 Nintendo Switch™ 模擬器。\n關注我們的 Discord 取得所有最新消息。\n對於有興趣貢獻的開發者,可以在我們的 GitHub 或 Discord 上了解更多資訊。" + "uk_UA": "Ryujinx — це емулятор для Nintendo Switch™ 1.\nОстанні новини можна отримати в нашому Discord.\nРозробники, що бажають долучитись до розробки та зробити свій внесок, можуть отримати більше інформації на нашому GitLab або в Discord.", + "zh_CN": "Ryujinx 是一个 Nintendo Switch™ 1 模拟器。\n有兴趣做出贡献的开发者可以在我们的 GitLab 或 Discord 上了解更多信息。\n", + "zh_TW": "Ryujinx 是一款 Nintendo Switch™ 1 模擬器。\n關注我們的 Discord 取得所有最新消息。\n對於有興趣貢獻的開發者,可以在我們的 GitLab 或 Discord 上了解更多資訊。" } }, { @@ -16155,7 +16305,7 @@ "el_GR": "Ενεργοποιεί ή απενεργοποιεί την Εμπλουτισμένη Παρουσία σας στο Discord", "en_US": "Choose whether or not to display Ryujinx on your \"currently playing\" Discord activity", "es_ES": "Elige si muestras Ryujinx o no en tu actividad de Discord cuando lo estés usando", - "fr_FR": "Choisissez d'afficher ou non Ryujinx sur votre activité « en cours de jeu » Discord", + "fr_FR": "Choisissez d’afficher ou non Ryujinx dans votre activité Discord « en cours de jeu »", "he_IL": "בחרו להציג את ריוג'ינקס או לא בפעילות הדיסקורד שלכם \"משוחק כרגע\".", "it_IT": "Scegli se mostrare o meno Ryujinx nella tua attività su Discord", "ja_JP": "Discord の \"現在プレイ中\" アクティビティに Ryujinx を表示するかどうかを選択します", @@ -16255,7 +16405,7 @@ "el_GR": "", "en_US": "Enter an autoload directory to add to the list", "es_ES": "Elige un directorio de carga automática para agregar a la lista", - "fr_FR": "Entrez un répertoire de mises à jour/DLC à ajouter à la liste", + "fr_FR": "Saisissez un répertoire d’autochargement à ajouter à la liste", "he_IL": "", "it_IT": "Inserisci una cartella di caricamento automatico da aggiungere alla lista", "ja_JP": "", @@ -16280,7 +16430,7 @@ "el_GR": "", "en_US": "Add an autoload directory to the list", "es_ES": "Agregar un directorio de carga automática a la lista", - "fr_FR": "Ajouter un répertoire de mises à jour/DLC à la liste", + "fr_FR": "Ajouter un répertoire d’autochargement à la liste", "he_IL": "", "it_IT": "Aggiungi una cartella di caricamento automatico alla lista", "ja_JP": "", @@ -16305,7 +16455,7 @@ "el_GR": "", "en_US": "Remove selected autoload directory", "es_ES": "Eliminar el directorio de carga automática seleccionado", - "fr_FR": "Supprimer le répertoire de mises à jour/DLC sélectionné", + "fr_FR": "Supprimer le répertoire d’autochargement sélectionné", "he_IL": "", "it_IT": "Rimuovi la cartella di caricamento automatico selezionata", "ja_JP": "", @@ -16330,7 +16480,7 @@ "el_GR": "Ενεργοποίηση ή απενεργοποίηση προσαρμοσμένων θεμάτων στο GUI", "en_US": "Use a custom Avalonia theme for the GUI to change the appearance of the emulator menus", "es_ES": "Activa o desactiva los temas personalizados para la interfaz", - "fr_FR": "Utilisez un thème personnalisé Avalonia pour modifier l'apparence des menus de l'émulateur", + "fr_FR": "Utilisez un thème Avalonia personnalisé pour modifier l'apparence des menus de l'émulateur", "he_IL": "השתמש בעיצוב מותאם אישית של אבלוניה עבור ה-ממשק הגראפי כדי לשנות את המראה של תפריטי האמולטור", "it_IT": "Utilizza un tema di Avalonia personalizzato per cambiare l'aspetto dei menù dell'emulatore", "ja_JP": "エミュレータのメニュー外観を変更するためカスタム Avalonia テーマを使用します", @@ -16380,7 +16530,7 @@ "el_GR": "Αναζητήστε ένα προσαρμοσμένο θέμα GUI", "en_US": "Browse for a custom GUI theme", "es_ES": "Busca un tema personalizado para la interfaz", - "fr_FR": "Parcourir vers un thème personnalisé pour l'interface utilisateur", + "fr_FR": "Parcourir un thème personnalisé pour l’interface graphique", "he_IL": "חפש עיצוב ממשק גראפי מותאם אישית", "it_IT": "Scegli un tema dell'interfaccia personalizzato", "ja_JP": "カスタム GUI テーマを参照します", @@ -16397,6 +16547,31 @@ "zh_TW": "瀏覽自訂 GUI 佈景主題" } }, + { + "ID": "UseGlobalInputTooltip", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "If this option is enabled in custom settings, the global input configuration will be used.\n\nIn the global settings: you can enable or disable it as needed; this setting will be inherited by any new custom configurations created.", + "es_ES": "", + "fr_FR": "Si cette option est activée dans les paramètres personnalisés, la configuration d’entrée globale sera utilisée.\n\nDans les paramètres globaux, vous pouvez l’activer ou la désactiver selon vos besoins ; ce réglage sera alors hérité par toutes les nouvelles configurations personnalisées créées", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "사용자 지정 설정에서 이 옵션을 활성화하면 전역 입력 구성이 사용됩니다.\n\n전역 설정에서 필요에 따라 활성화하거나 비활성화할 수 있습니다. 이 설정은 새로 생성된 모든 사용자 지정 구성에 상속됩니다.", + "no_NO": "", + "pl_PL": "", + "pt_BR": "Se esta opção está ativada nas configurações customizadas, as configurações globais de entrada serão usadas.\n\nNas configurações globais: você pode ativar ou desativá-las se necessário; está configuração será herdada por qualquer nova configuração customizada criada.", + "ru_RU": "Если эта опция включена в пользовательских настройках, будет использована глобальная конфигурация ввода.\n\nВ глобальных настройках: переключите эту опцию по своему усмотрению, это будет унаследовано для вновь созданых пользовательских конфигураций", + "sv_SE": "Om det här alternativet är aktiverat i anpassade inställningar kommer den globala inmatningskonfigurationen att användas.\n\nI de globala inställningarna: du kan aktivera eller inaktivera det efter behov; den här inställningen kommer att ärvas av alla nya anpassade konfigurationer som skapas.", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "如果在自定义设置中启用了此选项,则将使用全局输入配置。\n\n在全局设置中: 您可以根据需要启用或禁用它;之后创建的任何自定义配置都将继承此设置。", + "zh_TW": "如果在自訂設定啟用了此選項,則將使用全域輸入配置。\n\n在全域設定中:你可以根據需要啟用或停用它;之後建立的任何自訂配置都將繼承此設定。" + } + }, { "ID": "DockModeToggleTooltip", "Translations": { @@ -16405,11 +16580,11 @@ "el_GR": "Ενεργοποιήστε ή απενεργοποιήστε τη λειτουργία σύνδεσης", "en_US": "Docked mode makes the emulated system behave as a docked Nintendo Switch. This improves graphical fidelity in most games. Conversely, disabling this will make the emulated system behave as a handheld Nintendo Switch, reducing graphics quality.\n\nConfigure player 1 controls if planning to use docked mode; configure handheld controls if planning to use handheld mode.\n\nLeave ON if unsure.", "es_ES": "El modo dock o modo TV hace que la consola emulada se comporte como una Nintendo Switch en su dock. Esto mejora la calidad gráfica en la mayoría de los juegos. Del mismo modo, si lo desactivas, el sistema emulado se comportará como una Nintendo Switch en modo portátil, reduciendo la cálidad de los gráficos.\n\nConfigura los controles de \"Jugador\" 1 si planeas jugar en modo dock/TV; configura los controles de \"Portátil\" si planeas jugar en modo portátil.\n\nActívalo si no sabes qué hacer.", - "fr_FR": "Le mode station d'accueil permet à la console émulée de se comporter comme une Nintendo Switch en mode station d'accueil, ce qui améliore la fidélité graphique dans la plupart des jeux. Inversement, la désactivation de cette option rendra la console émulée comme une console Nintendo Switch portable, réduisant la qualité graphique.\n\nConfigurer les controles du joueur 1 si vous prévoyez d'utiliser le mode station d'accueil; configurez les commandes portable si vous prévoyez d'utiliser le mode portable.\n\nLaissez ACTIVER si vous n'êtes pas sûr.", + "fr_FR": "Le mode docké fait que le système émulé se comporte comme une Nintendo Switch en mode dock. Cela améliore la qualité graphique dans la plupart des jeux. À l’inverse, désactiver ce mode fera que le système émulé se comporte comme une Nintendo Switch en mode portable, ce qui réduit la qualité graphique.\n\nConfigurez les contrôles du joueur 1 si vous prévoyez d’utiliser le mode docké ; configurez les contrôles pour le mode portable si vous comptez utiliser ce dernier.\n\nLaissez ACTIVÉ si vous n’êtes pas sûr..", "he_IL": "מצב עגינה גורם למערכת המדומה להתנהג כ-נינטנדו סוויץ' בתחנת עגינתו. זה משפר את הנאמנות הגרפית ברוב המשחקים.\n לעומת זאת, השבתה של תכונה זו תגרום למערכת המדומה להתנהג כ- נינטנדו סוויץ' נייד, ולהפחית את איכות הגרפיקה.\n\nהגדירו את שלט שחקן 1 אם אתם מתכננים להשתמש במצב עגינה; הגדירו את פקדי כף היד אם אתם מתכננים להשתמש במצב נייד.\n\nמוטב להשאיר דלוק אם אתם לא בטוחים.", "it_IT": "La modalità TV fa sì che il sistema emulato si comporti come una Nintendo Switch posizionata nella sua base. Ciò migliora la qualità grafica nella maggior parte dei giochi. Al contrario, disabilitandola il sistema emulato si comporterà come una Nintendo Switch in modalità portatile, riducendo la qualità grafica.\n\nConfigura i controlli del giocatore 1 se intendi usare la modalità TV; configura i controlli della modalità portatile se intendi usare quest'ultima.\n\nNel dubbio, lascia l'opzione attiva.", "ja_JP": "有効にすると,ドッキングされた Nintendo Switch をエミュレートします.多くのゲームではグラフィックス品質が向上します.\n無効にすると,携帯モードの Nintendo Switch をエミュレートします.グラフィックスの品質は低下します.\n\nドッキングモード有効ならプレイヤー1の,無効なら携帯の入力を設定してください.\n\nよくわからない場合はオンのままにしてください.", - "ko_KR": "도킹 모드를 사용하면 에뮬레이트된 시스템이 도킹된 Nintendo Switch처럼 동작합니다. 이 경우, 대부분의 게임에서 그래픽 충실도를 향상시킵니다. 반대로 이 기능을 비활성화하면 에뮬레이트된 시스템이 휴대용 Nintendo Switch처럼 작동하여 그래픽 품질이 저하됩니다.\n\n도킹 모드를 사용할 계획이라면 플레이어 1 컨트롤을 구성하세요. 휴대용 모드를 사용하려는 경우 휴대용 컨트롤을 구성하십시오.\n\n모르면 켬으로 두세요.", + "ko_KR": "도킹 모드를 사용하면 에뮬레이트된 시스템이 도킹된 Nintendo Switch처럼 동작합니다. 이 경우, 대부분의 게임에서 그래픽 충실도를 향상시킵니다. 반대로 이 기능을 비활성화하면 에뮬레이트된 시스템이 휴대용 Nintendo Switch처럼 작동하여 그래픽 품질이 저하됩니다.\n\n도킹 모드를 사용할 계획이라면 플레이어 1 컨트롤을 구성하세요. 휴대용 모드를 사용하려는 경우 휴대용 컨트롤을 구성하십시오.\n\n모르면 체크 상태로 두세요.", "no_NO": "Forankret modus gjør at systemet oppføre seg som en forankret Nintendo Switch. Dette forbedrer grafikkkvaliteten i de fleste spill. Motsatt vil deaktivering av dette gjøre at systemet oppføre seg som en håndholdt Nintendo Switch, noe som reduserer grafikkkvaliteten.\n\nKonfigurer spiller 1 kontroller hvis du planlegger å bruke forankret modus; konfigurer håndholdte kontroller hvis du planlegger å bruke håndholdte modus.\n\nLa PÅ hvis du er usikker.", "pl_PL": "Tryb Zadokowany sprawia, że emulowany system zachowuje się jak zadokowany Nintendo Switch. Poprawia to jakość grafiki w większości gier. I odwrotnie, wyłączenie tej opcji sprawi, że emulowany system będzie zachowywał się jak przenośny Nintendo Switch, zmniejszając jakość grafiki.\n\nSkonfiguruj sterowanie gracza 1, jeśli planujesz używać trybu Zadokowanego; Skonfiguruj sterowanie przenośne, jeśli planujesz używać trybu przenośnego.\n\nPozostaw WŁĄCZONY, jeśli nie masz pewności.", "pt_BR": "O modo TV faz o sistema emulado se comportar como um Nintendo Switch na TV, o que melhora a fidelidade gráfica na maioria dos jogos. Por outro lado, desativar essa opção fará o sistema emulado se comportar como um Nintendo Switch portátil, reduzindo a qualidade gráfica.\n\nConfigure os controles do jogador 1 se planeja usar o modo TV; configure os controles de portátil se planeja usar o modo Portátil.\n\nMantenha ativado se estiver em dúvida.", @@ -16430,11 +16605,11 @@ "el_GR": "", "en_US": "Direct keyboard access (HID) support. Provides games access to your keyboard as a text entry device.\n\nOnly works with games that natively support keyboard usage on Switch hardware.\n\nLeave OFF if unsure.", "es_ES": "Soporte de acceso directo al teclado (HID). Proporciona a los juegos acceso a su teclado como dispositivo de entrada de texto.\n\nSolo funciona con juegos que permiten de forma nativa el uso del teclado en el hardware de Switch.\n\nDesactívalo si no sabes qué hacer.", - "fr_FR": "Prise en charge de l'accès direct au clavier (HID). Permet aux jeux d'accéder à votre clavier comme périphérique de saisie de texte.\n\nFonctionne uniquement avec les jeux prenant en charge nativement l'utilisation du clavier sur le matériel Switch.\n\nLaissez désactiver si vous n'êtes pas sûr.", + "fr_FR": "Prise en charge de l’accès direct au clavier (HID). Permet aux jeux d’accéder à votre clavier comme périphérique de saisie de texte.\n\nFonctionne uniquement avec les jeux qui supportent nativement l’utilisation du clavier sur la console Switch.\n\nLaissez DÉSACTIVÉ si vous n'êtes pas sûr.", "he_IL": "", "it_IT": "Supporto per l'accesso diretto alla tastiera (HID). Fornisce ai giochi l'accesso alla tastiera come dispositivo di inserimento del testo.\n\nFunziona solo con i giochi che supportano nativamente l'utilizzo della tastiera su hardware Switch.\n\nNel dubbio, lascia l'opzione disattivata.", "ja_JP": "直接キーボード アクセス (HID) のサポートです. テキスト入力デバイスとしてキーボードへのゲームアクセスを提供します.\n\nSwitchハードウェアでキーボードの使用をネイティブにサポートしているゲームでのみ動作します.\n\nわからない場合はオフのままにしてください.", - "ko_KR": "키보드 직접 접속(HID)을 지원합니다. 텍스트 입력 장치로 키보드에 대한 게임 접속을 제공합니다.\n\nSwitch 하드웨어에서 키보드 사용을 기본적으로 지원하는 게임에서만 작동합니다.\n\n모르면 끔으로 두세요.", + "ko_KR": "키보드 직접 접속(HID)을 지원합니다. 텍스트 입력 장치로 키보드에 대한 게임 접속을 제공합니다.\n\nSwitch 하드웨어에서 키보드 사용을 기본적으로 지원하는 게임에서만 작동합니다.\n\n모르면 체크 해제 상태로 두세요.", "no_NO": "Direkte tastaturtilgang (HID) støtte. Gir deg spill-tilgang til tastaturet som en tekstinnlegg-enhet.\n\nfungerer kun med spill som lokalt støtter tastaturbruk på Ninteno SwitchTM maskinvare.\n\nLa være AV hvis du er usikker.", "pl_PL": "Obsługa bezpośredniego dostępu do klawiatury (HID). Zapewnia dostęp gier do klawiatury jako urządzenia do wprowadzania tekstu.\n\nDziała tylko z grami, które natywnie wspierają użycie klawiatury w urządzeniu Switch hardware.\n\nPozostaw wyłączone w razie braku pewności.", "pt_BR": "Suporte para acesso direto ao teclado (HID). Permite que os jogos acessem seu teclado como um dispositivo de entrada de texto.\n\nFunciona apenas com jogos que suportam o uso de teclado nativamente no hardware do Switch.\n\nDeixe desativado se estiver em dúvida.", @@ -16455,11 +16630,11 @@ "el_GR": "", "en_US": "Direct mouse access (HID) support. Provides games access to your mouse as a pointing device.\n\nOnly works with games that natively support mouse controls on Switch hardware, which are few and far between.\n\nWhen enabled, touch screen functionality may not work.\n\nLeave OFF if unsure.", "es_ES": "Soporte de acceso directo al mouse (HID). Proporciona a los juegos acceso a su mouse como puntero.\n\nSolo funciona con juegos que permiten de forma nativa el uso de controles con mouse en el hardware de switch, lo cual son pocos.\n\nCuando esté activado, la funcionalidad de pantalla táctil puede no funcionar.\n\nDesactívalo si no sabes qué hacer.", - "fr_FR": "Prise en charge de l'accès direct à la souris (HID). Permet aux jeux d'accéder à votre souris en tant que dispositif de pointage.\n\nFonctionne uniquement avec les jeux qui prennent en charge nativement les contrôles de souris sur le matériel Switch, ce qui est rare.\n\nLorsqu'il est activé, la fonctionnalité de l'écran tactile peut ne pas fonctionner.\n\nLaissez désactiver si vous n'êtes pas sûr.", + "fr_FR": "Prise en charge de l’accès direct à la souris (HID). Permet aux jeux d’accéder à votre souris comme périphérique de pointage.\n\nNe fonctionne qu’avec les jeux qui supportent nativement les contrôles souris sur la console Switch, ce qui est rare.\n\nLorsque cette option est activée, la fonctionnalité de l’écran tactile peut ne pas fonctionner.\n\nLaissez DÉSACTIVÉ si vous n'êtes pas sûr.", "he_IL": "", "it_IT": "Supporto per l'accesso diretto al mouse (HID). Fornisce ai giochi l'accesso al mouse come dispositivo di puntamento.\n\nFunziona solo con i rari giochi che supportano nativamente l'utilizzo del mouse su hardware Switch.\n\nQuando questa opzione è attivata, il touchscreen potrebbe non funzionare.\n\nNel dubbio, lascia l'opzione disattivata.", "ja_JP": "直接マウスアクセス (HID) のサポートです. ポインティングデバイスとしてマウスへのゲームアクセスを提供します.\n\nSwitchハードウェアでマウスの使用をネイティブにサポートしているゲームでのみ動作します.\n\n有効にしている場合, タッチスクリーン機能は動作しない場合があります.\n\nわからない場合はオフのままにしてください.", - "ko_KR": "마우스 직접 접속(HID)을 지원합니다. 마우스에 대한 게임 접속을 포인팅 장치로 제공합니다.\n\nSwitch 하드웨어에서 마우스 컨트롤을 기본적으로 지원하는 게임에서만 작동하며 거의 없습니다.\n\n활성화하면 터치 스크린 기능이 작동하지 않을 수 있습니다.\n\n모르면 끔으로 두세요.", + "ko_KR": "마우스 직접 접속(HID)을 지원합니다. 마우스에 대한 게임 접속을 포인팅 장치로 제공합니다.\n\nSwitch 하드웨어에서 마우스 컨트롤을 기본적으로 지원하는 게임에서만 작동하며 거의 없습니다.\n\n활성화하면 터치 스크린 기능이 작동하지 않을 수 있습니다.\n\n모르면 체크 해제 상태로 두세요.", "no_NO": "Direkte musepeker (HID) støtte. Gir deg spill-tilgang til musepeker.\n\nfungerer kun med spill som lokalt støtter musepekere på Ninteno SwitchTM maskinvare.\n\nNår aktivert, kan det hende touch funksjoner ikke fungerer\n\nLa være AV hvis du er usikker.", "pl_PL": "Obsługa bezpośredniego dostępu do myszy (HID). Zapewnia dostęp gier do myszy jako urządzenia wskazującego.\n\nDziała tylko z grami, które natywnie obsługują przyciski myszy w urządzeniu Switch, które są nieliczne i daleko między nimi.\n\nPo włączeniu funkcja ekranu dotykowego może nie działać.\n\nPozostaw wyłączone w razie wątpliwości.", "pt_BR": "Suporte para acesso direto ao mouse (HID). Permite que os jogos acessem seu mouse como um dispositivo de apontamento.\n\nFunciona apenas com jogos que suportam controles de mouse nativamente no hardware do Switch, o que é raro.\n\nQuando ativado, a funcionalidade de tela sensível ao toque pode não funcionar.\n\nDeixe desativado se estiver em dúvida.", @@ -16580,7 +16755,7 @@ "el_GR": "", "en_US": "Sync System Time to match your PC's current date & time.", "es_ES": "", - "fr_FR": "Resynchronise la Date du Système pour qu'elle soit la même que celle du PC.", + "fr_FR": "Synchroniser l’heure système avec la date et l’heure actuelles de votre PC.", "he_IL": "", "it_IT": "Sincronizza data e ora del sistema con quelle del PC.", "ja_JP": "", @@ -16605,11 +16780,11 @@ "el_GR": "", "en_US": "Emulated console's Vertical Sync. Essentially a frame-limiter for the majority of games; disabling it may cause games to run at higher speed or make loading screens take longer or get stuck.\n\nCan be toggled in-game with a hotkey of your preference (F1 by default). We recommend doing this if you plan on disabling it.\n\nLeave ON if unsure.", "es_ES": "Sincronización vertical de la consola emulada. En práctica un limitador del framerate para la mayoría de los juegos; desactivando puede causar que juegos corran a mayor velocidad o que las pantallas de carga tarden más o queden atascados.\n\nSe puede alternar en juego utilizando una tecla de acceso rápido configurable (F1 by default). Recomendamos hacer esto en caso de querer desactivar sincroniziación vertical.\n\nDesactívalo si no sabes qué hacer.", - "fr_FR": "La synchronisation verticale de la console émulée. Essentiellement un limiteur de trame pour la majorité des jeux ; le désactiver peut entraîner un fonctionnement plus rapide des jeux ou prolonger ou bloquer les écrans de chargement.\n\nPeut être activé ou désactivé en jeu avec un raccourci clavier de votre choix (F1 par défaut). Nous recommandons de le faire si vous envisagez de le désactiver.\n\nLaissez activé si vous n'êtes pas sûr.", + "fr_FR": "Synchronisation verticale de la console émulée. Il s'agit essentiellement d'un limiteur de fréquence d'images pour la majorité des jeux ; la désactivation peut entraîner une accélération du jeu ou provoquer des temps de chargement plus longs, voire des blocages..\n\nPeut être activée/désactivée en jeu via un raccourci clavier de votre choix (F1 par défaut). Nous recommandons d’utiliser ce raccourci si vous prévoyez de la désactiver.\n\nLaissez ACTIVÉE si vous n’êtes pas sûr.", "he_IL": "", "it_IT": "Sincronizzazione verticale della console emulata. Funziona essenzialmente come un limitatore del framerate per la maggior parte dei giochi; disabilitarla può far girare giochi a velocità più alta, allungare le schermate di caricamento o farle bloccare.\n\nPuò essere attivata mentre giochi con un tasto di scelta rapida (F1 per impostazione predefinita). Ti consigliamo di farlo se hai intenzione di disabilitarla.\n\nNel dubbio, lascia l'opzione attiva.", "ja_JP": "エミュレートされたゲーム機の垂直同期です. 多くのゲームにおいて, フレームリミッタとして機能します. 無効にすると, ゲームが高速で実行されたり, ロード中に時間がかかったり, 止まったりすることがあります.\n\n設定したホットキー(デフォルトではF1)で, ゲーム内で切り替え可能です. 無効にする場合は, この操作を行うことをおすすめします.\n\nよくわからない場合はオンのままにしてください.", - "ko_KR": "에뮬레이트된 콘솔의 수직 동기화입니다. 기본적으로 대부분의 게임에서 프레임 제한 기능으로, 비활성화하면 게임이 더 빠른 속도로 실행되거나 로딩 화면이 더 오래 걸리거나 멈출 수 있습니다.\n\n게임 내에서 원하는 단축키(기본값은 F1)로 전환할 수 있습니다. 비활성화하려면 이 작업을 수행하는 것이 좋습니다.\n\n모르면 켬으로 두세요.", + "ko_KR": "에뮬레이트된 콘솔의 수직 동기화입니다. 기본적으로 대부분의 게임에서 프레임 제한 기능으로, 비활성화하면 게임이 더 빠른 속도로 실행되거나 로딩 화면이 더 오래 걸리거나 멈출 수 있습니다.\n\n게임 내에서 원하는 단축키(기본값은 F1)로 전환할 수 있습니다. 비활성화하려면 이 작업을 수행하는 것이 좋습니다.\n\n모르면 체크 상태로 두세요.", "no_NO": "Emuler konsollens loddrett synkronisering. på ett vis en bildefrekvens begrensning for de fleste spill; deaktivering kan få spill til å kjøre med høyere hastighet, eller til å laste skjermene tar lengre tid eller sitter fast.\n\nkan byttes inn i spillet med en hurtigtast for preferansen (F1 som standard). Vi anbefaler å gjøre dette hvis du planlegger å deaktivere dette.\n\nLa være PÅ hvis du er usikker.", "pl_PL": "Synchronizacja pionowa emulowanej konsoli. Zasadniczo ogranicznik klatek dla większości gier; wyłączenie jej może spowodować, że gry będą działać z większą szybkością, ekrany wczytywania wydłużą się lub nawet utkną.\n\nMoże być przełączana w grze za pomocą preferowanego skrótu klawiszowego. Zalecamy to zrobić, jeśli planujesz ją wyłączyć.\n\nW razie wątpliwości pozostaw WŁĄCZONĄ.", "pt_BR": "V-Sync do console emulado. Funciona essencialmente como um limitador de quadros para a maioria dos jogos; desativá-lo pode fazer com que os jogos rodem em uma velocidade mais alta ou que telas de carregamento demorem mais ou travem.\n\nPode ser alternado durante o jogo com uma tecla de atalho de sua preferência (F1 por padrão). Recomendamos isso caso planeje desativá-lo.\n\nMantenha ligado se estiver em dúvida.", @@ -16630,11 +16805,11 @@ "el_GR": "Ενεργοποιεί ή απενεργοποιεί το PPTC", "en_US": "Saves translated JIT functions so that they do not need to be translated every time the game loads.\n\nReduces stuttering and significantly speeds up boot times after the first boot of a game.\n\nLeave ON if unsure.", "es_ES": "Guarda funciones de JIT traducidas para que no sea necesario traducirlas cada vez que el juego carga.\n\nReduce los tirones y acelera significativamente el tiempo de inicio de los juegos después de haberlos ejecutado al menos una vez.\n\nActívalo si no sabes qué hacer.", - "fr_FR": "Sauvegarde les fonctions JIT afin qu'elles n'aient pas besoin d'être à chaque fois recompiler lorsque le jeu se charge.\n\nRéduit les lags et accélère considérablement le temps de chargement après le premier lancement d'un jeu.\n\nLaissez par défaut si vous n'êtes pas sûr.", + "fr_FR": "Sauvegarde les fonctions JIT traduites afin qu’elles n’aient pas besoin d’être retraduites à chaque chargement du jeu.\n\nRéduit les lags et accélère considérablement le temps de chargement après le premier lancement d'un jeu.\n\nLaissez ACTIVÉ si vous n’êtes pas sûr.", "he_IL": "שומר את פונקציות ה-JIT המתורגמות כך שלא יצטרכו לעבור תרגום שוב כאשר משחק עולה.\n\nמפחית תקיעות ומשפר מהירות עלייה של המערכת אחרי הפתיחה הראשונה של המשחק.\n\nמוטב להשאיר דלוק אם לא בטוחים.", "it_IT": "Salva le funzioni JIT tradotte in modo che non debbano essere tradotte tutte le volte che si avvia un determinato gioco.\n\nRiduce i fenomeni di stuttering e velocizza sensibilmente gli avvii successivi del gioco.\n\nNel dubbio, lascia l'opzione attiva.", "ja_JP": "翻訳されたJIT関数をセーブすることで, ゲームをロードするたびに毎回翻訳する処理を不要とします.\n\n一度ゲームを起動すれば,二度目以降の起動時遅延を大きく軽減できます.\n\nよくわからない場合はオンのままにしてください.", - "ko_KR": "번역된 JIT 함수를 저장하여 게임을 불러올 때마다 번역할 필요가 없도록 합니다.\n\n게임을 처음 부팅한 후 끊김 현상을 줄이고 부팅 시간을 크게 단축합니다.\n\n모르면 켬으로 두세요.", + "ko_KR": "번역된 JIT 함수를 저장하여 게임을 불러올 때마다 번역할 필요가 없도록 합니다.\n\n게임을 처음 부팅한 후 끊김 현상을 줄이고 부팅 시간을 크게 단축합니다.\n\n모르면 체크 상태로 두세요.", "no_NO": "Lagrer oversatte JIT funksjoner så de ikke trenger og bli oversatt hver gang spillet laster.\n\nKan redusere hakkete spilling og gjør at spillet starter opp raskere ved første oppstart.\n\nLa være PÅ om usikker.", "pl_PL": "Zapisuje przetłumaczone funkcje JIT, dzięki czemu nie muszą być tłumaczone za każdym razem, gdy gra się ładuje.\n\nZmniejsza zacinanie się i znacznie przyspiesza uruchamianie po pierwszym uruchomieniu gry.\n\nJeśli nie masz pewności, pozostaw WŁĄCZONE", "pt_BR": "Salva funções JIT traduzidas para que elas não precisem ser traduzidas toda vez que o jogo for carregado.\n\nReduz a trepidação e acelera significativamente os tempos de inicialização após a primeira inicialização de um jogo.\n\nDeixe LIGADO se não tiver certeza.", @@ -16655,7 +16830,7 @@ "el_GR": "", "en_US": "Load the PPTC using a third of the amount of cores.", "es_ES": "Cargue el PPTC utilizando un tercio de la cantidad de núcleos.", - "fr_FR": "Charger le PPTC en utilisant un tiers des coeurs.", + "fr_FR": "Charger le PPTC en utilisant un tiers des cœurs disponibles.", "he_IL": "", "it_IT": "Carica la cache PPTC usando un terzo dei core del processore.", "ja_JP": "", @@ -16680,11 +16855,11 @@ "el_GR": "Ενεργοποιεί τους ελέγχους ακεραιότητας σε αρχεία περιεχομένου παιχνιδιού", "en_US": "Checks for corrupt files when booting a game, and if corrupt files are detected, displays a hash error in the log.\n\nHas no impact on performance and is meant to help troubleshooting.\n\nLeave ON if unsure.", "es_ES": "Comprueba si hay archivos corruptos en los juegos que ejecutes al abrirlos, y si detecta archivos corruptos, muestra un error de Hash en los registros.\n\nEsto no tiene impacto alguno en el rendimiento y está pensado para ayudar a resolver problemas.\n\nActívalo si no sabes qué hacer.", - "fr_FR": "Vérifie si des fichiers sont corrompus lors du lancement d'un jeu, et si des fichiers corrompus sont détectés, affiche une erreur de hachage dans la console.\n\nN'a aucun impact sur les performances et est destiné à aider le dépannage.\n\nLaissez activé en cas d'incertitude.", + "fr_FR": "Vérifie la présence de fichiers corrompus au démarrage d’un jeu. En cas de fichiers corrompus détectés, un message d’erreur de hachage s’affiche dans le journal.\n\nN’a aucun impact sur les performances et est destiné à faciliter le dépannage.\n\nLaissez ACTIVÉ si vous n’êtes pas sûr.", "he_IL": "בודק לקבצים שגויים כאשר משחק עולה, ואם מתגלים כאלו, מציג את מזהה השגיאה שלהם לקובץ הלוג.\n\nאין לכך השפעה על הביצועים ונועד לעזור לבדיקה וניפוי שגיאות של האמולטור.\n\nמוטב להשאיר דלוק אם לא בטוחים.", "it_IT": "Controlla la presenza di file corrotti quando si avvia un gioco. Se vengono rilevati dei file corrotti, verrà mostrato un errore di hash nel log.\n\nQuesta opzione non influisce sulle prestazioni ed è pensata per facilitare la risoluzione dei problemi.\n\nNel dubbio, lascia l'opzione attiva.", "ja_JP": "ゲーム起動時にファイル破損をチェックし,破損が検出されたらログにハッシュエラーを表示します..\n\nパフォーマンスには影響なく, トラブルシューティングに役立ちます.\n\nよくわからない場合はオンのままにしてください.", - "ko_KR": "게임을 부팅할 때 손상된 파일을 확인하고, 손상된 파일이 감지되면 로그에 해시 오류를 표시합니다.\n\n성능에 영향을 미치지 않으며 문제 해결에 도움이 됩니다.\n\n모르면 켬으로 두세요.", + "ko_KR": "게임을 부팅할 때 손상된 파일을 확인하고, 손상된 파일이 감지되면 로그에 해시 오류를 표시합니다.\n\n성능에 영향을 미치지 않으며 문제 해결에 도움이 됩니다.\n\n모르면 체크 상태로 두세요.", "no_NO": "Sjekker for korrupte filer ved oppstart av et spill, og dersom korrupte filer oppdages, viser en hashfeil i loggen.\n\nhar ingen innvirkning på ytelsen og er ment å hjelpe med feilsøking.\n\nLa være PÅ hvis usikker.", "pl_PL": "Sprawdza pliki podczas uruchamiania gry i jeśli zostaną wykryte uszkodzone pliki, wyświetla w dzienniku błąd hash.\n\nNie ma wpływu na wydajność i ma pomóc w rozwiązywaniu problemów.\n\nPozostaw WŁĄCZONE, jeśli nie masz pewności.", "pt_BR": "Verifica se há arquivos corrompidos ao inicializar um jogo e, se forem detectados, exibe um erro de hash no log.\n\nNão tem impacto no desempenho e tem como objetivo ajudar na solução de problemas.\n\nDeixe LIGADO se não tiver certeza.", @@ -16705,7 +16880,7 @@ "el_GR": "Αλλαγή ήχου υποστήριξης", "en_US": "Changes the backend used to render audio.\n\nSDL2 is the preferred one, while OpenAL and SoundIO are used as fallbacks. Dummy will have no sound.\n\nSet to SDL2 if unsure.", "es_ES": "Cambia el motor usado para renderizar audio.\n\nSDL2 es el preferido, mientras que OpenAL y SoundIO se usan si hay problemas con este. Dummy no produce audio.\n\nSelecciona SDL2 si no sabes qué hacer.", - "fr_FR": "Modifie le backend utilisé pour donnée un rendu audio.\n\nSDL2 est recommandé, tandis que OpenAL et SoundIO sont utilisés comme backend secondaire. Le backend Dummy (Désactivé) ne rend aucun son.\n\nLaissez sur SDL2 si vous n'êtes pas sûr.", + "fr_FR": "Change le moteur utilisé pour le rendu audio.\n\nSDL2 est le moteur recommandé, tandis qu’OpenAL et SoundIO sont utilisés en secours. Dummy ne produit aucun son.\n\nLaissez sur SDL2 si vous n'êtes pas sûr.", "he_IL": "משנה את אחראי השמע.\n\nSDL2 הוא הנבחר, למראת שOpenAL וגם SoundIO משומשים כאפשרויות חלופיות. אפשרות הDummy לא תשמיע קול כלל.\n\nמוטב להשאיר על SDL2 אם לא בטוחים.", "it_IT": "Cambia il backend usato per riprodurre l'audio.\n\nSDL2 è quello preferito, mentre OpenAL e SoundIO sono usati come ripiego. Dummy non riprodurrà alcun suono.\n\nNel dubbio, imposta l'opzione su SDL2.", "ja_JP": "音声レンダリングに使用するバックエンドを変更します.\n\nSDL2 が優先され, OpenAL と SoundIO はフォールバックとして使用されます. ダミーは音声出力しません.\n\nよくわからない場合は SDL2 を設定してください.", @@ -16730,7 +16905,7 @@ "el_GR": "Αλλάξτε τον τρόπο αντιστοίχισης και πρόσβασης στη μνήμη επισκέπτη. Επηρεάζει σε μεγάλο βαθμό την απόδοση της προσομοίωσης της CPU.", "en_US": "Change how guest memory is mapped and accessed. Greatly affects emulated CPU performance.\n\nSet to HOST UNCHECKED if unsure.", "es_ES": "Cambia la forma de mapear y acceder a la memoria del guest. Afecta en gran medida al rendimiento de la CPU emulada.\n\nSelecciona \"Host sin verificación\" si no sabes qué hacer.", - "fr_FR": "Change la façon dont la mémoire émulée est mappée et utilisée. Cela affecte grandement les performances du processeur.\n\nRéglez sur Hôte non vérifié en cas d'incertitude.", + "fr_FR": "Modifie la manière dont la mémoire émulée est mappée et accédée. Impacte fortement les performances du processeur émulé.\n\nLaissez sur HÔTE NON VÉRIFIÉ si vous n'êtes pas sûr.", "he_IL": "שנה איך שזיכרון מארח מיוחד ומונגד. משפיע מאוד על ביצועי המעבד המדומה.\n\nמוטב להשאיר על מארח לא מבוקר אם לא בטוחים.", "it_IT": "Cambia il modo in cui la memoria guest è mappata e vi si accede. Influisce notevolmente sulle prestazioni della CPU emulata.\n\nNel dubbio, imposta l'opzione su Host Unchecked.", "ja_JP": "ゲストメモリのマップ/アクセス方式を変更します. エミュレートされるCPUのパフォーマンスに大きな影響を与えます.\n\nよくわからない場合は「ホスト,チェックなし」を設定してください.", @@ -16755,7 +16930,7 @@ "el_GR": "Χρησιμοποιήστε έναν πίνακα σελίδων λογισμικού για τη μετάφραση διευθύνσεων. Υψηλότερη ακρίβεια αλλά πιο αργή απόδοση.", "en_US": "Use a software page table for address translation. Highest accuracy but slowest performance.", "es_ES": "Usa una tabla de paginación de software para traducir direcciones. Ofrece la precisión más exacta pero el rendimiento más lento.", - "fr_FR": "Utilisez une table logicielle pour la traduction d'adresses. La plus grande précision est fournie, mais les performances en seront impactées.", + "fr_FR": "Utilise une table des pages logicielle pour la traduction des adresses. Offre la plus grande précision mais les performances sont les plus lentes.", "he_IL": "השתמש בתוכנת ה-page table בכדי להתייחס לתרגומים. דיוק מרבי לקונסולה אך המימוש הכי איטי.", "it_IT": "Usa una software page table per la traduzione degli indirizzi. Massima precisione ma prestazioni più lente.", "ja_JP": "アドレス変換にソフトウェアページテーブルを使用します. 非常に正確ですがパフォーマンスが大きく低下します.", @@ -16780,7 +16955,7 @@ "el_GR": "Απευθείας αντιστοίχιση της μνήμης στον χώρο διευθύνσεων υπολογιστή υποδοχής. Πολύ πιο γρήγορη μεταγλώττιση και εκτέλεση JIT.", "en_US": "Directly map memory in the host address space. Much faster JIT compilation and execution.", "es_ES": "Mapea la memoria directamente en la dirección de espacio del host. Compilación y ejecución JIT mucho más rápida.", - "fr_FR": "Mappez directement la mémoire dans l'espace d'adresses de l'hôte. Compilation et exécution JIT beaucoup plus rapides.", + "fr_FR": "Mappe directement la mémoire dans l’espace d’adressage de l’hôte. Compilation JIT et exécution beaucoup plus rapides.", "he_IL": "ממפה זיכרון ישירות לכתובת המארח. מהיר בהרבה ביכולות קימפול ה-JIT והריצה.", "it_IT": "Mappa direttamente la memoria nello spazio degli indirizzi dell'host. Compilazione ed esecuzione JIT molto più veloce.", "ja_JP": "ホストのアドレス空間にメモリを直接マップします.JITのコンパイルと実行速度が大きく向上します.", @@ -16805,7 +16980,7 @@ "el_GR": "Απευθείας χαρτογράφηση της μνήμης, αλλά μην καλύπτετε τη διεύθυνση εντός του χώρου διευθύνσεων επισκέπτη πριν από την πρόσβαση. Πιο γρήγορα, αλλά με κόστος ασφάλειας. Η εφαρμογή μπορεί να έχει πρόσβαση στη μνήμη από οπουδήποτε στο Ryujinx, επομένως εκτελείτε μόνο προγράμματα που εμπιστεύεστε με αυτήν τη λειτουργία.", "en_US": "Directly map memory, but do not mask the address within the guest address space before access. Faster, but at the cost of safety. The guest application can access memory from anywhere in Ryujinx, so only run programs you trust with this mode.", "es_ES": "Mapea la memoria directamente, pero no enmascara la dirección dentro del espacio de dirección del guest antes del acceso. El modo más rápido, pero a costa de seguridad. La aplicación guest puede acceder a la memoria desde cualquier parte en Ryujinx, así que ejecuta solo programas en los que confíes cuando uses este modo.", - "fr_FR": "Mapper directement la mémoire dans la carte, mais ne pas masquer l'adresse dans l'espace d'adressage du client avant l'accès. Plus rapide, mais la sécurité sera négligée. L'application peut accéder à la mémoire depuis n'importe où dans Ryujinx, donc exécutez uniquement les programmes en qui vous avez confiance avec ce mode.", + "fr_FR": "Mappe directement la mémoire, mais sans masquer l’adresse dans l’espace d’adressage invité avant l’accès. Plus rapide, mais au détriment de la sécurité. L’application invitée peut accéder à n’importe quelle zone mémoire de Ryujinx ; n’utilisez ce mode qu’avec des programmes de confiance.", "he_IL": "ממפה זיכרון ישירות, אך לא ממסך את הכתובת בתוך כתובת המארח לפני הגישה. מהיר, אך במחיר של הגנה. יישום המארח בעל גישה לזיכרון מכל מקום בריוג'ינקס, לכן הריצו איתו רק קבצים שאתם סומכים עליהם.", "it_IT": "Mappa direttamente la memoria, ma non maschera l'indirizzo all'interno dello spazio degli indirizzi guest prima dell'accesso. Più veloce, ma a costo della sicurezza. L'applicazione guest può accedere alla memoria da qualsiasi punto di Ryujinx, quindi esegui solo programmi di cui ti fidi con questa modalità.", "ja_JP": "メモリを直接マップしますが, アクセス前にゲストのアドレス空間内のアドレスをマスクしません. より高速になりますが, 安全性が犠牲になります. ゲストアプリケーションは Ryujinx のどこからでもメモリにアクセスできるので,このモードでは信頼できるプログラムだけを実行するようにしてください.", @@ -16830,7 +17005,7 @@ "el_GR": "Χρησιμοποιήστε Hypervisor αντί για JIT. Βελτιώνει σημαντικά την απόδοση όταν διατίθεται, αλλά μπορεί να είναι ασταθής στην τρέχουσα κατάστασή του.", "en_US": "Use Hypervisor instead of JIT. Greatly improves performance when available, but can be unstable in its current state.", "es_ES": "Usar Hypervisor en lugar de JIT. Mejora enormemente el rendimiento cuando está disponible, pero puede ser inestable en su estado actual.", - "fr_FR": "Utiliser l'Hyperviseur au lieu du JIT. Améliore considérablement les performances lorsqu'il est disponible, mais peut être instable dans son état actuel.", + "fr_FR": "Utiliser l'Hyperviseur au lieu du JIT. Améliore considérablement les performances lorsque disponible, mais peut être instable dans son état actuel.", "he_IL": "השתמש ב- Hypervisor במקום JIT. משפר מאוד ביצועים כשניתן, אבל יכול להיות לא יציב במצבו הנוכחי.", "it_IT": "Usa Hypervisor invece di JIT. Migliora notevolmente le prestazioni quando disponibile, ma può essere instabile nel suo stato attuale.", "ja_JP": "JIT の代わりにハイパーバイザーを使用します. 利用可能な場合, パフォーマンスが大幅に向上しますが, 現在の状態では不安定になる可能性があります.", @@ -16855,11 +17030,11 @@ "el_GR": "Επεκτείνει την ποσότητα της μνήμης στο εξομοιούμενο σύστημα από 4 GiB σε 6 GiB", "en_US": "Utilizes an alternative memory mode with 8GiB of DRAM to mimic a Switch development model.\n\nThis is only useful for higher-resolution texture packs or 4k resolution mods. Does NOT improve performance.\n\nLeave OFF if unsure.", "es_ES": "Expande la memoria DRAM del sistema emulado de 4GiB a 6GiB.\n\nUtilizar solo con packs de texturas HD o mods de resolución 4K. NO mejora el rendimiento.\n\nDesactívalo si no sabes qué hacer.", - "fr_FR": "Change le montant de DRAM qui est alloué.\n\nActivez cette option pour les packs de textures 4k ou les mods à résolution 4k.\nN'améliore pas les performances.\n\nLaissez à 4GiO en cas de doute.", + "fr_FR": "Utilise un mode mémoire alternatif avec 4, 6, 8 ou 12GiO de DRAM pour simuler un modèle de développement Switch.\n\nUtile uniquement pour les packs de textures haute résolution ou les mods en 4K.\nN’améliore PAS les performances.\n\nLaissez à 4GiO si vous n’êtes pas sûr.", "he_IL": "מנצל תצורת מצב-זיכרון חלופית לחכות את מכשיר הפיתוח של הסוויץ'.\n\nזה שימושי להחלפת חבילות מרקמים באיכותיים יותר או כאלו ברזולוציית 4k. לא משפר ביצועים.\n\nמוטב להשאיר כבוי אם לא בטוחים.", "it_IT": "Utilizza un layout di memoria alternativo per imitare un'unità di sviluppo di Switch.\n\nQuesta opzione è utile soltanto per i pacchetti di texture ad alta risoluzione o per le mod che aumentano la risoluzione a 4K. NON migliora le prestazioni.\n\nNel dubbio, lascia l'opzione disattivata.", "ja_JP": "エミュレートされたシステムのメモリ容量を 4GiB から 6GiB に増加します.\n\n高解像度のテクスチャパックや 4K解像度の mod を使用する場合に有用です. パフォーマンスを改善するものではありません.\n\nよくわからない場合はオフのままにしてください.", - "ko_KR": "Switch 개발 모델을 모방하기 위해 8GB DRAM이 포함된 대체 메모리 모드를 활용합니다.\n\n이는 고해상도 텍스처 팩 또는 4K 해상도 모드에만 유용합니다. 성능을 개선하지 않습니다.\n\n모르면 끔으로 두세요.", + "ko_KR": "Switch 개발 모델을 모방하기 위해 8GB DRAM이 포함된 대체 메모리 모드를 활용합니다.\n\n이는 고해상도 텍스처 팩 또는 4K 해상도 모드에만 유용합니다. 성능을 개선하지 않습니다.\n\n모르면 체크 해제 상태로 두세요.", "no_NO": "Bruker en alternativ minnemodus med 8GiB i DRAM for og etterligne Switch utvikler modeller.\n\nDette er bare nyttig for teksturpakker eller 4k oppløsningsmoduler. Forbedrer IKKE ytelsen.\n\nLa AV hvis usikker.", "pl_PL": "Wykorzystuje alternatywny układ MemoryMode, aby naśladować model rozwojowy Switcha.\n\nJest to przydatne tylko w przypadku pakietów tekstur o wyższej rozdzielczości lub modów w rozdzielczości 4k. NIE poprawia wydajności.\n\nW razie wątpliwości pozostaw WYŁĄCZONE.", "pt_BR": "Utiliza um modo de memória alternativo com 6, 8 ou 12 GB de DRAM para imitar um modelo de desenvolvimento do Switch.\n\nIsso só é útil para pacotes de textura de alta resolução ou mods de resolução 4k. NÃO melhora o desempenho.\n\nDeixe em 4 GB se não tiver certeza.", @@ -16880,11 +17055,11 @@ "el_GR": "Ενεργοποίηση ή απενεργοποίηση της αγνοώησης για υπηρεσίες που λείπουν", "en_US": "Ignores unimplemented Horizon OS services. This may help in bypassing crashes when booting certain games.\n\nLeave OFF if unsure.", "es_ES": "Hack para ignorar servicios no implementados del Horizon OS. Esto puede ayudar a sobrepasar crasheos cuando inicies ciertos juegos.\n\nDesactívalo si no sabes qué hacer.", - "fr_FR": "Ignore les services Horizon OS non-intégrés. Cela peut aider à contourner les plantages lors du démarrage de certains jeux.\n\nLaissez désactivé en cas d'incertitude.", + "fr_FR": "Ignore les services Horizon OS non implémentés. Cela peut aider à éviter les plantages au démarrage de certains jeux.\n\nLaissez DÉSACTIVÉ si vous n’êtes pas sûr.", "he_IL": "מתעלם מפעולות שלא קיבלו מימוש במערכת ההפעלה Horizon OS. זה עלול לעזור לעקוף קריסות של היישום במשחקים מסויימים.\n\nמוטב להשאיר כבוי אם לא בטוחים.", "it_IT": "Ignora i servizi non implementati del sistema operativo Horizon. Può aiutare ad aggirare gli arresti anomali che si verificano avviando alcuni giochi.\n\nNel dubbio, lascia l'opzione disattivata.", "ja_JP": "未実装の Horizon OS サービスを無視します. 特定のゲームにおいて起動時のクラッシュを回避できる場合があります.\n\nよくわからない場合はオフのままにしてください.", - "ko_KR": "구현되지 않은 Horizon OS 서비스는 무시됩니다. 특정 게임을 부팅할 때, 발생하는 충돌을 우회하는 데 도움이 될 수 있습니다.\n\n모르면 끔으로 두세요.", + "ko_KR": "구현되지 않은 Horizon OS 서비스는 무시됩니다. 특정 게임을 부팅할 때, 발생하는 충돌을 우회하는 데 도움이 될 수 있습니다.\n\n모르면 체크 해제 상태로 두세요.", "no_NO": "Ignorerer ikke implementerte Horisont OS-tjenester. Dette kan hjelpe med å omgå krasj ved oppstart av enkelte spill.\n\nLa AV hvis du er usikker.", "pl_PL": "Ignoruje niezaimplementowane usługi Horizon OS. Może to pomóc w ominięciu awarii podczas uruchamiania niektórych gier.\n\nW razie wątpliwości pozostaw WYŁĄCZONE.", "pt_BR": "Ignora serviços não implementados do Horizon OS. Isso pode ajudar a contornar travamentos ao inicializar certos jogos.\n\nDeixe OFF se não tiver certeza.", @@ -16905,11 +17080,11 @@ "el_GR": "", "en_US": "The Controller Applet dialog will not appear if the gamepad is disconnected while an application is running.\n\nLeave OFF if unsure.", "es_ES": "", - "fr_FR": "", + "fr_FR": "La fenêtre de l’applet manette ne s’affichera pas si la manette est déconnectée pendant l’exécution d’une application\n\nLaissez DÉSACTIVÉ si vous n’êtes pas sûr.", "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "앱이 실행 중일 때, 게임패드의 연결이 끊어지면 컨트롤러 애플릿 대화 상자가 나타나지 않습니다.\n\n모르시면 끔으로 두십시오.", + "ko_KR": "앱이 실행 중일 때, 게임패드의 연결이 끊어지면 컨트롤러 애플릿 대화 상자가 나타나지 않습니다.\n\n모르시면 체크 해제 상태로 두십시오.", "no_NO": "Håndkontroller-appleten vises ikke hvis gamepaden kobles fra mens et program kjører.", "pl_PL": "", "pt_BR": "A caixa de diálogo do Applet do controlador não aparecerá se o controle for desconectado enquanto um aplicativo estiver em execução.\n\nDeixe a opção DESLIGADO se não tiver certeza.", @@ -16930,7 +17105,7 @@ "el_GR": "Αυτή η επιλογή παρακάμπτει το παράθυρο διαλόγου 'Διαχειριστής Προφίλ Χρήστη' κατά τη διάρκεια του παιχνιδιού, χρησιμοποιώντας ένα προεπιλεγμένο προφίλ.\n\nΗ εναλλαγή προφίλ βρίσκεται στις 'Ρυθμίσεις' - 'Διαχειριστής Προφίλ Χρήστη'. Επιλέξτε το επιθυμητό προφίλ πριν φορτώσετε το παιχνίδι.", "en_US": "This option skips the 'Manage User Profiles' dialog during gameplay, using a pre-selected profile.\n\nProfile switching is found in 'Settings' - 'Manager User Profiles'. Select the desired profile before loading the game.", "es_ES": "Esta opción omite el diálogo de 'Gestionar perfiles de usuario' durante el juego, utilizando un perfil preseleccionado.\n\nEl cambio de perfil se encuentra en 'Configuración' - 'Gestionar perfiles de usuario'. Seleccione el perfil deseado antes de cargar el juego.", - "fr_FR": "Cette option permet d'éviter le dialogue du 'Gérer les profils d'utilisateurs' pendant le jeu, en utilisant un profil pré-sélectionné.\n\nLa sélection du profil se trouve dans 'Paramètres' - 'Gérer les profils d'utilisateurs'. Sélectionnez le profil souhaité avant de charger la partie.", + "fr_FR": "Cette option permet d'éviter le dialogue du 'Gérer les profils d'utilisateurs' pendant le jeu, en utilisant un profil pré-sélectionné.\n\nLa sélection du profil se trouve dans 'Paramètres' - 'Gérer les profils d'utilisateurs'. Sélectionnez le profil souhaité avant de lancer le jeu.", "he_IL": "", "it_IT": "Questa opzione salta la finestra di dialogo 'Gestisci i profili utente' durante il gioco, utilizzando un profilo pre-selezionato.\n\nIl cambio del profilo si trova in 'Impostazioni' - 'Gestisci i profili utente'. Seleziona il profilo desiderato prima di caricare il gioco.", "ja_JP": "このオプションは、ゲームプレイ中に「ユーザプロファイルを管理」ダイアログをスキップし、事前に選択されたプロファイルを使用します。\n\nプロファイルの切り替えは、「設定」-「ユーザプロファイルを管理」で見つけることができます。ゲームのロード前に目的のプロファイルをを選択してください。", @@ -16955,7 +17130,7 @@ "el_GR": "Ενεργοποίηση Πολυνηματικής Επεξεργασίας Γραφικών", "en_US": "Executes graphics backend commands on a second thread.\n\nSpeeds up shader compilation, reduces stuttering, and improves performance on GPU drivers without multithreading support of their own. Slightly better performance on drivers with multithreading.\n\nSet to AUTO if unsure.", "es_ES": "Ejecuta los comandos del motor gráfico en un segundo hilo. Acelera la compilación de sombreadores, reduce los tirones, y mejora el rendimiento en controladores gráficos que no realicen su propio procesamiento con múltiples hilos. Rendimiento ligeramente superior en controladores gráficos que soporten múltiples hilos.\n\nSelecciona \"Auto\" si no sabes qué hacer.", - "fr_FR": "Exécute des commandes du backend graphiques sur un second thread.\n\nAccélère la compilation des shaders, réduit les crashs et les lags, améliore les performances sur les pilotes GPU sans support de multithreading. Légère augementation des performances sur les pilotes avec multithreading intégrer.\n\nRéglez sur Auto en cas d'incertitude.", + "fr_FR": "Exécute des commandes du backend graphiques sur un second thread.\n\nAccélère la compilation des shaders, réduit les crashs et les lags, améliore les performances sur les pilotes GPU sans support natif du multithreading. Offre une légère amélioration des performances sur les pilotes multithreadés.\n\nRéglez sur AUTO si vous n’êtes pas sûr.", "he_IL": "מריץ פקודות גראפיקה בתהליך שני נפרד.\n\nמאיץ עיבוד הצללות, מפחית תקיעות ומשפר ביצועים של דרייבר כרטיסי מסך אשר לא תומכים בהרצה רב-תהליכית.\n\nמוטב להשאיר על אוטומטי אם לא בטוחים.", "it_IT": "Esegue i comandi del backend grafico su un secondo thread.\n\nVelocizza la compilazione degli shader, riduce lo stuttering e migliora le prestazioni sui driver grafici senza il supporto integrato al multithreading. Migliora leggermente le prestazioni sui driver che supportano il multithreading.\n\nNel dubbio, imposta l'opzione su Automatico.", "ja_JP": "グラフィックスバックエンドのコマンドを別スレッドで実行します.\n\nシェーダのコンパイルを高速化し, 遅延を軽減し, マルチスレッド非対応の GPU ドライバにおいてパフォーマンスを改善します. マルチスレッド対応のドライバでも若干パフォーマンス改善が見られます.\n\nよくわからない場合は自動に設定してください.", @@ -16980,7 +17155,7 @@ "el_GR": "Εκτελεί εντολές γραφικών σε ένα δεύτερο νήμα. Επιτρέπει την πολυνηματική μεταγλώττιση Shader σε χρόνο εκτέλεσης, μειώνει το τρεμόπαιγμα και βελτιώνει την απόδοση των προγραμμάτων οδήγησης χωρίς τη δική τους υποστήριξη πολλαπλών νημάτων. Ποικίλες κορυφαίες επιδόσεις σε προγράμματα οδήγησης με multithreading. Μπορεί να χρειαστεί επανεκκίνηση του Ryujinx για να απενεργοποιήσετε σωστά την ενσωματωμένη λειτουργία πολλαπλών νημάτων του προγράμματος οδήγησης ή ίσως χρειαστεί να το κάνετε χειροκίνητα για να έχετε την καλύτερη απόδοση.", "en_US": "Executes graphics backend commands on a second thread.\n\nSpeeds up shader compilation, reduces stuttering, and improves performance on GPU drivers without multithreading support of their own. Slightly better performance on drivers with multithreading.\n\nSet to AUTO if unsure.", "es_ES": "Ejecuta los comandos del motor gráfico en un segundo hilo. Acelera la compilación de sombreadores, reduce los tirones, y mejora el rendimiento en controladores gráficos que no realicen su propio procesamiento con múltiples hilos. Rendimiento ligeramente superior en controladores gráficos que soporten múltiples hilos.\n\nSelecciona \"Auto\" si no sabes qué hacer.", - "fr_FR": "Exécute des commandes du backend graphiques sur un second thread.\n\nAccélère la compilation des shaders, réduit les crashs et les lags, améliore les performances sur les pilotes GPU sans support de multithreading. Légère augementation des performances sur les pilotes avec multithreading intégrer.\n\nRéglez sur Auto en cas d'incertitude.", + "fr_FR": "Exécute des commandes du backend graphiques sur un second thread.\n\nAccélère la compilation des shaders, réduit les crashs et les lags, améliore les performances sur les pilotes GPU sans support natif du multithreading. Offre une légère amélioration des performances sur les pilotes multithreadés.\n\nRéglez sur AUTO si vous n’êtes pas sûr.", "he_IL": "מריץ פקודות גראפיקה בתהליך שני נפרד.\n\nמאיץ עיבוד הצללות, מפחית תקיעות ומשפר ביצועים של דרייבר כרטיסי מסך אשר לא תומכים בהרצה רב-תהליכית.\n\nמוטב להשאיר על אוטומטי אם לא בטוחים.", "it_IT": "Esegue i comandi del backend grafico su un secondo thread.\n\nVelocizza la compilazione degli shader, riduce lo stuttering e migliora le prestazioni sui driver grafici senza il supporto integrato al multithreading. Migliora leggermente le prestazioni sui driver che supportano il multithreading.\n\nNel dubbio, imposta l'opzione su Automatico.", "ja_JP": "グラフィックスバックエンドのコマンドを別スレッドで実行します.\n\nシェーダのコンパイルを高速化し, 遅延を軽減し, マルチスレッド非対応の GPU ドライバにおいてパフォーマンスを改善します. マルチスレッド対応のドライバでも若干パフォーマンス改善が見られます.\n\nよくわからない場合は自動に設定してください.", @@ -17005,11 +17180,11 @@ "el_GR": "Ενεργοποιεί ή απενεργοποιεί την Προσωρινή Μνήμη Shader", "en_US": "Saves a disk shader cache which reduces stuttering in subsequent runs.\n\nLeave ON if unsure.", "es_ES": "Guarda una caché de sombreadores en disco, la cual reduce los tirones a medida que vas jugando.\n\nActívalo si no sabes qué hacer.", - "fr_FR": "Enregistre un cache de shaders sur le disque dur, réduit le lag lors de multiples exécutions.\n\nLaissez activé si vous n'êtes pas sûr.", + "fr_FR": "Sauvegarde un cache de shaders sur disque, ce qui réduit les saccades lors des exécutions suivantes.\n\nLaissez ACTIVÉ si vous n'êtes pas sûr.", "he_IL": "שומר זכרון מטמון של הצללות, דבר שמפחית תקיעות בריצות מסוימות.\n\nמוטב להשאיר דלוק אם לא בטוחים.", "it_IT": "Salva una cache degli shader su disco che riduce i fenomeni di stuttering nelle esecuzioni successive.\n\nNel dubbio, lascia l'opzione attiva.", "ja_JP": "ディスクシェーダーキャッシュをセーブし,次回以降の実行時遅延を軽減します.\n\nよくわからない場合はオンのままにしてください.", - "ko_KR": "후속 실행 시 끊김 현상을 줄이는 디스크 셰이더 캐시를 저장합니다.\n\n모르면 켬으로 두세요.", + "ko_KR": "후속 실행 시 끊김 현상을 줄이는 디스크 셰이더 캐시를 저장합니다.\n\n모르면 체크 상태로 두세요.", "no_NO": "Lagrer en disk shader cache som reduserer hakking jo flere ganger du spiller.\n\nLa være PÅ om usikker.", "pl_PL": "Zapisuje pamięć podręczną shaderów na dysku, co zmniejsza zacinanie się w kolejnych uruchomieniach.\n\nPozostaw WŁĄCZONE, jeśli nie masz pewności.", "pt_BR": "Salva um cache de shader no disco que reduz a trepidação em execuções subsequentes.\n\nDeixe LIGADO se não tiver certeza.", @@ -17030,7 +17205,7 @@ "el_GR": "", "en_US": "Multiplies the game's rendering resolution.\n\nA few games may not work with this and look pixelated even when the resolution is increased; for those games, you may need to find mods that remove anti-aliasing or that increase their internal rendering resolution. For using the latter, you'll likely want to select Native.\n\nThis option can be changed while a game is running by clicking \"Apply\" below; you can simply move the settings window aside and experiment until you find your preferred look for a game.\n\nKeep in mind 4x is overkill for virtually any setup.", "es_ES": "Multiplica la resolución de rendereo del juego.\n\nAlgunos juegos podrían no funcionar con esto y verse pixelado al aumentar la resolución; en esos casos, quizás sería necesario buscar mods que de anti-aliasing o que aumenten la resolución interna. Para usar este último, probablemente necesitarás seleccionar Nativa.\n\nEsta opción puede ser modificada mientras que un juego este corriendo haciendo click en \"Aplicar\" más abajo; simplemente puedes mover la ventana de configuración a un lado y experimentar hasta que encuentres tu estilo preferido para un juego.\n\nTener en cuenta que 4x es excesivo para prácticamente cualquier configuración.", - "fr_FR": "Multiplie la résolution de rendu du jeu.\n\nQuelques jeux peuvent ne pas fonctionner avec cette fonctionnalité et sembler pixelisés même lorsque la résolution est augmentée ; pour ces jeux, vous devrez peut-être trouver des mods qui suppriment l'anti-aliasing ou qui augmentent leur résolution de rendu interne. Pour utiliser cette dernière option, vous voudrez probablement sélectionner \"Natif\".\n\nCette option peut être modifiée pendant qu'un jeu est en cours d'exécution en cliquant sur \"Appliquer\" ci-dessous ; vous pouvez simplement déplacer la fenêtre des paramètres sur le côté et expérimenter jusqu'à ce que vous trouviez l'apparence souhaitée pour un jeu.\n\nGardez à l'esprit que 4x est excessif pour pratiquement n'importe quelle configuration.", + "fr_FR": "Multiplie la résolution de rendu du jeu.\n\nQuelques jeux peuvent ne pas fonctionner avec cette fonctionnalité et apparaître pixelisés même lorsque la résolution est augmentée ; pour ces jeux, vous devrez peut-être trouver des mods qui suppriment l'anti-aliasing ou qui augmentent leur résolution de rendu interne. Pour utiliser cette dernière option, vous voudrez probablement sélectionner \"Natif\".\n\nCette option peut être modifiée pendant qu'un jeu est en cours d'exécution en cliquant sur \"Appliquer\" ci-dessous ; vous pouvez simplement déplacer la fenêtre des paramètres sur le côté et expérimenter jusqu'à ce que vous trouviez l'apparence souhaitée pour un jeu.\n\nGardez à l'esprit que 4x est excessif pour pratiquement n'importe quelle configuration.", "he_IL": "", "it_IT": "Moltiplica la risoluzione di rendering del gioco.\n\nAlcuni giochi potrebbero non funzionare con questa opzione e sembrare pixelati anche quando la risoluzione è aumentata; per quei giochi, potrebbe essere necessario trovare mod che rimuovono l'anti-aliasing o che aumentano la risoluzione di rendering interna. Per quest'ultimo caso, probabilmente dovrai selezionare Nativo (1x).\n\nQuesta opzione può essere modificata mentre un gioco è in esecuzione facendo clic su \"Applica\" qui sotto; puoi semplicemente spostare la finestra delle impostazioni da parte e sperimentare fino a quando non trovi il tuo look preferito.\n\nTieni presente che \"4x\" è eccessivo per praticamente qualsiasi configurazione.", "ja_JP": "ゲームのレンダリング解像度倍率を設定します.\n\n解像度を上げてもピクセルのように見えるゲームもあります. そのようなゲームでは, アンチエイリアスを削除するか, 内部レンダリング解像度を上げる mod を見つける必要があるかもしれません. その場合, ようなゲームでは、ネイティブを選択してください.\n\nこのオプションはゲーム実行中に下の「適用」をクリックすることで変更できます. 設定ウィンドウを脇に移動して, ゲームが好みの表示になるよう試してみてください.\n\nどのような設定でも, \"4x\" はやり過ぎであることを覚えておいてください.", @@ -17130,7 +17305,7 @@ "el_GR": "Τοποθεσία Εναπόθεσης Προσωρινής Μνήμης Shaders", "en_US": "Graphics Shaders Dump Path", "es_ES": "Directorio en el cual se volcarán los sombreadores de los gráficos", - "fr_FR": "Chemin de copie des Shaders :", + "fr_FR": "Chemin de sauvegarde des shaders graphiques", "he_IL": "נתיב השלכת הצללות גראפיות", "it_IT": "Percorso di dump degli shader", "ja_JP": "グラフィックス シェーダー ダンプのパスです", @@ -17155,7 +17330,7 @@ "el_GR": "Ενεργοποιεί ή απενεργοποιεί την καταγραφή σε ένα αρχείο στο δίσκο", "en_US": "Saves console logging to a log file on disk. Does not affect performance.", "es_ES": "Guarda los registros de la consola en archivos en disco. No afectan al rendimiento.", - "fr_FR": "Sauvegarde le journal de la console dans un fichier journal sur le disque. Cela n'affecte pas les performances.", + "fr_FR": "Enregistre les journaux de la console dans un fichier sur le disque. N’affecte pas les performances.", "he_IL": "שומר את רישומי שורת הפקודות לזיכרון, לא משפיע על ביצועי היישום.", "it_IT": "Salva il log della console in un file su disco. Non influisce sulle prestazioni.", "ja_JP": "コンソール出力されるログをディスク上のログファイルにセーブします. パフォーマンスには影響を与えません.", @@ -17180,7 +17355,7 @@ "el_GR": "Ενεργοποιεί την εκτύπωση μηνυμάτων καταγραφής ατελειών", "en_US": "Prints stub log messages in the console. Does not affect performance.", "es_ES": "Escribe mensajes de Stub en la consola. No afectan al rendimiento.", - "fr_FR": "Affiche les messages de journaux dans la console. N'affecte pas les performances.", + "fr_FR": "Affiche dans la console les journaux stub. N’affecte pas les performances.", "he_IL": "מדפיס רישומים כושלים לשורת הפקודות. לא משפיע על ביצועי היישום.", "it_IT": "Stampa i messaggi di log relativi alle stub nella console. Non influisce sulle prestazioni.", "ja_JP": "stub ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.", @@ -17205,7 +17380,7 @@ "el_GR": "Ενεργοποιεί την εκτύπωση μηνυμάτων αρχείου καταγραφής πληροφοριών", "en_US": "Prints info log messages in the console. Does not affect performance.", "es_ES": "Escribe mensajes de Info en la consola. No afectan al rendimiento.", - "fr_FR": "Affiche les messages de journaux d'informations dans la console. N'affecte pas les performances.", + "fr_FR": "Affiche dans la console les journaux info. N’affecte pas les performances.", "he_IL": "מדפיק רישומי מידע לשורת הפקודות. לא משפיע על ביצועי היישום.", "it_IT": "Stampa i messaggi di log informativi nella console. Non influisce sulle prestazioni.", "ja_JP": "info ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.", @@ -17230,7 +17405,7 @@ "el_GR": "Ενεργοποιεί την εκτύπωση μηνυμάτων καταγραφής προειδοποιήσεων", "en_US": "Prints warning log messages in the console. Does not affect performance.", "es_ES": "Escribe mensajes de Advertencia en la consola. No afectan al rendimiento.", - "fr_FR": "Affiche les messages d'avertissement dans la console. N'affecte pas les performances.", + "fr_FR": "Affiche dans la console les journaux d’avertissement. N’affecte pas les performances.", "he_IL": "מדפיק רישומי הערות לשורת הפקודות. לא משפיע על ביצועי היישום.", "it_IT": "Stampa i messaggi di log relativi agli avvisi nella console. Non influisce sulle prestazioni.", "ja_JP": "warning ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.", @@ -17255,7 +17430,7 @@ "el_GR": "Ενεργοποιεί την εκτύπωση μηνυμάτων αρχείου καταγραφής σφαλμάτων", "en_US": "Prints error log messages in the console. Does not affect performance.", "es_ES": "Escribe mensajes de Error en la consola. No afectan al rendimiento.", - "fr_FR": "Affiche les messages de journaux d'erreur dans la console. N'affecte pas les performances.", + "fr_FR": "Affiche dans la console les journaux d’erreur. N’affecte pas les performances.", "he_IL": "מדפיס רישומי שגיאות לשורת הפקודות. לא משפיע על ביצועי היישום.", "it_IT": "Stampa i messaggi di log relativi agli errori nella console. Non influisce sulle prestazioni.", "ja_JP": "error ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.", @@ -17280,7 +17455,7 @@ "el_GR": "Ενεργοποιεί την εκτύπωση μηνυμάτων αρχείου καταγραφής ιχνών", "en_US": "Prints trace log messages in the console. Does not affect performance.", "es_ES": "Escribe mensajes de Rastro en la consola. No afectan al rendimiento.", - "fr_FR": "Affiche la trace des messages de journaux dans la console. N'affecte pas les performances.", + "fr_FR": "Affiche dans la console les journaux de trace. N’affecte pas les performances.", "he_IL": "מדפיק רישומי זיכרון לשורת הפקודות. לא משפיע על ביצועי היישום.", "it_IT": "Stampa i messaggi di log relativi al trace nella console. Non influisce sulle prestazioni.", "ja_JP": "trace ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.", @@ -17305,7 +17480,7 @@ "el_GR": "Ενεργοποιεί την εκτύπωση μηνυμάτων καταγραφής επισκεπτών", "en_US": "Prints guest log messages in the console. Does not affect performance.", "es_ES": "Escribe mensajes de Guest en la consola. No afectan al rendimiento.", - "fr_FR": "Affiche les messages de journaux des invités dans la console. N'affecte pas les performances.", + "fr_FR": "Affiche dans la console les journaux du système invité. N’affecte pas les performances.", "he_IL": "מדפיס רישומי אורח לשורת הפקודות. לא משפיע על ביצועי היישום.", "it_IT": "Stampa i messaggi di log del guest nella console. Non influisce sulle prestazioni.", "ja_JP": "guest ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.", @@ -17330,7 +17505,7 @@ "el_GR": "Ενεργοποιεί την εκτύπωση μηνυμάτων αρχείου καταγραφής πρόσβασης", "en_US": "Prints file access log messages in the console.", "es_ES": "Activa mensajes de acceso a archivo en la consola", - "fr_FR": "Affiche les messages de journaux d'accès aux fichiers dans la console.", + "fr_FR": "Affiche dans la console les journaux d’accès aux fichiers.", "he_IL": "מדפיס גישות לקבצי רישום לשורת הפקודות.", "it_IT": "Stampa i messaggi di log relativi all'accesso ai file nella console.", "ja_JP": "ファイルアクセスログメッセージをコンソールに出力します.", @@ -17355,7 +17530,7 @@ "el_GR": "Ενεργοποιεί την έξοδο καταγραφής πρόσβασης FS στην κονσόλα. Οι πιθανοί τρόποι λειτουργίας είναι 0-3", "en_US": "Enables FS access log output to the console. Possible modes are 0-3", "es_ES": "Activa registros FS Access en la consola. Los modos posibles son entre 0 y 3", - "fr_FR": "Active la sortie du journal d'accès FS de la console. Les modes possibles sont 0-3", + "fr_FR": "Active l’affichage des journaux d’accès FS dans la console. Les modes possibles sont de 0 à 3.", "he_IL": "מאפשר גישה לרישומי FS ליציאת שורת הפקודות. האפשרויות הינן 0-3.", "it_IT": "Attiva l'output dei log di accesso FS nella console. Le modalità possibili vanno da 0 a 3", "ja_JP": "コンソールへのファイルシステムアクセスログ出力を有効にします.0-3 のモードが有効です", @@ -17405,7 +17580,7 @@ "el_GR": "", "en_US": "Prints Avalonia (UI) log messages in the console.", "es_ES": "", - "fr_FR": "", + "fr_FR": "Affiche les journaux Avalonia (UI) dans la console.", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -17455,7 +17630,7 @@ "el_GR": "Ενεργοποιεί την εκτύπωση μηνυμάτων αρχείου καταγραφής εντοπισμού σφαλμάτων", "en_US": "Prints debug log messages in the console.\n\nOnly use this if specifically instructed by a staff member, as it will make logs difficult to read and worsen emulator performance.", "es_ES": "Escribe mensajes de debug en la consola\n\nActiva esto solo si un miembro del equipo te lo pide expresamente, pues hará que el registro sea difícil de leer y empeorará el rendimiento del emulador.", - "fr_FR": "Affiche les messages de débogage dans la console.\n\nN'utilisez ceci que si un développeur le demande, car cela rendra les logs difficiles à lire et réduit les performances de l'émulateur.", + "fr_FR": "Affiche dans la console les journaux de débogage.\n\nN’utilisez cette option que si un membre du personnel vous l’a expressément demandé, car cela rendra les journaux difficiles à lire et dégradera les performances de l’émulateur.", "he_IL": "מדפיס הודעות יומן ניפוי באגים בשורת הפקודות.", "it_IT": "Stampa i messaggi di log per il debug nella console.\n\nUsa questa opzione solo se specificatamente richiesto da un membro del team, dal momento che rende i log difficili da leggere e riduce le prestazioni dell'emulatore.", "ja_JP": "デバッグログメッセージをコンソールに出力します.\n\nログが読みづらくなり,エミュレータのパフォーマンスが低下するため,開発者から特別な指示がある場合のみ使用してください.", @@ -17480,7 +17655,7 @@ "el_GR": "Ανοίξτε έναν επιλογέα αρχείων για να επιλέξετε ένα αρχείο συμβατό με το Switch για φόρτωση", "en_US": "Open a file explorer to choose a Switch compatible file to load", "es_ES": "Abre el explorador de archivos para elegir un archivo compatible con Switch para cargar", - "fr_FR": "Ouvre l'explorateur de fichiers pour choisir un fichier compatible Switch à charger", + "fr_FR": "Ouvre un explorateur de fichiers pour choisir un fichier compatible Switch à charger.", "he_IL": "פתח סייר קבצים כדי לבחור קובץ תואם סוויץ' לטעינה", "it_IT": "Apri un selettore file per scegliere un file compatibile con Switch da caricare", "ja_JP": "ロードする Switch 互換のファイルを選択するためファイルエクスプローラを開きます", @@ -17505,7 +17680,7 @@ "el_GR": "Ανοίξτε έναν επιλογέα αρχείων για να επιλέξετε μία μη συσκευασμένη εφαρμογή, συμβατή με το Switch για φόρτωση", "en_US": "Open a file explorer to choose a Switch compatible, unpacked application to load", "es_ES": "Abre el explorador de archivos para elegir un archivo desempaquetado y compatible con Switch para cargar", - "fr_FR": "Ouvre l'explorateur de fichiers pour choisir une application Switch compatible et décompressée à charger", + "fr_FR": "Ouvre un explorateur de fichiers pour choisir une application dépaquetée compatible Switch à charger.", "he_IL": "פתח סייר קבצים כדי לבחור יישום תואם סוויץ', לא ארוז לטעינה.", "it_IT": "Apri un selettore file per scegliere un'applicazione estratta compatibile con Switch da caricare", "ja_JP": "ロードする Switch 互換の展開済みアプリケーションを選択するためファイルエクスプローラを開きます", @@ -17530,7 +17705,7 @@ "el_GR": "", "en_US": "Open a file explorer to choose one or more folders to bulk load DLC from", "es_ES": "Abrir un explorador de archivos para seleccionar una o más carpetas para cargar DLC de forma masiva", - "fr_FR": "Ouvre l'explorateur de fichier pour choisir un ou plusieurs dossiers duquel charger les DLC", + "fr_FR": "Ouvre un explorateur de fichiers pour choisir un ou plusieurs dossiers afin de charger en masse des DLC", "he_IL": "", "it_IT": "Apri un selettore file per scegliere una o più cartelle dalle quali caricare DLC in blocco", "ja_JP": "", @@ -17555,7 +17730,7 @@ "el_GR": "", "en_US": "Open a file explorer to choose one or more folders to bulk load title updates from", "es_ES": "Abrir un explorador de archivos para seleccionar una o más carpetas para cargar actualizaciones de título de forma masiva", - "fr_FR": "Ouvre l'explorateur de fichier pour choisir un ou plusieurs dossiers duquel charger les mises à jour", + "fr_FR": "Ouvre un explorateur de fichiers pour choisir un ou plusieurs dossiers afin de charger en masse des mises à jour de titre.", "he_IL": "", "it_IT": "Apri un selettore file per scegliere una o più cartelle dalle quali caricare aggiornamenti in blocco", "ja_JP": "", @@ -17605,7 +17780,7 @@ "el_GR": "", "en_US": "Open Ryujinx screenshots folder", "es_ES": "", - "fr_FR": "", + "fr_FR": "Ouvrir le dossier des captures d’écran Ryujinx", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -17630,7 +17805,7 @@ "el_GR": "Ανοίξτε το φάκελο στον οποίο διατηρούνται τα αρχεία καταγραφής", "en_US": "Opens the folder where logs are written to", "es_ES": "Abre la carpeta en la que se guardan los registros", - "fr_FR": "Ouvre le dossier dans lequel les journaux sont écrits", + "fr_FR": "Ouvre le dossier où les journaux sont enregistrés", "he_IL": "פותח את התיקיה שאליה נכתבים רישומים", "it_IT": "Apre la cartella dove vengono salvati i log", "ja_JP": "ログが格納されるフォルダを開きます", @@ -17680,7 +17855,7 @@ "el_GR": "Ανοίξτε το παράθυρο Ρυθμίσεων", "en_US": "Open settings window", "es_ES": "Abre la ventana de configuración", - "fr_FR": "Ouvrir la fenêtre de configuration", + "fr_FR": "Ouvrir la fenêtre des paramètres", "he_IL": "פתח את חלון ההגדרות", "it_IT": "Apri la finestra delle impostazioni", "ja_JP": "設定ウインドウを開きます", @@ -17984,7 +18159,7 @@ "he_IL": "מאפשר ליישומים באמולצייה להתחבר לאינטרנט.\n\nמשחקים עם חיבור לאן יכולים להתחבר אחד לשני כשאופצייה זו מופעלת והמערכות מתחברות לאותה נקודת גישה. כמו כן זה כולל שורות פקודות אמיתיות גם.\n\nאופצייה זו לא מאפשרת חיבור לשרתי נינטנדו. כשהאופצייה דלוקה היא עלולה לגרום לקריסת היישום במשחקים מסויימים שמנסים להתחבר לאינטרנט.\n\nמוטב להשאיר כבוי אם לא בטוחים.", "it_IT": "Consente all'applicazione emulata di connettersi a Internet.\n\nI giochi che dispongono di una modalità LAN possono connettersi tra di loro quando questa opzione è abilitata e sono connessi alla stessa rete, comprese le console reali.\n\nQuesta opzione NON consente la connessione ai server di Nintendo. Potrebbe causare arresti anomali in alcuni giochi che provano a connettersi a Internet.\n\nNel dubbio, lascia l'opzione disattivata.", "ja_JP": "エミュレートしたアプリケーションをインターネットに接続できるようにします.\n\nLAN モードを持つゲーム同士は,この機能を有効にして同じアクセスポイントに接続すると接続できます. 実機も含まれます.\n\n任天堂のサーバーには接続できません. インターネットに接続しようとすると,特定のゲームでクラッシュすることがあります.\n\nよくわからない場合はオフのままにしてください.", - "ko_KR": "에뮬레이트된 앱을 인터넷에 연결할 수 있습니다.\n\nLAN 모드가 있는 게임은 이 기능이 활성화되고 시스템이 동일한 접속 포인트에 연결되어 있을 때 서로 연결할 수 있습니다. 이는 실제 콘솔도 포함됩니다.\n\nNintendo 서버 연결을 허용하지 않습니다. 인터넷에 연결을 시도하는 특정 게임에서 충돌이 발생할 수 있습니다.\n\n모르면 끔으로 두세요.", + "ko_KR": "에뮬레이트된 앱을 인터넷에 연결할 수 있습니다.\n\nLAN 모드가 있는 게임은 이 기능이 활성화되고 시스템이 동일한 접속 포인트에 연결되어 있을 때 서로 연결할 수 있습니다. 이는 실제 콘솔도 포함됩니다.\n\nNintendo 서버 연결을 허용하지 않습니다. 인터넷에 연결을 시도하는 특정 게임에서 충돌이 발생할 수 있습니다.\n\n모르면 체크 해제 상태로 두세요.", "no_NO": "Tillater emulert applikasjon å koble til Internett.\n\nSpill med en LAN-modus kan koble til hverandre når dette er aktivert og systemene er koblet til det samme tilgangspunktet. Dette inkluderer ekte konsoller også.\n\ntillater IKKE tilkobling til Nintendo servere. Kan forårsake krasjing i enkelte spill som prøver å koble til Internett.\n\nLa stå AV hvis du er usikker.", "pl_PL": "Pozwala emulowanej aplikacji na łączenie się z Internetem.\n\nGry w trybie LAN mogą łączyć się ze sobą, gdy ta opcja jest włączona, a systemy są połączone z tym samym punktem dostępu. Dotyczy to również prawdziwych konsol.\n\nNie pozwala na łączenie się z serwerami Nintendo. Może powodować awarie niektórych gier, które próbują połączyć się z Internetem.\n\nPozostaw WYŁĄCZONE, jeśli nie masz pewności.", "pt_BR": "Permite que o aplicativo emulado se conecte à Internet.\n\nJogos com modo LAN podem se conectar uns aos outros quando isso está habilitado e os sistemas estão conectados ao mesmo ponto de acesso. Isso inclui consoles reais também.\n\nNÃO permite a conexão com servidores Nintendo. Pode causar travamentos em certos jogos que tentam se conectar à Internet.\n\nDeixe DESLIGADO se não tiver certeza.", @@ -18184,7 +18359,7 @@ "he_IL": "מעבד", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "중앙처리장치", "no_NO": "Prosessor", "pl_PL": "", "pt_BR": "", @@ -18369,7 +18544,7 @@ "tr_TR": "", "uk_UA": "", "zh_CN": "{0} FPS ({1}毫秒)", - "zh_TW": "" + "zh_TW": "{0} FPS ({1}毫秒)" } }, { @@ -18405,7 +18580,7 @@ "el_GR": "", "en_US": "Update Available!", "es_ES": "", - "fr_FR": "", + "fr_FR": "Mise à jour disponible !", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -18530,7 +18705,7 @@ "el_GR": "Σφάλμα κατά την εκκαθάριση του shader cache στο {0}: {1}", "en_US": "Error purging shader cache at {0}: {1}", "es_ES": "Error al eliminar la caché de sombreadores en {0}: {1}", - "fr_FR": "Erreur lors de la purge des Shaders à {0}: {1}", + "fr_FR": "Erreur lors de la purge du cache des shaders à {0} : {1}", "he_IL": "שגיאה בניקוי מטמון ההצללות ב-{0}: {1}", "it_IT": "Errore nell'eliminazione della cache degli shader a {0}: {1}", "ja_JP": "シェーダーキャッシュの破棄エラー {0}: {1}", @@ -18555,7 +18730,7 @@ "el_GR": "Τα κλειδιά δεν βρέθηκαν", "en_US": "Keys not found", "es_ES": "No se encontraron keys", - "fr_FR": "Clés introuvables", + "fr_FR": "Clés non trouvées", "he_IL": "המפתחות לא נמצאו", "it_IT": "Chiavi non trovate", "ja_JP": "Keys がありません", @@ -18630,7 +18805,7 @@ "el_GR": "Η εφαρμογή δε βρέθηκε", "en_US": "Application not found", "es_ES": "No se encontró la aplicación", - "fr_FR": " Application introuvable", + "fr_FR": "Application introuvable", "he_IL": "יישום לא נמצא", "it_IT": "Applicazione non trovata", "ja_JP": "アプリケーションがありません", @@ -18930,7 +19105,7 @@ "el_GR": "", "en_US": "Bundled: Version {0}", "es_ES": "Incorporado: Versión {0}", - "fr_FR": "Inclus avec le jeu: Version {0}", + "fr_FR": "Inclus : Version {0}", "he_IL": "", "it_IT": "Incluso: Versione {0}", "ja_JP": "", @@ -18955,7 +19130,7 @@ "el_GR": "", "en_US": "Bundled:", "es_ES": "Incorporado:", - "fr_FR": "Inclus avec le jeu :", + "fr_FR": "Inclus :", "he_IL": "", "it_IT": "Incluso:", "ja_JP": "", @@ -19080,7 +19255,7 @@ "el_GR": "", "en_US": "Save {0:n0} Mb", "es_ES": "Ahorra {0:n0} Mb", - "fr_FR": "Sauvegarde de {0:n0} Mo", + "fr_FR": "Économiser {0:n0} Mo", "he_IL": "", "it_IT": "Risparmia {0:n0} MB", "ja_JP": "", @@ -19105,7 +19280,7 @@ "el_GR": "", "en_US": "Saved {0:n0} Mb", "es_ES": "{0:n0} Mb ahorrado(s)", - "fr_FR": "Sauvegardé {0:n0} Mo", + "fr_FR": "Économisé {0:n0} Mo", "he_IL": "", "it_IT": "Risparmiati {0:n0} MB", "ja_JP": "", @@ -19659,7 +19834,7 @@ "he_IL": "מוריד עדכון...", "it_IT": "Download dell'aggiornamento...", "ja_JP": "アップデートをダウンロード中...", - "ko_KR": "업데이트 내려받기 중...", + "ko_KR": "업데이트 내려받는 중...", "no_NO": "Laster ned oppdatering...", "pl_PL": "Pobieranie Aktualizacji...", "pt_BR": "Baixando Atualização...", @@ -19680,7 +19855,7 @@ "el_GR": "Προσκολλημένο", "en_US": "Docked", "es_ES": "Dock/TV", - "fr_FR": "Mode station d'accueil", + "fr_FR": "Mode Docké", "he_IL": "בתחנת עגינה", "it_IT": "TV", "ja_JP": "ドッキング", @@ -19905,7 +20080,7 @@ "el_GR": "Επιλέξτε ένα υποστηριζόμενο αρχείο για άνοιγμα", "en_US": "Select a supported file to open", "es_ES": "Selecciona un archivo soportado para cargar", - "fr_FR": "Sélectionnez un fichier supporté à ouvrir", + "fr_FR": "Sélectionnez un fichier compatible à ouvrir", "he_IL": "בחר קובץ נתמך לפתיחה", "it_IT": "Seleziona un file supportato da aprire", "ja_JP": "開くファイルを選択", @@ -20180,7 +20355,7 @@ "el_GR": "Ρυθμίσεις Ελέγχου Κίνησης", "en_US": "Motion Control Settings", "es_ES": "Opciones de controles de movimiento", - "fr_FR": "Réglages des contrôles par mouvement", + "fr_FR": "Paramètres du contrôle de mouvement", "he_IL": "הגדרות שליטת תנועות ג'ירוסקופ", "it_IT": "Impostazioni dei sensori di movimento", "ja_JP": "モーションコントロール設定", @@ -20230,7 +20405,7 @@ "el_GR": "", "en_US": "LED Settings", "es_ES": "", - "fr_FR": "", + "fr_FR": "Paramètres LED", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -20255,7 +20430,7 @@ "el_GR": "Επιλογή Αρχείου Θέματος", "en_US": "Select Theme File", "es_ES": "Selecciona un archivo de tema", - "fr_FR": "Sélectionner un fichier de thème", + "fr_FR": "Sélectionnez un fichier de thème", "he_IL": "בחרו קובץ ערכת נושא", "it_IT": "Seleziona file del tema", "ja_JP": "テーマファイルを選択", @@ -20430,7 +20605,7 @@ "el_GR": "Επιλογή αρχείων DLC", "en_US": "Select DLC files", "es_ES": "Selecciona archivo(s) de DLC", - "fr_FR": "Sélectionner les fichiers DLC", + "fr_FR": "Sélectionnez les fichiers DLC", "he_IL": "בחרו קבצי הרחבות משחק", "it_IT": "Seleziona file dei DLC", "ja_JP": "DLC ファイルを選択", @@ -20455,7 +20630,7 @@ "el_GR": "Επιλογή αρχείων ενημέρωσης", "en_US": "Select update files", "es_ES": "Selecciona archivo(s) de actualización", - "fr_FR": "Sélectionner les fichiers de mise à jour", + "fr_FR": "Sélectionnez les fichiers de mise à jour", "he_IL": "בחרו קבצי עדכון", "it_IT": "Seleziona file di aggiornamento", "ja_JP": "アップデートファイルを選択", @@ -20480,7 +20655,7 @@ "el_GR": "", "en_US": "Select mod directory", "es_ES": "Seleccionar un directorio de Mods", - "fr_FR": "Sélectionner le répertoire du mod", + "fr_FR": "Sélectionnez le répertoire du mod", "he_IL": "בחר תיקיית מודים", "it_IT": "Seleziona cartella delle mod", "ja_JP": "modディレクトリを選択", @@ -20530,7 +20705,7 @@ "el_GR": "", "en_US": "This function will first check the empty space and then trim the XCI File to save disk space.", "es_ES": "Esta función verificará el espacio vacío y después recortará el archivo XCI para ahorrar espacio en disco", - "fr_FR": "Cette fonction va vérifier l'espace vide, puis réduire le fichier XCI pour économiser de l'espace de disque dur.", + "fr_FR": "Cette fonction vérifie d’abord l’espace libre, puis réduit le fichier XCI pour économiser de l’espace disque.", "he_IL": "", "it_IT": "Questa funzionalità controllerà prima lo spazio libero e poi ridurrà la dimensione del file XCI per risparmiare spazio su disco.", "ja_JP": "", @@ -20555,7 +20730,7 @@ "el_GR": "", "en_US": "Current File Size: {0:n} MB\nGame Data Size: {1:n} MB\nDisk Space Savings: {2:n} MB", "es_ES": "Tamaño de archivo actual: {0:n} MB\nTamaño de datos de juego: {1:n} MB\nAhorro de espacio en disco: {2:n} MB", - "fr_FR": "Taille actuelle du fichier: {0:n} MB\nTaille des données de jeux: {1:n} MB\nÉconomie d'espaces sur le disque: {2:n} MB", + "fr_FR": "Taille actuelle du fichier: {0:n} MB\nTaille des données du jeu: {1:n} MB\nEspace disque économisé: {2:n} MB", "he_IL": "", "it_IT": "Dimensione attuale del file: {0:n} MB\nDimensione dei dati del gioco: {1:n} MB\nRisparmio spazio su disco: {2:n} MB", "ja_JP": "", @@ -20580,7 +20755,7 @@ "el_GR": "", "en_US": "XCI File does not need to be trimmed. Check logs for further details", "es_ES": "El archivo XCI no necesita ser recortado. Verifica los logs para más detalles.", - "fr_FR": "Fichier XCI n'a pas besoin d'être réduit. Regarder les journaux pour plus de détails", + "fr_FR": "Le fichier XCI n’a pas besoin d’être réduit. Référez-vous aux journaux pour plus de détails.", "he_IL": "", "it_IT": "Non è necessario ridurre la dimensione del file XCI. Controlla i log per ulteriori dettagli", "ja_JP": "", @@ -20605,7 +20780,7 @@ "el_GR": "", "en_US": "XCI File cannot be untrimmed. Check logs for further details", "es_ES": "El recorte del archivo XCI no puede ser deshecho. Verifica los registros para más detalles.", - "fr_FR": "Fichier XCI ne peut pas être dé-réduit. Regarder les journaux pour plus de détails", + "fr_FR": "Fichier XCI ne peut pas être dé-réduit. Référez-vous aux journaux pour plus de détails", "he_IL": "", "it_IT": "Il file XCI non può essere riportato alla sua dimensione originale. Controlla i log per ulteriori dettagli", "ja_JP": "", @@ -20630,7 +20805,7 @@ "el_GR": "", "en_US": "XCI File is Read Only and could not be made writable. Check logs for further details", "es_ES": "El archivo XCI es de solo Lectura y no se le puede escribir. Lee el registro para más información.", - "fr_FR": "Fichier XCI est en Lecture Seule et n'a pas pu être rendu accessible en écriture. Regarder les journaux pour plus de détails", + "fr_FR": "Fichier XCI est en Lecture Seule et n'a pas pu être rendu accessible en écriture. Référez-vous aux journaux pour plus de détails", "he_IL": "", "it_IT": "Il file XCI è in sola lettura e non può essere reso accessibile in scrittura. Controlla i log per ulteriori dettagli", "ja_JP": "", @@ -20655,7 +20830,7 @@ "el_GR": "", "en_US": "XCI File has changed in size since it was scanned. Please check the file is not being written to and try again.", "es_ES": "El archivo XCI ha cambiado de tamaño desde que fue escaneado. Verifica que no se esté escribiendo al archivo y vuelve a intentarlo.", - "fr_FR": "Fichier XCI a changé en taille depuis qu'il a été scanné. Vérifier que le fichier n'est pas en cours d'écriture et réessayer.", + "fr_FR": "La taille du fichier XCI a changé depuis son analyse. Veuillez vérifier que le fichier n’est pas en cours d’écriture, puis réessayez.", "he_IL": "", "it_IT": "La dimensione del file XCI è cambiata da quando è stato scansionato. Controlla che il file non stia venendo scritto da qualche altro programma e poi riprova.", "ja_JP": "", @@ -20955,7 +21130,7 @@ "el_GR": "", "en_US": "XCI File Trimmer", "es_ES": "Recortador de archivos XCI", - "fr_FR": "Rogneur de fichier XCI", + "fr_FR": "Réducteur de fichiers XCI", "he_IL": "", "it_IT": "Riduci dimensioni dei file XCI", "ja_JP": "", @@ -21105,7 +21280,7 @@ "el_GR": "", "en_US": "Potential Savings", "es_ES": "Ahorro potencial", - "fr_FR": "Économies potentielles d'espace de disque dur", + "fr_FR": "Économies Potentielles", "he_IL": "", "it_IT": "Risparmio potenziale", "ja_JP": "", @@ -21130,7 +21305,7 @@ "el_GR": "", "en_US": "Actual Savings", "es_ES": "Ahorro real", - "fr_FR": "Économies actualles d'espace de disque dur", + "fr_FR": "Économies Réelles", "he_IL": "", "it_IT": "Risparmio effettivo", "ja_JP": "", @@ -21430,7 +21605,7 @@ "el_GR": "", "en_US": "Bundled DLC cannot be removed, only disabled.", "es_ES": "", - "fr_FR": "Les DLC inclus avec le jeu ne peuvent pas être supprimés mais peuvent être désactivés.", + "fr_FR": "Le DLC inclus ne peut pas être supprimé, seulement désactivé.", "he_IL": "", "it_IT": "I DLC inclusi non possono essere rimossi, ma solo disabilitati.", "ja_JP": "", @@ -21955,7 +22130,7 @@ "el_GR": "User Id:", "en_US": "User ID:", "es_ES": "Id de Usuario:", - "fr_FR": "Identifiant de l'utilisateur :", + "fr_FR": "Identifiant utilisateur : ", "he_IL": "מזהה משתמש:", "it_IT": "ID utente:", "ja_JP": "ユーザID:", @@ -22005,7 +22180,7 @@ "el_GR": "", "en_US": "Select the graphics backend that will be used in the emulator.\n\nVulkan is overall better for all modern graphics cards, as long as their drivers are up to date. Vulkan also features faster shader compilation (less stuttering) on all GPU vendors.\n\nOpenGL may achieve better results on old Nvidia GPUs, on old AMD GPUs on Linux, or on GPUs with lower VRAM, though shader compilation stutters will be greater.\n\nSet to Vulkan if unsure. Set to OpenGL if your GPU does not support Vulkan even with the latest graphics drivers.", "es_ES": "Seleccione el backend gráfico que utilizará el emulador.\n\nVulkan, en general, es mejor para todas las tarjetas gráficas modernas, mientras que sus controladores estén actualizados. Vulkan también cuenta con complicación más rápida de sombreadores (menos tirones) en todos los proveredores de GPU.\n\nOpenGL puede lograr mejores resultados en GPU Nvidia antiguas, GPU AMD antiguas en Linux o en GPUs con menor VRAM, aunque tirones de compilación de sombreadores serán mayores.\n\nSetear en Vulkan si no sabe que hacer. Setear en OpenGL si su GPU no tiene soporte para Vulkan aún con los últimos controladores gráficos.", - "fr_FR": "Sélectionnez le moteur graphique qui sera utilisé dans l'émulateur.\n\nVulkan est globalement meilleur pour toutes les cartes graphiques modernes, tant que leurs pilotes sont à jour. Vulkan offre également une compilation de shaders plus rapide (moins de saccades) sur tous les fournisseurs de GPU.\n\nOpenGL peut obtenir de meilleurs résultats sur d'anciennes cartes graphiques Nvidia, sur d'anciennes cartes graphiques AMD sous Linux, ou sur des GPU avec moins de VRAM, bien que les saccades dues à la compilation des shaders soient plus importantes.\n\nRéglez sur Vulkan si vous n'êtes pas sûr. Réglez sur OpenGL si votre GPU ne prend pas en charge Vulkan même avec les derniers pilotes graphiques.", + "fr_FR": "Sélectionnez le moteur graphique à utiliser dans l’émulateur.\n\nVulkan est généralement préférable pour toutes les cartes graphiques modernes, à condition que leurs pilotes soient à jour. Vulkan offre également une compilation des shaders plus rapide (moins de saccades) chez tous les fabricants de GPU.\n\nOpenGL peut donner de meilleurs résultats sur d’anciennes cartes Nvidia, sur de vieux GPU AMD sous Linux, ou sur des GPU avec moins de mémoire vidéo, mais la compilation des shaders provoquera davantage de saccade\n\nChoisissez Vulkan si vous n’êtes pas sûr. Optez pour OpenGL si votre GPU ne prend pas en charge Vulkan, même avec les derniers pilotes graphiques.", "he_IL": "", "it_IT": "Seleziona il backend grafico che verrà utilizzato nell'emulatore.\n\nVulkan è nel complesso migliore per tutte le schede grafiche moderne, a condizione che i relativi driver siano aggiornati. Vulkan dispone anche di una compilazione degli shader più veloce (con minore stuttering) su tutte le marche di GPU.\n\nOpenGL può ottenere risultati migliori su vecchie GPU Nvidia, su vecchie GPU AMD su Linux, o su GPU con poca VRAM, anche se lo stuttering dovuto alla compilazione degli shader sarà maggiore.\n\nNel dubbio, scegli Vulkan. Seleziona OpenGL se la GPU non supporta Vulkan nemmeno con i driver grafici più recenti.", "ja_JP": "エミュレーションに使用するグラフィックスバックエンドを選択します.\n\nVulkanは, 最近のグラフィックカードでドライバが最新であれば, 全体的に優れています. すべてのGPUベンダーで, シェーダーコンパイルがより高速で, スタッタリングが少ないのが特徴です.\n\n古いNvidia GPU, Linuxでの古いAMD GPU, VRAMの少ないGPUなどでは, OpenGLの方が良い結果が得られるかもしれません. ですが, シェーダーコンパイルのスタッターは大きくなります.\n\n不明な場合はVulkanに設定してください。最新のグラフィックドライバでもVulkanをサポートしていないGPUの場合は, OpenGLに設定してください.", @@ -22055,7 +22230,7 @@ "el_GR": "", "en_US": "Uses Vulkan.\nOn an ARM Mac, and when playing a game that runs well under it, uses the Metal backend.", "es_ES": "", - "fr_FR": "", + "fr_FR": "Utilise Vulkan.\nSur un Mac ARM, et lorsqu’un jeu fonctionne bien avec, utilise le moteur Metal.", "he_IL": "", "it_IT": "Utilizza Vulkan.\nSu un Mac con processore ARM, utilizza il backend Metal nei giochi che funzionano bene con quest'ultimo.", "ja_JP": "", @@ -22105,11 +22280,11 @@ "el_GR": "", "en_US": "Compresses ASTC textures in order to reduce VRAM usage.\n\nGames using this texture format include Astral Chain, Bayonetta 3, Fire Emblem Engage, Metroid Prime Remastered, Super Mario Bros. Wonder and The Legend of Zelda: Tears of the Kingdom.\n\nGraphics cards with 4GiB VRAM or less will likely crash at some point while running these games.\n\nEnable only if you're running out of VRAM on the aforementioned games. Leave OFF if unsure.", "es_ES": "Comprimir texturas ASTC para reducir uso de VRAM.\n\nJuegos que utilizan este formato de textura incluyen Astral Chain, Bayonetta 3, Fire Emblem Engage, Metroid Prime Remastered, Super Mario Bros. Wonder y The Legend of Zelda: Tears of the Kingdom.\n\nTarjetas gráficas con 4GiB de VRAM o menos probalemente se caeran en algún momento mientras que estén corriendo estos juegos.\n\nActivar solo si está quedan sin VRAM en los juegos antes mencionados. Desactívalo si no sabes qué hacer.", - "fr_FR": "Les jeux utilisant ce format de texture incluent Astral Chain, Bayonetta 3, Fire Emblem Engage, Metroid Prime Remastered, Super Mario Bros. Wonder et The Legend of Zelda: Tears of the Kingdom.\n\nLes cartes graphiques avec 4 Go ou moins de VRAM risquent probablement de planter à un moment donné lors de l'exécution de ces jeux.\n\nActivez uniquement si vous manquez de VRAM sur les jeux mentionnés ci-dessus. Laissez DÉSACTIVÉ si vous n'êtes pas sûr.", + "fr_FR": "Compresse les textures ASTC pour réduire l’utilisation de la VRAM.\n\nLes jeux utilisant ce format de texture incluent Astral Chain, Bayonetta 3, Fire Emblem Engage, Metroid Prime Remastered, Super Mario Bros. Wonder et The Legend of Zelda: Tears of the Kingdom.\n\nLes cartes graphiques avec 4GiO de VRAM ou moins risquent de planter à un moment donné en jouant à ces jeux.\n\nActivez cette option uniquement si vous manquez de VRAM sur ces jeux. Laissez DÉSACTIVÉ si vous n'êtes pas sûr.", "he_IL": "", "it_IT": "Comprime le texture ASTC per ridurre l'utilizzo di VRAM.\n\nI giochi che utilizzano questo formato di texture includono Astral Chain, Bayonetta 3, Fire Emblem Engage, Metroid Prime Remastered, Super Mario Bros. Wonder e The Legend of Zelda: Tears of the Kingdom.\n\nLe schede grafiche con 4GiB o meno di VRAM probabilmente si bloccheranno ad un certo punto durante l'esecuzione di questi giochi.\n\nAttiva questa opzione solo se sei a corto di VRAM nei giochi sopra menzionati. Nel dubbio, lascia l'opzione disattivata.", "ja_JP": "VRAM使用量を減らすためにASTCテクスチャを圧縮します.\n\nこのテクスチャフォーマットを使用するゲームには, Astral Chain, Bayonetta 3, Fire Emblem Engage, Metroid Prime Remastered, Super Mario Bros. Wonder, The Legend of Zelda: Tears of the Kingdomが含まれます.\n\nVRAMが4GB以下のグラフィックカードでは, これらのゲームを実行中にクラッシュする可能性があります.\n\n前述のゲームでVRAMが不足している場合のみ有効にしてください. 不明な場合はオフにしてください.", - "ko_KR": "VRAM 사용량을 줄이기 위해 ASTC 텍스처를 압축합니다.\n\n이 텍스처 형식을 사용하는 게임에는 Astral Chain, Bayonetta 3, Fire Emblem Engage, Metroid Prime Remastered, Super Mario Bros. Wonder, The Legend of Zelda: Tears of the Kingdom이 있습니다.\n\n4GiB VRAM 이하의 그래픽 카드는 이러한 게임을 실행하는 동안 어느 시점에서 충돌할 가능성이 있습니다.\n\n위에서 언급한 게임에서 VRAM이 부족한 경우에만 활성화합니다. 모르면 끔으로 두세요.", + "ko_KR": "VRAM 사용량을 줄이기 위해 ASTC 텍스처를 압축합니다.\n\n이 텍스처 형식을 사용하는 게임에는 애스트럴 체인, 베요네타 3, 파이어 엠블렘 인게이지, 메트로이드 프라임 리마스터, 슈퍼 마리오브라더스 원더, 젤다의 전설 티어스 오브 더 킹덤이 있습니다.\n\n4GiB VRAM 이하의 그래픽 카드는 이러한 게임을 실행하는 동안 어느 시점에서 충돌할 가능성이 있습니다.\n\n위에서 언급한 게임에서 VRAM이 부족한 경우에만 활성화합니다. 모르면 체크 해제 상태로 두세요.", "no_NO": "Kompresser ASTC-teksturer for å redusere VRAM-bruk.\n\nSpill som bruker dette teksturformatet, inkluderer Astral Chain, Bayonetta 3, Fire Emblem Engage, Metroid Prime Remastered, Super Mario Bros. Wonder and The Legend of Zelda: Tears of the Kingdom.\n\nGrafikkkort med 4GiB VRAM eller mindre, vil sannsynligvis krasje på et tidspunkt når spillene kjører.\n\nAktiver bare hvis du går tom for VRAM på nevnte spill. La AV om du er usikker.", "pl_PL": "", "pt_BR": "Compacta texturas ASTC para reduzir o uso de VRAM.\n\nJogos que usam esse formato de textura incluem Astral Chain, Bayonetta 3, Fire Emblem Engage, Metroid Prime Remastered, Super Mario Bros. Wonder e The Legend of Zelda: Tears of the Kingdom.\n\nPlacas gráficas com 4GB VRAM ou menos provavelmente travarão em algum momento durante a execução desses jogos.\n\nHabilite somente se estiver ficando sem VRAM nos jogos mencionados acima. Deixe DESLIGADO se não tiver certeza.", @@ -22155,7 +22330,7 @@ "el_GR": "Επιλέξτε την κάρτα γραφικών η οποία θα χρησιμοποιηθεί από το Vulkan.\n\nΔεν επηρεάζει το OpenGL.\n\nΔιαλέξτε την GPU που διαθέτει την υπόδειξη \"dGPU\" αν δεν είστε βέβαιοι. Αν δεν υπάρχει κάποιαν, το πειράξετε", "en_US": "Select the graphics card that will be used with the Vulkan graphics backend.\n\nDoes not affect the GPU that OpenGL will use.\n\nSet to the GPU flagged as \"dGPU\" if unsure. If there isn't one, leave untouched.", "es_ES": "Selecciona la tarjeta gráfica que se utilizará con los back-end de gráficos Vulkan.\n\nNo afecta la GPU que utilizará OpenGL.\n\nFije a la GPU marcada como \"dGUP\" ante dudas. Si no hay una, no haga modificaciones.", - "fr_FR": "Sélectionnez la carte graphique qui sera utilisée avec l'interface graphique Vulkan.\n\nCela ne change pas le GPU qu'OpenGL utilisera.\n\nChoisissez le GPU noté \"dGPU\" si vous n'êtes pas sûr. S'il n'y en a pas, ne pas modifier.", + "fr_FR": "Sélectionnez la carte graphique qui sera utilisée avec le moteur graphique Vulkan.\n\nCela n’affecte pas le GPU utilisé par OpenGL.\n\nChoisissez le GPU identifié comme « dGPU » si vous n’êtes pas sûr. S’il n’y en a pas, laissez tel quel.", "he_IL": "בחר את הכרטיס הגראפי שישומש עם הגראפיקה של וולקאן.\n\nדבר זה לא משפיע על הכרטיס הגראפי שישומש עם OpenGL.\n\nמוטב לבחור את ה-GPU המסומן כ-\"dGPU\" אם אינכם בטוחים, אם זו לא אופצייה, אל תשנו דבר.", "it_IT": "Seleziona la scheda grafica che verrà usata con il backend grafico Vulkan.\n\nL'opzione non modifica la GPU usata da OpenGL.\n\nNel dubbio, seleziona la GPU contrassegnata come \"dGPU\". Se non ce n'è una, lascia intatta questa opzione.", "ja_JP": "Vulkanグラフィックスバックエンドで使用されるグラフィックスカードを選択します.\n\nOpenGLが使用するGPUには影響しません.\n\n不明な場合は, \"dGPU\" としてフラグが立っているGPUに設定します. ない場合はそのままにします.", @@ -22359,7 +22534,7 @@ "he_IL": "אמולצייה ברמה גבוהה של כרטיס גראפי עם קוד מקרו.\n\nמשפר את ביצועי היישום אך עלול לגרום לגליצ'ים חזותיים במשחקים מסויימים.\n\nמוטב להשאיר דלוק אם אינך בטוח.", "it_IT": "Emulazione di alto livello del codice macro della GPU.\n\nMigliora le prestazioni, ma può causare anomalie grafiche in alcuni giochi.\n\nNel dubbio, lascia l'opzione attiva.", "ja_JP": "GPU マクロコードの高レベルエミュレーションです.\n\nパフォーマンスを向上させますが, 一部のゲームでグラフィックに不具合が発生する可能性があります.\n\nよくわからない場合はオンのままにしてください.", - "ko_KR": "GPU 매크로 코드의 고수준 에뮬레이션입니다.\n\n성능은 향상되지만 일부 게임에서 그래픽 오류가 발생할 수 있습니다.\n\n모르면 켬으로 두세요.", + "ko_KR": "GPU 매크로 코드의 고수준 에뮬레이션입니다.\n\n성능은 향상되지만 일부 게임에서 그래픽 오류가 발생할 수 있습니다.\n\n모르면 체크 상태로 두세요.", "no_NO": "High-level emulering av GPU makrokode.\n\nForbedrer ytelse, men kan forårsake grafiske glitches i noen spill.\n\nForlat PÅ hvis usikker.", "pl_PL": "Wysokopoziomowa emulacja kodu GPU Macro.\n\nPoprawia wydajność, ale może powodować błędy graficzne w niektórych grach.\n\nW razie wątpliwości pozostaw WŁĄCZONE.", "pt_BR": "Habilita emulação de alto nível de códigos Macro da GPU.\n\nMelhora a performance, mas pode causar problemas gráficos em alguns jogos.\n\nEm caso de dúvida, deixe ATIVADO.", @@ -22755,7 +22930,7 @@ "el_GR": "", "en_US": "Applies anti-aliasing to the game render.\n\nFXAA will blur most of the image, while SMAA will attempt to find jagged edges and smooth them out.\n\nNot recommended to use in conjunction with the FSR scaling filter.\n\nThis option can be changed while a game is running by clicking \"Apply\" below; you can simply move the settings window aside and experiment until you find your preferred look for a game.\n\nLeave on NONE if unsure.", "es_ES": "Aplica antia-aliasing al rendereo del juego.\n\nFXAA desenfocará la mayor parte del la iamgen, mientras que SMAA intentará encontrar bordes irregulares y suavizarlos.\n\nNo se recomienda usar en conjunto con filtro de escala FSR.\n\nEsta opción puede ser modificada mientras que esté corriendo el juego haciendo click en \"Aplicar\" más abajo; simplemente puedes mover la ventana de configuración a un lado y experimentar hasta que encuentres tu estilo preferido para un juego.\n\nDejar en NADA si no está seguro.", - "fr_FR": "FXAA floute la plupart de l'image, tandis que SMAA tente de détecter les contours dentelés et de les lisser.\n\nIl n'est pas recommandé de l'utiliser en conjonction avec le filtre de mise à l'échelle FSR.\n\nCette option peut être modifiée pendant qu'un jeu est en cours d'exécution en cliquant sur \"Appliquer\" ci-dessous ; vous pouvez simplement déplacer la fenêtre des paramètres sur le côté et expérimenter jusqu'à ce que vous trouviez l'apparence souhaitée pour un jeu.\n\nLaissez sur AUCUN si vous n'êtes pas sûr.", + "fr_FR": "Applique l’anticrénelage au rendu du jeu.\n\nFXAA floute la plupart de l’image, tandis que SMAA tente de détecter les contours irréguliers pour les lisser.\n\nIl n’est pas recommandé d’utiliser cette option avec le filtre de mise à l’échelle FSR.\n\nCette option peut être modifiée pendant que le jeu tourne en cliquant sur « Appliquer » ci-dessous ; vous pouvez simplement déplacer la fenêtre des paramètres pour tester jusqu’à trouver l’apparence qui vous convient.\n\nLaissez sur AUCUN si vous n’êtes pas sûr.", "he_IL": "", "it_IT": "Applica l'anti-aliasing al rendering del gioco.\n\nFXAA rende la maggior parte dell'immagine sfocata, mentre SMAA tenta di rilevare e smussare i bordi frastagliati.\n\nSi consiglia di non usarlo in combinazione con il filtro di scaling FSR.\n\nQuesta opzione può essere modificata mentre un gioco è in esecuzione facendo clic su \"Applica\" qui sotto; puoi semplicemente spostare la finestra delle impostazioni da parte e sperimentare fino a quando non trovi il tuo look preferito per un gioco.\n\nNel dubbio, lascia su Nessuno.", "ja_JP": "ゲームレンダリングにアンチエイリアスを適用します.\n\nFXAAは画像の大部分をぼかし, SMAAはギザギザのエッジを見つけて滑らかにします.\n\nFSRスケーリングフィルタとの併用は推奨しません.\n\nこのオプションは, ゲーム実行中に下の「適用」をクリックして変更できます. 設定ウィンドウを脇に移動し, ゲームが好みの表示になるように試してみてください.\n\n不明な場合は「なし」のままにしておいてください.", @@ -22880,14 +23055,14 @@ "el_GR": "", "en_US": "Nearest", "es_ES": "Cercano", - "fr_FR": "Le plus proche", + "fr_FR": "Plus proche", "he_IL": "", "it_IT": "", "ja_JP": "", "ko_KR": "근린", "no_NO": "Nærmeste", "pl_PL": "Najbliższe", - "pt_BR": "", + "pt_BR": "Mais Próximo", "ru_RU": "Ступенчатая", "sv_SE": "Närmaste", "th_TH": "ใกล้สุด", @@ -22980,7 +23155,7 @@ "el_GR": "", "en_US": "Set FSR 1.0 sharpening level. Higher is sharper.", "es_ES": "Ajuste el nivel de nitidez FSR 1.0. Mayor es más nítido.", - "fr_FR": "Définissez le niveau de netteté FSR 1.0. Plus élevé signifie plus net.", + "fr_FR": "Définir le niveau de netteté FSR 1.0. Plus la valeur est élevée, plus l'image est nette.", "he_IL": "", "it_IT": "Imposta il livello di nitidezza di FSR 1.0. Valori più alti comportano una maggiore nitidezza.", "ja_JP": "FSR 1.0のシャープ化レベルを設定します. 高い値ほどシャープになります.", @@ -23030,7 +23205,7 @@ "el_GR": " Μεσαίο SMAA", "en_US": "SMAA Medium", "es_ES": "SMAA Medio", - "fr_FR": "SMAA moyen", + "fr_FR": "SMAA Moyenne", "he_IL": "SMAA בינוני", "it_IT": "SMAA Medio", "ja_JP": "", @@ -23055,7 +23230,7 @@ "el_GR": "Υψηλό SMAA", "en_US": "SMAA High", "es_ES": "SMAA Alto", - "fr_FR": "SMAA Élevé", + "fr_FR": "SMAA Élevée", "he_IL": "SMAA גבוהה", "it_IT": "SMAA Alto", "ja_JP": "", @@ -23180,7 +23355,7 @@ "el_GR": "", "en_US": "The network interface used for LAN/LDN features.\n\nIn conjunction with a VPN or XLink Kai and a game with LAN support, can be used to spoof a same-network connection over the Internet.\n\nLeave on DEFAULT if unsure.", "es_ES": "Interfaz de red usada para características LAN/LDN.\n\njunto con una VPN o XLink Kai y un juego con soporte LAN, puede usarse para suplantar una conexión de la misma red a través de Internet.\n\nDeje en DEFAULT si no está seguro.", - "fr_FR": "L'interface réseau utilisée pour les fonctionnalités LAN/LDN.\n\nEn conjonction avec un VPN ou XLink Kai et un jeu prenant en charge le LAN, peut être utilisée pour simuler une connexion sur le même réseau via Internet.\n\nLaissez sur PAR DÉFAUT si vous n'êtes pas sûr.", + "fr_FR": "L'interface réseau utilisée pour les fonctionnalités LAN/LDN.\n\nEn conjonction avec un VPN ou XLink Kai et un jeu prenant en charge le LAN, peut être utilisée pour simuler une connexion sur le même réseau via Internet.\n\nLaissez sur DÉFAUT si vous n'êtes pas sûr.", "he_IL": "", "it_IT": "L'interfaccia di rete utilizzata per le funzionalità LAN/LDN.\n\nIn combinazione con una VPN o XLink Kai e un gioco che supporta la modalità LAN, questa opzione può essere usata per simulare la connessione alla stessa rete attraverso Internet.\n\nNel dubbio, lascia l'opzione su Predefinito.", "ja_JP": "LAN/LDN機能に使用されるネットワークインタフェースです.\n\nVPNやXLink Kai、LAN対応のゲームと併用することで, インターネット上の同一ネットワーク接続になりすますことができます.\n\n不明な場合はデフォルトのままにしてください.", @@ -23205,7 +23380,7 @@ "el_GR": "Προεπιλογή", "en_US": "Default", "es_ES": "Predeterminado", - "fr_FR": "Par défaut", + "fr_FR": "Défaut", "he_IL": "ברירת המחדל", "it_IT": "Predefinito", "ja_JP": "デフォルト", @@ -23250,26 +23425,26 @@ { "ID": "AboutChangelogButton", "Translations": { - "ar_SA": "عرض سجل التغييرات على غيت هاب", - "de_DE": "Changelog in GitHub öffnen", - "el_GR": "Προβολή αρχείου αλλαγών στο GitHub", - "en_US": "View Changelog on GitHub", - "es_ES": "Ver registro de cambios en GitHub", - "fr_FR": "Voir le Changelog sur GitHub", - "he_IL": "צפה במידע אודות שינויים בגיטהב", - "it_IT": "Visualizza changelog su GitHub", - "ja_JP": "GitHub で更新履歴を表示", - "ko_KR": "GitHub에서 변경 내역 보기", - "no_NO": "Vis endringslogg på GitHub", - "pl_PL": "Zobacz listę zmian na GitHubie", - "pt_BR": "Ver Mudanças no GitHub", - "ru_RU": "Показать список изменений на GitHub", - "sv_SE": "Visa ändringslogg på GitHub", - "th_TH": "ดูประวัติการเปลี่ยนแปลงบน GitHub", - "tr_TR": "GitHub'da Değişiklikleri Görüntüle", - "uk_UA": "Переглянути журнал змін на GitHub", - "zh_CN": "在 Github 上查看更新日志", - "zh_TW": "在 GitHub 上檢視更新日誌" + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "View Changelog", + "es_ES": "", + "fr_FR": "Voir Changelog", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "변경 로그 보기", + "no_NO": "", + "pl_PL": "", + "pt_BR": "Ver Registro", + "ru_RU": "", + "sv_SE": "Visa ändringslogg", + "th_TH": "ด", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "查看更新日志", + "zh_TW": "檢視更新日誌" } }, { @@ -23384,7 +23559,7 @@ "he_IL": "", "it_IT": "Disabilitato", "ja_JP": "無効", - "ko_KR": "비활성화됨", + "ko_KR": "비활성화", "no_NO": "Deaktivert", "pl_PL": "Wyłączone", "pt_BR": "Desativado", @@ -23494,7 +23669,7 @@ "tr_TR": "", "uk_UA": "Вимкнути хостинг P2P мережі, піри будуть підключатися через майстер-сервер замість прямого з'єднання з вами.", "zh_CN": "禁用 P2P 网络连接,对方将通过主服务器进行连接,而不是直接连接到您。", - "zh_TW": "停用對等網路代管 (P2P Network Hosting), 用戶群會經過代理何服器而非直接連線至你的主機。" + "zh_TW": "停用對等網路代管 (P2P Network Hosting), 用戶群會經過代理伺服器而非直接連線至你的主機。" } }, { @@ -23909,7 +24084,7 @@ "he_IL": "", "it_IT": "Consente all'utente di specificare una frequenza di aggiornamento emulata. In alcuni titoli potrebbe aumentare o diminuire la velocità del gameplay, mentre in altri potrebbe consentire di limitare il framerate a un multiplo della frequenza di aggiornamento, o causare comportamenti imprevedibili. Questa funzionalità è sperimentale, e non ci sono certezze sul modo in cui influenzerà il gameplay.\n\nNel dubbio, lascia l'opzione disattivata.", "ja_JP": "", - "ko_KR": "사용자가 에뮬레이트된 화면 주사율을 지정할 수 있습니다. 일부 타이틀에서는 게임플레이 로직 속도가 빨라지거나 느려질 수 있습니다. 다른 타이틀에서는 주사율의 배수로 FPS를 제한하거나 예측할 수 없는 동작으로 이어질 수 있습니다. 이는 실험적 기능으로 게임 플레이에 어떤 영향을 미칠지 보장할 수 없습니다. \n\n모르면 끔으로 두세요.", + "ko_KR": "사용자가 에뮬레이트된 화면 주사율을 지정할 수 있습니다. 일부 타이틀에서는 게임플레이 로직 속도가 빨라지거나 느려질 수 있습니다. 다른 타이틀에서는 주사율의 배수로 FPS를 제한하거나 예측할 수 없는 동작으로 이어질 수 있습니다. 이는 실험적 기능으로 게임 플레이에 어떤 영향을 미칠지 보장할 수 없습니다. \n\n모르면 체크 해제 상태로 두세요.", "no_NO": "Gjør det mulig for brukeren å angi en emulert oppdateringsfrekvens. I noen titler kan dette øke eller senke hastigheten på spillogikken. I andre titler kan det gjøre det mulig å begrense FPS til et multiplum av oppdateringsfrekvensen, eller føre til uforutsigbar oppførsel. Dette er en eksperimentell funksjon, og det gis ingen garantier for hvordan spillingen påvirkes. \n\nLa AV stå hvis du er usikker.", "pl_PL": "", "pt_BR": "Permite que o usuário especifique uma taxa de atualização emulada. Em alguns títulos, isso pode acelerar ou desacelerar a taxa de lógica do jogo. Em outros títulos, pode permitir limitar o FPS em algum múltiplo da taxa de atualização ou levar a um comportamento imprevisível. Este é um recurso experimental, sem garantias de como o jogo será afetado. \n\nDeixe OFF se não tiver certeza.", @@ -23980,7 +24155,7 @@ "el_GR": "", "en_US": "Custom Refresh Rate %:", "es_ES": "", - "fr_FR": "Pourcentage du Taux de Rafraîchissement Customisé :", + "fr_FR": "% du taux de rafraîchissement personnalisé :", "he_IL": "", "it_IT": "Frequenza di aggiornamento personalizzata (%):", "ja_JP": "", @@ -24055,7 +24230,7 @@ "el_GR": "", "en_US": "Toggle VSync mode:", "es_ES": "", - "fr_FR": "Activer/Désactiver mode VSync :", + "fr_FR": "Basculer le mode VSync :", "he_IL": "", "it_IT": "Cambia modalità VSync:", "ja_JP": "", @@ -24137,7 +24312,7 @@ "ko_KR": "터보 모드 :", "no_NO": "", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Modo Turbo:", "ru_RU": "", "sv_SE": "Turboläge:", "th_TH": "", @@ -24162,7 +24337,7 @@ "ko_KR": "터보 모드 단축키입니다.\nRyujinx CPU 설정에서 터보 모드의 동작을 구성합니다.\n\n모르면 바인딩 해제 상태로 두세요.", "no_NO": "Hurtigtasten for turbo-modus.\nKonfigurer oppførselen til turbo-modus i Ryujinx CPU-innstillinger.\n\nLa være ubundet hvis du er usikker.", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Tecla de atalho do Modo Turbo.\nConfigure o comportamento do Modo Turbo nas configurações de CPU do Ryujinx.\n\nDeixe Não Atribuído se não tiver certeza.", "ru_RU": "", "sv_SE": "Snabbtangenten för turboläge.\nKonfigurera beteendet för turboläge i Ryujinx CPU-inställningar.\n\nLämna Obunden om du är osäker.", "th_TH": "", @@ -24180,14 +24355,14 @@ "el_GR": "", "en_US": "Only while pressed", "es_ES": "", - "fr_FR": "Seulement quand le raccourci est maintenu", + "fr_FR": "Uniquement en appuyant", "he_IL": "", "it_IT": "", "ja_JP": "", "ko_KR": "누르고 있는 동안만", "no_NO": "Bare mens du trykker på", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Somente enquanto pressionado.", "ru_RU": "", "sv_SE": "Endast när du trycker ner", "th_TH": "", @@ -24205,7 +24380,7 @@ "el_GR": "", "en_US": "Last updated: {0}", "es_ES": "", - "fr_FR": "", + "fr_FR": "Dernière mise à jour : {0}", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -24230,14 +24405,14 @@ "el_GR": "", "en_US": "Compatibility List - {0} entries", "es_ES": "", - "fr_FR": "", + "fr_FR": "Liste de Compatibilité – {0} entrées", "he_IL": "", "it_IT": "", "ja_JP": "", "ko_KR": "호환성 목록 - {0}개 항목", "no_NO": "Kompatibilitetsliste - {0} oppføringer", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Lista de Compatibilidade - {0} registros", "ru_RU": "Список совместимости — записей: {0}", "sv_SE": "Kompatibilitetslista - {0} poster", "th_TH": "", @@ -24255,7 +24430,7 @@ "el_GR": "", "en_US": "This compatibility list might contain out of date entries.\nDo not be opposed to testing games in the \"Ingame\" status.", "es_ES": "", - "fr_FR": "", + "fr_FR": "Cette liste de compatibilité peut contenir des entrées obsolètes.N’hésitez pas à tester les jeux dont le statut est « En cours ».", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -24280,7 +24455,7 @@ "el_GR": "", "en_US": "Search compatibility entries...", "es_ES": "", - "fr_FR": "", + "fr_FR": "Rechercher des entrées de compatibilité...", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -24305,14 +24480,14 @@ "el_GR": "", "en_US": "Search {0} compatibility entries...", "es_ES": "", - "fr_FR": "", + "fr_FR": "Rechercher parmi {0} entrées de compatibilité...", "he_IL": "", "it_IT": "", "ja_JP": "", "ko_KR": "어카이브 {0} 호환성 항목...", "no_NO": "Søk i {0} kompatibilitetsoppføringer...", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Procurando {0} registros de compatibilidade...", "ru_RU": "Поиск среди {0} записей о совместимости...", "sv_SE": "Sök i {0} kompatibilitetsposter...", "th_TH": "", @@ -24330,7 +24505,7 @@ "el_GR": "", "en_US": "Open Compatibility List", "es_ES": "", - "fr_FR": "", + "fr_FR": "Ouvrir la liste de compatibilité", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -24347,6 +24522,106 @@ "zh_TW": "開啟相容性列表" } }, + { + "ID": "CompatibilityListGamesAndApplications", + "Translations": { + "ar_SA": "", + "de_DE": "Spiele & Anwendungen", + "el_GR": "Παιχνίδια και Εφαρμογές", + "en_US": "Games & Applications", + "es_ES": "Juegos y Aplicaciones", + "fr_FR": "Jeux et Applications", + "he_IL": "משחקים ואפליקציות", + "it_IT": "Giochi e Applicazioni", + "ja_JP": "ゲームとアプリケーション", + "ko_KR": "게임 및 애플리케이션", + "no_NO": "Spill og Applikasjoner", + "pl_PL": "Gry i Aplikacje", + "pt_BR": "Jogos e Aplicativos", + "ru_RU": "Игры и Приложения", + "sv_SE": "Spel och applikationer", + "th_TH": "", + "tr_TR": "Oyunlar ve Uygulamalar", + "uk_UA": "Ігри та Додатки", + "zh_CN": "游戏和应用程序", + "zh_TW": "遊戲與應用程式" + } + }, + { + "ID": "CompatibilityListStatus", + "Translations": { + "ar_SA": "الحالة", + "de_DE": "", + "el_GR": "Κατάσταση", + "en_US": "Status", + "es_ES": "Estado", + "fr_FR": "Statut", + "he_IL": "מצב", + "it_IT": "Stato", + "ja_JP": "状況", + "ko_KR": "상태", + "no_NO": "", + "pl_PL": "Stan", + "pt_BR": "Estado", + "ru_RU": "Статус", + "sv_SE": "", + "th_TH": "สถานะ", + "tr_TR": "Durum", + "uk_UA": "Статус", + "zh_CN": "状态", + "zh_TW": "狀態" + } + }, + { + "ID": "CompatibilityListDescription", + "Translations": { + "ar_SA": "", + "de_DE": "Probleme und Merkmale", + "el_GR": "Προβλήματα και Χαρακτηριστικά", + "en_US": "Issues & Features", + "es_ES": "Problemas y Características", + "fr_FR": "Problèmes et Caractéristiques", + "he_IL": "", + "it_IT": "Problemi e Caratteristiche", + "ja_JP": "問題点と特徴", + "ko_KR": "문제점 및 특징", + "no_NO": "Problemer og Egenskaper", + "pl_PL": "Problemy i Cechy", + "pt_BR": "Problemas e Características", + "ru_RU": "Проблемы и Особенности", + "sv_SE": "Problem och egenskaper", + "th_TH": "", + "tr_TR": "Sorunlar ve Özellikler", + "uk_UA": "Проблеми та Особливості", + "zh_CN": "问题和特性", + "zh_TW": "問題與特性" + } + }, + { + "ID": "CompatibilityListInfo", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "Πληροφορίες", + "en_US": "Info", + "es_ES": "Información", + "fr_FR": "", + "he_IL": "מידע", + "it_IT": "", + "ja_JP": "情報", + "ko_KR": "정보", + "no_NO": "", + "pl_PL": "Informacja", + "pt_BR": "", + "ru_RU": "Инфо", + "sv_SE": "", + "th_TH": "", + "tr_TR": "Bilgi", + "uk_UA": "Інфо", + "zh_CN": "信息", + "zh_TW": "資訊" + } + }, { "ID": "CompatibilityListOnlyShowOwnedGames", "Translations": { @@ -24355,7 +24630,7 @@ "el_GR": "", "en_US": "Only show owned games", "es_ES": "", - "fr_FR": "", + "fr_FR": "Afficher uniquement les jeux possédés", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -24380,7 +24655,7 @@ "el_GR": "", "en_US": "Playable", "es_ES": "", - "fr_FR": "", + "fr_FR": "Jouable", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -24405,7 +24680,7 @@ "el_GR": "", "en_US": "Ingame", "es_ES": "", - "fr_FR": "", + "fr_FR": "En Jeu", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -24455,7 +24730,7 @@ "el_GR": "", "en_US": "Boots", "es_ES": "", - "fr_FR": "", + "fr_FR": "Démarre", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -24480,11 +24755,11 @@ "el_GR": "", "en_US": "Nothing", "es_ES": "", - "fr_FR": "", + "fr_FR": "Rien", "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "불가능", + "ko_KR": "불가", "no_NO": "Ingenting", "pl_PL": "", "pt_BR": "Nada", @@ -24505,11 +24780,11 @@ "el_GR": "", "en_US": "Boots and plays without any crashes or GPU bugs of any kind, and at a speed fast enough to reasonably enjoy on an average PC.", "es_ES": "", - "fr_FR": "", + "fr_FR": "Démarre et fonctionne sans aucun plantage ni bug graphique, à une vitesse suffisante pour être apprécié raisonnablement sur un PC moyen.", "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "어떠한 충돌이나 GPU 버그 없이 부팅 및 플레이가 가능하며, 일반 PC에서 충분히 즐길 수 있을 만큼 빠른 속도입니다.", + "ko_KR": "어떠한 충돌이나 GPU 버그 없이 부팅 및 플레이가 가능하며, 일반 PC에서 충분히 즐길 수 있을 만큼 쾌적한 속도입니다.", "no_NO": "Starter opp og spiller uten krasj eller GPU-feil av noe slag, og med en hastighet som er rask nok til å ha rimelig glede av på en gjennomsnittlig PC.", "pl_PL": "", "pt_BR": "Inicializa e roda sem travamentos ou bugs de GPU de qualquer tipo, e em uma velocidade rápida o suficiente para ser aproveitado em um PC comum.", @@ -24530,11 +24805,11 @@ "el_GR": "", "en_US": "Boots and goes in-game but suffers from one or more of the following: crashes, deadlocks, GPU bugs, distractingly bad audio, or is simply too slow. Game still might able to be played all the way through, but not as the game is intended to play.", "es_ES": "", - "fr_FR": "", + "fr_FR": "Démarre et lance le jeu, mais souffre d’un ou plusieurs des problèmes suivants : plantages, blocages, bugs graphiques, audio très désagréable, ou performances trop lentes. Le jeu peut encore être jouable jusqu’au bout, mais pas dans les conditions prévues.", "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "부팅하고 게임에 들어가지만 충돌, 교착 상태, GPU 버그, 방해가 될 정도로 나쁜 오디오 또는 너무 느린 문제 중 하나 이상으로 인해 문제가 발생합니다. 게임은 여전히 ​​가능할 수 있습니다.", + "ko_KR": "부팅하고 게임에 진입하지만 충돌, 교착, GPU 버그, 오디오에 문제가 있거나 버벅임 중 하나 이상으로 인해 문제가 발생합니다. 게임은 어쨌든 진행할 수 있습니다.", "no_NO": "Starter og går i gang i spillet, men lider av ett eller flere av følgende: krasjer, fastlåser, GPU-feil, distraherende dårlig lyd eller er rett og slett for tregt. Spillet kan fortsatt spilles helt til ende, men ikke slik det er ment å spilles.", "pl_PL": "", "pt_BR": "Inicializa e entra no jogo, mas sofre de um ou mais dos seguintes: travamentos, deadlocks, bugs de GPU, áudio ruim que distrai ou é simplesmente muito lento. O jogo ainda pode ser jogado até o fim, mas não da forma como foi criado para ser jogado.", @@ -24555,7 +24830,7 @@ "el_GR": "", "en_US": "Boots and goes past the title screen but does not make it into main gameplay.", "es_ES": "", - "fr_FR": "", + "fr_FR": "Démarre et dépasse l’écran titre, mais n’atteint pas le gameplay principal.", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -24580,7 +24855,7 @@ "el_GR": "", "en_US": "Boots but does not make it past the title screen.", "es_ES": "", - "fr_FR": "", + "fr_FR": "Démarre mais ne dépasse pas l’écran titre.", "he_IL": "", "it_IT": "", "ja_JP": "", @@ -24605,11 +24880,11 @@ "el_GR": "", "en_US": "Does not boot or shows no signs of activity.", "es_ES": "", - "fr_FR": "", + "fr_FR": "Ne démarre pas et ne montre aucun signe d’activité.", "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "부팅되지 않거나 활동 흔적이 보이지 않습니다.", + "ko_KR": "부팅되지 않거나 동작하지 않습니다.", "no_NO": "Starter ikke opp eller viser ingen tegn til aktivitet.", "pl_PL": "", "pt_BR": "Não inicializa ou não mostra sinais de atividade.", @@ -24630,14 +24905,14 @@ "el_GR": "", "en_US": "Custom Config", "es_ES": "", - "fr_FR": "", + "fr_FR": "Configuration personnalisée", "he_IL": "", "it_IT": "", "ja_JP": "", "ko_KR": "사용자 정의 설정", "no_NO": "Tilpasset konfigurasjon", "pl_PL": "", - "pt_BR": "", + "pt_BR": "Configurações Customizadas", "ru_RU": "Индивидуальные параметры", "sv_SE": "Anpassad konfiguration", "th_TH": "", @@ -24748,4 +25023,4 @@ } } ] -} \ No newline at end of file +} diff --git a/distribution/macos/create_app_bundle.sh b/distribution/macos/create_app_bundle.sh index cbe930d2d..0b4ab8e04 100755 --- a/distribution/macos/create_app_bundle.sh +++ b/distribution/macos/create_app_bundle.sh @@ -33,23 +33,29 @@ echo -n "APPL????" > "$APP_BUNDLE_DIRECTORY/Contents/PkgInfo" echo "Running bundle fix up python script" python3 bundle_fix_up.py "$APP_BUNDLE_DIRECTORY" MacOS/Ryujinx -# Resign all dyplib files as ad-hoc after changing them -find "$APP_BUNDLE_DIRECTORY/Contents/Frameworks" -type f -name "*.dylib" -exec codesign --force --sign - {} \; - # Now sign it echo "Starting signing process" if ! [ -x "$(command -v codesign)" ]; then if ! [ -x "$(command -v rcodesign)" ]; then - echo "Cannot find rcodesign on your system, please install rcodesign." + echo "Cannot find rcodesign on your system, please install rcodesign and ensure it is in your search path." exit 1 fi - # cargo install apple-codesign echo "Using rcodesign for ad-hoc signing" + + echo "Resigning all frameworks dylib files as ad-hoc" + find "$APP_BUNDLE_DIRECTORY/Contents/Frameworks" -type f -name "*.dylib" -exec rcodesign sign {} \; + + echo "Signing app bundle as ad-hoc" rcodesign sign --entitlements-xml-path "$ENTITLEMENTS_FILE_PATH" "$APP_BUNDLE_DIRECTORY" else echo "Using codesign for ad-hoc signing" + + echo "Resigning all frameworks dylib files as ad-hoc" + find "$APP_BUNDLE_DIRECTORY/Contents/Frameworks" -type f -name "*.dylib" -exec codesign --force --sign - {} \; + + echo "Signing app bundle as ad-hoc" codesign --entitlements "$ENTITLEMENTS_FILE_PATH" -f -s - "$APP_BUNDLE_DIRECTORY" fi diff --git a/distribution/macos/create_macos_build_ava.sh b/distribution/macos/create_macos_build_ava.sh index de6fab358..028486f51 100755 --- a/distribution/macos/create_macos_build_ava.sh +++ b/distribution/macos/create_macos_build_ava.sh @@ -20,6 +20,18 @@ SOURCE_REVISION_ID=$6 CONFIGURATION=$7 CANARY=$8 +if [[ "$(uname)" == "Darwin" ]]; then + echo "Clearing xattr on all dot undercsore files" + find "$BASE_DIR" -type f -name "._*" -exec sh -c ' + for f; do + dir=$(dirname "$f") + base=$(basename "$f") + orig="$dir/${base#._}" + [ -f "$orig" ] && xattr -c "$orig" || true + done + ' sh {} + +fi + if [ "$CANARY" == "1" ]; then RELEASE_TAR_FILE_NAME=ryujinx-canary-$VERSION-macos_universal.app.tar elif [ "$VERSION" == "1.1.0" ]; then diff --git a/distribution/macos/create_macos_build_headless.sh b/distribution/macos/create_macos_build_headless.sh index 5de862a2f..6052b202c 100755 --- a/distribution/macos/create_macos_build_headless.sh +++ b/distribution/macos/create_macos_build_headless.sh @@ -20,6 +20,18 @@ SOURCE_REVISION_ID=$6 CONFIGURATION=$7 CANARY=$8 +if [[ "$(uname)" == "Darwin" ]]; then + echo "Clearing xattr on all dot undercsore files" + find "$BASE_DIR" -type f -name "._*" -exec sh -c ' + for f; do + dir=$(dirname "$f") + base=$(basename "$f") + orig="$dir/${base#._}" + [ -f "$orig" ] && xattr -c "$orig" || true + done + ' sh {} + +fi + if [ "$CANARY" == "1" ]; then RELEASE_TAR_FILE_NAME=nogui-ryujinx-canary-$VERSION-macos_universal.tar elif [ "$VERSION" == "1.1.0" ]; then diff --git a/docs/compatibility.csv b/docs/compatibility.csv index c46a0d1e9..6499c8a7a 100644 --- a/docs/compatibility.csv +++ b/docs/compatibility.csv @@ -601,6 +601,7 @@ 010060200A4BE000,"Brawlout",ldn-untested;online,playable,2021-06-04 17:35:35 0100C1B00E1CA000,"Brawlout Demo",demo,playable,2021-02-13 22:46:53 010022C016DC8000,"Breakout: Recharged",slow,ingame,2022-11-06 15:32:57 +010048A021C40000,"Breakout Beyond",,playable,2025-04-26 19:11:35 01000AA013A5E000,"Breathedge",UE4;nvdec,playable,2021-05-06 15:44:28 01003D50100F4000,"Breathing Fear",,playable,2020-07-14 15:12:29 010026800BB06000,"Brick Breaker",nvdec;online,playable,2020-12-15 18:26:23 @@ -1124,6 +1125,7 @@ 0100034012606000,"Family Mysteries: Poisonous Promises",audio;crash,menus,2021-11-26 12:35:06 010017C012726000,"Fantasy Friends",,playable,2022-10-17 19:42:39 0100767008502000,"FANTASY HERO ~unsigned legacy~",,playable,2022-07-26 12:28:52 +0100755017EE0000,"FANTASY LIFE i: The Girl Who Steals Time",gpu;crash;vulkan-backend-bug,ingame,2025-06-08 20:41:00 0100944003820000,"Fantasy Strike",online,playable,2021-02-27 01:59:18 01000E2012F6E000,"Fantasy Tavern Sextet -Vol.1 New World Days-",gpu;crash;Needs Update,ingame,2022-12-05 16:48:00 01005C10136CA000,"Fantasy Tavern Sextet -Vol.2 Adventurer's Days-",gpu;slow;crash,ingame,2021-11-06 02:57:29 @@ -2028,6 +2030,7 @@ 0100628004BCE000,"Nights of Azure 2: Bride of the New Moon",crash;nvdec;regression,menus,2022-11-24 16:00:39 010042300C4F6000,"Nightshade/百花百狼",nvdec,playable,2020-05-10 19:43:31 0100AA0008736000,"Nihilumbra",,playable,2020-05-10 16:00:12 +01009FA01FF6C000,"Nikoderiko: The Magical World",gpu,ingame,2025-04-26 19:13:31 0100D03003F0E000,"Nine Parchments",ldn-untested,playable,2022-08-07 12:32:08 0100E2F014F46000,"NINJA GAIDEN Σ",nvdec,playable,2022-11-13 16:27:02 0100696014F4A000,"NINJA GAIDEN Σ2",nvdec,playable,2024-07-31 21:53:48 @@ -2743,6 +2746,7 @@ 01005D701264A000,"SpyHack",,playable,2021-04-15 10:53:51 010077B00E046000,"Spyro™ Reignited Trilogy",nvdec;UE4,playable,2022-09-11 18:38:33 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 0100FCD0102EC000,"Squidlit",,playable,2020-08-06 12:38:32 0100EBF00E702000,"STAR OCEAN First Departure R",nvdec,playable,2021-07-05 19:29:16 @@ -3013,6 +3017,7 @@ 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 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 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 diff --git a/nuget.config b/nuget.config index 80f5bd7fc..26f795ba1 100644 --- a/nuget.config +++ b/nuget.config @@ -1,7 +1,25 @@  + - - - - + + + + + + + + + + + + + + + + + + + diff --git a/src/ARMeilleure/ARMeilleure.csproj b/src/ARMeilleure/ARMeilleure.csproj index 5b6c5a6da..c3a82d4cd 100644 --- a/src/ARMeilleure/ARMeilleure.csproj +++ b/src/ARMeilleure/ARMeilleure.csproj @@ -3,10 +3,10 @@ true $(DefaultItemExcludes);._* + true - diff --git a/src/ARMeilleure/CodeGen/Arm64/Arm64Optimizer.cs b/src/ARMeilleure/CodeGen/Arm64/Arm64Optimizer.cs index a433cea65..112193f46 100644 --- a/src/ARMeilleure/CodeGen/Arm64/Arm64Optimizer.cs +++ b/src/ARMeilleure/CodeGen/Arm64/Arm64Optimizer.cs @@ -254,7 +254,7 @@ namespace ARMeilleure.CodeGen.Arm64 private static bool IsMemoryLoadOrStore(Instruction inst) { - return inst == Instruction.Load || inst == Instruction.Store; + return inst is Instruction.Load or Instruction.Store; } private static bool ConstTooLong(Operand constOp, OperandType accessType) diff --git a/src/ARMeilleure/CodeGen/Arm64/Assembler.cs b/src/ARMeilleure/CodeGen/Arm64/Assembler.cs index 47902ddc8..0d493426b 100644 --- a/src/ARMeilleure/CodeGen/Arm64/Assembler.cs +++ b/src/ARMeilleure/CodeGen/Arm64/Assembler.cs @@ -774,6 +774,7 @@ namespace ARMeilleure.CodeGen.Arm64 instI |= 1 << 22; // sh flag imm >>= 12; } + WriteInstructionAuto(instI | (EncodeUImm12(imm, 0) << 10), rd, rn); } else diff --git a/src/ARMeilleure/CodeGen/Arm64/CodeGenCommon.cs b/src/ARMeilleure/CodeGen/Arm64/CodeGenCommon.cs index 1f0148d5e..af5f1a8c7 100644 --- a/src/ARMeilleure/CodeGen/Arm64/CodeGenCommon.cs +++ b/src/ARMeilleure/CodeGen/Arm64/CodeGenCommon.cs @@ -52,7 +52,7 @@ namespace ARMeilleure.CodeGen.Arm64 // Any value AND all ones will be equal itself, so it's effectively a no-op. // Any value OR all ones will be equal all ones, so one can just use MOV. // Any value XOR all ones will be equal its inverse, so one can just use MVN. - if (value == 0 || value == ulong.MaxValue) + if (value is 0 or ulong.MaxValue) { immN = 0; immS = 0; diff --git a/src/ARMeilleure/CodeGen/Arm64/CodeGenContext.cs b/src/ARMeilleure/CodeGen/Arm64/CodeGenContext.cs index 46cd863cf..e4d9f46fa 100644 --- a/src/ARMeilleure/CodeGen/Arm64/CodeGenContext.cs +++ b/src/ARMeilleure/CodeGen/Arm64/CodeGenContext.cs @@ -1,6 +1,7 @@ using ARMeilleure.CodeGen.Linking; using ARMeilleure.CodeGen.RegisterAllocators; using ARMeilleure.IntermediateRepresentation; +using Microsoft.IO; using Ryujinx.Common.Memory; using System; using System.Collections.Generic; @@ -14,7 +15,7 @@ namespace ARMeilleure.CodeGen.Arm64 private const int CbnzInstLength = 4; private const int LdrLitInstLength = 4; - private readonly Stream _stream; + private readonly RecyclableMemoryStream _stream; public int StreamOffset => (int)_stream.Length; diff --git a/src/ARMeilleure/CodeGen/Arm64/CodeGenerator.cs b/src/ARMeilleure/CodeGen/Arm64/CodeGenerator.cs index 8f88f2e27..fbf4c1eb4 100644 --- a/src/ARMeilleure/CodeGen/Arm64/CodeGenerator.cs +++ b/src/ARMeilleure/CodeGen/Arm64/CodeGenerator.cs @@ -189,8 +189,8 @@ namespace ARMeilleure.CodeGen.Arm64 // The only blocks which can have 0 successors are exit blocks. Operation last = block.Operations.Last; - Debug.Assert(last.Instruction == Instruction.Tailcall || - last.Instruction == Instruction.Return); + Debug.Assert(last.Instruction is Instruction.Tailcall or + Instruction.Return); } else { @@ -464,7 +464,7 @@ namespace ARMeilleure.CodeGen.Arm64 Operand dest = operation.Destination; Operand source = operation.GetSource(0); - Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64); + Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64); Debug.Assert(dest.Type != source.Type); Debug.Assert(source.Type != OperandType.V128); @@ -483,7 +483,7 @@ namespace ARMeilleure.CodeGen.Arm64 Operand dest = operation.Destination; Operand source = operation.GetSource(0); - Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64); + Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64); Debug.Assert(dest.Type != source.Type); Debug.Assert(source.Type.IsInteger()); @@ -1463,7 +1463,7 @@ namespace ARMeilleure.CodeGen.Arm64 private static bool IsLoadOrStore(Operation operation) { - return operation.Instruction == Instruction.Load || operation.Instruction == Instruction.Store; + return operation.Instruction is Instruction.Load or Instruction.Store; } private static OperandType GetMemOpValueType(Operation operation) @@ -1499,6 +1499,7 @@ namespace ARMeilleure.CodeGen.Arm64 return false; } } + if (memOp.Index != default) { return false; @@ -1553,7 +1554,7 @@ namespace ARMeilleure.CodeGen.Arm64 private static void EnsureSameReg(Operand op1, Operand op2) { - Debug.Assert(op1.Kind == OperandKind.Register || op1.Kind == OperandKind.Memory); + Debug.Assert(op1.Kind is OperandKind.Register or OperandKind.Memory); Debug.Assert(op1.Kind == op2.Kind); Debug.Assert(op1.Value == op2.Value); } diff --git a/src/ARMeilleure/CodeGen/Arm64/CodeGeneratorIntrinsic.cs b/src/ARMeilleure/CodeGen/Arm64/CodeGeneratorIntrinsic.cs index b87370557..390dc5b2e 100644 --- a/src/ARMeilleure/CodeGen/Arm64/CodeGeneratorIntrinsic.cs +++ b/src/ARMeilleure/CodeGen/Arm64/CodeGeneratorIntrinsic.cs @@ -509,7 +509,6 @@ namespace ARMeilleure.CodeGen.Arm64 context.Assembler.WriteInstruction(instruction, rd, rn); } - } private static void GenerateScalarTernary( diff --git a/src/ARMeilleure/CodeGen/Arm64/HardwareCapabilities.cs b/src/ARMeilleure/CodeGen/Arm64/HardwareCapabilities.cs index fbaf16d04..fa9e7fe2e 100644 --- a/src/ARMeilleure/CodeGen/Arm64/HardwareCapabilities.cs +++ b/src/ARMeilleure/CodeGen/Arm64/HardwareCapabilities.cs @@ -137,6 +137,7 @@ namespace ARMeilleure.CodeGen.Arm64 { return val != 0; } + return false; } diff --git a/src/ARMeilleure/CodeGen/Arm64/PreAllocator.cs b/src/ARMeilleure/CodeGen/Arm64/PreAllocator.cs index a82c6939f..76a231d6c 100644 --- a/src/ARMeilleure/CodeGen/Arm64/PreAllocator.cs +++ b/src/ARMeilleure/CodeGen/Arm64/PreAllocator.cs @@ -736,19 +736,19 @@ namespace ARMeilleure.CodeGen.Arm64 { IntrinsicInfo info = IntrinsicTable.GetInfo(intrinsic & ~(Intrinsic.Arm64VTypeMask | Intrinsic.Arm64VSizeMask)); - return info.Type == IntrinsicType.ScalarBinaryRd || - info.Type == IntrinsicType.ScalarTernaryFPRdByElem || - info.Type == IntrinsicType.ScalarTernaryShlRd || - info.Type == IntrinsicType.ScalarTernaryShrRd || - info.Type == IntrinsicType.Vector128BinaryRd || - info.Type == IntrinsicType.VectorBinaryRd || - info.Type == IntrinsicType.VectorInsertByElem || - info.Type == IntrinsicType.VectorTernaryRd || - info.Type == IntrinsicType.VectorTernaryRdBitwise || - info.Type == IntrinsicType.VectorTernaryFPRdByElem || - info.Type == IntrinsicType.VectorTernaryRdByElem || - info.Type == IntrinsicType.VectorTernaryShlRd || - info.Type == IntrinsicType.VectorTernaryShrRd; + return info.Type is IntrinsicType.ScalarBinaryRd or + IntrinsicType.ScalarTernaryFPRdByElem or + IntrinsicType.ScalarTernaryShlRd or + IntrinsicType.ScalarTernaryShrRd or + IntrinsicType.Vector128BinaryRd or + IntrinsicType.VectorBinaryRd or + IntrinsicType.VectorInsertByElem or + IntrinsicType.VectorTernaryRd or + IntrinsicType.VectorTernaryRdBitwise or + IntrinsicType.VectorTernaryFPRdByElem or + IntrinsicType.VectorTernaryRdByElem or + IntrinsicType.VectorTernaryShlRd or + IntrinsicType.VectorTernaryShrRd; } private static bool HasConstSrc1(Operation node, ulong value) @@ -849,7 +849,7 @@ namespace ARMeilleure.CodeGen.Arm64 Comparison compType = (Comparison)comp.AsInt32(); - return compType == Comparison.Equal || compType == Comparison.NotEqual; + return compType is Comparison.Equal or Comparison.NotEqual; } } @@ -871,9 +871,9 @@ namespace ARMeilleure.CodeGen.Arm64 IntrinsicInfo info = IntrinsicTable.GetInfo(intrinsic & ~(Intrinsic.Arm64VTypeMask | Intrinsic.Arm64VSizeMask)); // Those have integer inputs that don't support consts. - return info.Type != IntrinsicType.ScalarFPConvGpr && - info.Type != IntrinsicType.ScalarFPConvFixedGpr && - info.Type != IntrinsicType.SetRegister; + return info.Type is not IntrinsicType.ScalarFPConvGpr and + not IntrinsicType.ScalarFPConvFixedGpr and + not IntrinsicType.SetRegister; } return false; diff --git a/src/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs b/src/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs index be3dff58c..c7aa1ee5f 100644 --- a/src/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs +++ b/src/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs @@ -37,6 +37,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => x + y); } + break; case Instruction.BitwiseAnd: @@ -48,6 +49,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => x & y); } + break; case Instruction.BitwiseExclusiveOr: @@ -59,6 +61,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => x ^ y); } + break; case Instruction.BitwiseNot: @@ -70,6 +73,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateUnaryI64(operation, (x) => ~x); } + break; case Instruction.BitwiseOr: @@ -81,6 +85,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => x | y); } + break; case Instruction.ConvertI64ToI32: @@ -88,6 +93,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateUnaryI32(operation, (x) => x); } + break; case Instruction.Compare: @@ -129,6 +135,7 @@ namespace ARMeilleure.CodeGen.Optimizations break; } } + break; case Instruction.Copy: @@ -140,6 +147,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateUnaryI64(operation, (x) => x); } + break; case Instruction.Divide: @@ -151,6 +159,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => y != 0 ? x / y : 0); } + break; case Instruction.DivideUI: @@ -162,6 +171,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => y != 0 ? (long)((ulong)x / (ulong)y) : 0); } + break; case Instruction.Multiply: @@ -173,6 +183,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => x * y); } + break; case Instruction.Negate: @@ -184,6 +195,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateUnaryI64(operation, (x) => -x); } + break; case Instruction.ShiftLeft: @@ -195,6 +207,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => x << (int)y); } + break; case Instruction.ShiftRightSI: @@ -206,6 +219,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => x >> (int)y); } + break; case Instruction.ShiftRightUI: @@ -217,6 +231,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => (long)((ulong)x >> (int)y)); } + break; case Instruction.SignExtend16: @@ -228,6 +243,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateUnaryI64(operation, (x) => (short)x); } + break; case Instruction.SignExtend32: @@ -239,6 +255,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateUnaryI64(operation, (x) => (int)x); } + break; case Instruction.SignExtend8: @@ -250,6 +267,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateUnaryI64(operation, (x) => (sbyte)x); } + break; case Instruction.ZeroExtend16: @@ -261,6 +279,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateUnaryI64(operation, (x) => (ushort)x); } + break; case Instruction.ZeroExtend32: @@ -272,6 +291,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateUnaryI64(operation, (x) => (uint)x); } + break; case Instruction.ZeroExtend8: @@ -283,6 +303,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateUnaryI64(operation, (x) => (byte)x); } + break; case Instruction.Subtract: @@ -294,6 +315,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => x - y); } + break; } } diff --git a/src/ARMeilleure/CodeGen/Optimizations/Optimizer.cs b/src/ARMeilleure/CodeGen/Optimizations/Optimizer.cs index 1afc3a782..cbc6ab784 100644 --- a/src/ARMeilleure/CodeGen/Optimizations/Optimizer.cs +++ b/src/ARMeilleure/CodeGen/Optimizations/Optimizer.cs @@ -227,11 +227,11 @@ namespace ARMeilleure.CodeGen.Optimizations private static bool HasSideEffects(Operation node) { - return node.Instruction == Instruction.Call - || node.Instruction == Instruction.Tailcall - || node.Instruction == Instruction.CompareAndSwap - || node.Instruction == Instruction.CompareAndSwap16 - || node.Instruction == Instruction.CompareAndSwap8; + return node.Instruction is Instruction.Call + or Instruction.Tailcall + or Instruction.CompareAndSwap + or Instruction.CompareAndSwap16 + or Instruction.CompareAndSwap8; } private static bool IsPropagableCompare(Operation operation) diff --git a/src/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs b/src/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs index 76c636b55..92fedf7bf 100644 --- a/src/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs +++ b/src/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs @@ -847,7 +847,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators // If this is a copy (or copy-like operation), set the copy source interval as well. // This is used for register preferencing later on, which allows the copy to be eliminated // in some cases. - if (node.Instruction == Instruction.Copy || node.Instruction == Instruction.ZeroExtend32) + if (node.Instruction is Instruction.Copy or Instruction.ZeroExtend32) { Operand source = node.GetSource(0); @@ -1120,8 +1120,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators private static bool IsLocalOrRegister(OperandKind kind) { - return kind == OperandKind.LocalVariable || - kind == OperandKind.Register; + return kind is OperandKind.LocalVariable or + OperandKind.Register; } } } diff --git a/src/ARMeilleure/CodeGen/X86/Assembler.cs b/src/ARMeilleure/CodeGen/X86/Assembler.cs index 46dadbfce..c27ee43cb 100644 --- a/src/ARMeilleure/CodeGen/X86/Assembler.cs +++ b/src/ARMeilleure/CodeGen/X86/Assembler.cs @@ -1478,7 +1478,7 @@ namespace ARMeilleure.CodeGen.X86 private static bool Is64Bits(OperandType type) { - return type == OperandType.I64 || type == OperandType.FP64; + return type is OperandType.I64 or OperandType.FP64; } private static bool IsImm8(ulong immediate, OperandType type) diff --git a/src/ARMeilleure/CodeGen/X86/AssemblerTable.cs b/src/ARMeilleure/CodeGen/X86/AssemblerTable.cs index 8910e8891..4b226803b 100644 --- a/src/ARMeilleure/CodeGen/X86/AssemblerTable.cs +++ b/src/ARMeilleure/CodeGen/X86/AssemblerTable.cs @@ -13,7 +13,6 @@ namespace ARMeilleure.CodeGen.X86 private const int BadOp = 0; [Flags] - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] private enum InstructionFlags { None = 0, diff --git a/src/ARMeilleure/CodeGen/X86/CodeGenContext.cs b/src/ARMeilleure/CodeGen/X86/CodeGenContext.cs index d4d4c2058..afae3211f 100644 --- a/src/ARMeilleure/CodeGen/X86/CodeGenContext.cs +++ b/src/ARMeilleure/CodeGen/X86/CodeGenContext.cs @@ -1,5 +1,6 @@ using ARMeilleure.CodeGen.RegisterAllocators; using ARMeilleure.IntermediateRepresentation; +using Microsoft.IO; using Ryujinx.Common.Memory; using System.IO; using System.Numerics; @@ -8,7 +9,7 @@ namespace ARMeilleure.CodeGen.X86 { class CodeGenContext { - private readonly Stream _stream; + private readonly RecyclableMemoryStream _stream; private readonly Operand[] _blockLabels; public int StreamOffset => (int)_stream.Length; diff --git a/src/ARMeilleure/CodeGen/X86/CodeGenerator.cs b/src/ARMeilleure/CodeGen/X86/CodeGenerator.cs index 1122c6940..86acea4a8 100644 --- a/src/ARMeilleure/CodeGen/X86/CodeGenerator.cs +++ b/src/ARMeilleure/CodeGen/X86/CodeGenerator.cs @@ -175,8 +175,8 @@ namespace ARMeilleure.CodeGen.X86 // The only blocks which can have 0 successors are exit blocks. Operation last = block.Operations.Last; - Debug.Assert(last.Instruction == Instruction.Tailcall || - last.Instruction == Instruction.Return); + Debug.Assert(last.Instruction is Instruction.Tailcall or + Instruction.Return); } else { @@ -478,7 +478,7 @@ namespace ARMeilleure.CodeGen.X86 Debug.Assert(HardwareCapabilities.SupportsVexEncoding); Debug.Assert(dest.Kind == OperandKind.Register && src1.Kind == OperandKind.Register && src2.Kind == OperandKind.Register); - Debug.Assert(src3.Kind == OperandKind.Register || src3.Kind == OperandKind.Memory); + Debug.Assert(src3.Kind is OperandKind.Register or OperandKind.Memory); EnsureSameType(dest, src1, src2, src3); Debug.Assert(dest.Type == OperandType.V128); @@ -788,7 +788,7 @@ namespace ARMeilleure.CodeGen.X86 Operand dest = operation.Destination; Operand source = operation.GetSource(0); - Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64); + Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64); if (dest.Type == OperandType.FP32) { @@ -1723,7 +1723,7 @@ namespace ARMeilleure.CodeGen.X86 return; } - Debug.Assert(op1.Kind == OperandKind.Register || op1.Kind == OperandKind.Memory); + Debug.Assert(op1.Kind is OperandKind.Register or OperandKind.Memory); Debug.Assert(op1.Kind == op2.Kind); Debug.Assert(op1.Value == op2.Value); } diff --git a/src/ARMeilleure/CodeGen/X86/PreAllocator.cs b/src/ARMeilleure/CodeGen/X86/PreAllocator.cs index 915f283c7..6b93efdfb 100644 --- a/src/ARMeilleure/CodeGen/X86/PreAllocator.cs +++ b/src/ARMeilleure/CodeGen/X86/PreAllocator.cs @@ -66,6 +66,7 @@ namespace ARMeilleure.CodeGen.X86 { PreAllocatorSystemV.InsertCallCopies(block.Operations, node); } + break; case Instruction.ConvertToFPUI: @@ -81,6 +82,7 @@ namespace ARMeilleure.CodeGen.X86 { nextNode = PreAllocatorSystemV.InsertLoadArgumentCopy(cctx, ref buffer, block.Operations, preservedArgs, node); } + break; case Instruction.Negate: @@ -88,6 +90,7 @@ namespace ARMeilleure.CodeGen.X86 { GenerateNegate(block.Operations, node); } + break; case Instruction.Return: @@ -99,6 +102,7 @@ namespace ARMeilleure.CodeGen.X86 { PreAllocatorSystemV.InsertReturnCopy(block.Operations, node); } + break; case Instruction.Tailcall: @@ -110,6 +114,7 @@ namespace ARMeilleure.CodeGen.X86 { PreAllocatorSystemV.InsertTailcallCopies(block.Operations, node); } + break; case Instruction.VectorInsert8: @@ -117,6 +122,7 @@ namespace ARMeilleure.CodeGen.X86 { GenerateVectorInsert8(block.Operations, node); } + break; case Instruction.Extended: @@ -132,6 +138,7 @@ namespace ARMeilleure.CodeGen.X86 node.SetSources([Const(stackOffset)]); } + break; } } @@ -312,9 +319,9 @@ namespace ARMeilleure.CodeGen.X86 case Instruction.Extended: { - bool isBlend = node.Intrinsic == Intrinsic.X86Blendvpd || - node.Intrinsic == Intrinsic.X86Blendvps || - node.Intrinsic == Intrinsic.X86Pblendvb; + bool isBlend = node.Intrinsic is Intrinsic.X86Blendvpd or + Intrinsic.X86Blendvps or + Intrinsic.X86Pblendvb; // BLENDVPD, BLENDVPS, PBLENDVB last operand is always implied to be XMM0 when VEX is not supported. // SHA256RNDS2 always has an implied XMM0 as a last operand. @@ -513,8 +520,8 @@ namespace ARMeilleure.CodeGen.X86 Operand dest = node.Destination; Operand source = node.GetSource(0); - Debug.Assert(dest.Type == OperandType.FP32 || - dest.Type == OperandType.FP64, $"Invalid destination type \"{dest.Type}\"."); + Debug.Assert(dest.Type is OperandType.FP32 or + OperandType.FP64, $"Invalid destination type \"{dest.Type}\"."); Operation currentNode = node; @@ -761,7 +768,7 @@ namespace ARMeilleure.CodeGen.X86 Comparison compType = (Comparison)comp.AsInt32(); - return compType == Comparison.Equal || compType == Comparison.NotEqual; + return compType is Comparison.Equal or Comparison.NotEqual; } } diff --git a/src/ARMeilleure/CodeGen/X86/X86Optimizer.cs b/src/ARMeilleure/CodeGen/X86/X86Optimizer.cs index d72442c5a..49dc1c8a4 100644 --- a/src/ARMeilleure/CodeGen/X86/X86Optimizer.cs +++ b/src/ARMeilleure/CodeGen/X86/X86Optimizer.cs @@ -248,12 +248,12 @@ namespace ARMeilleure.CodeGen.X86 private static bool IsMemoryLoadOrStore(Instruction inst) { - return inst == Instruction.Load || - inst == Instruction.Load16 || - inst == Instruction.Load8 || - inst == Instruction.Store || - inst == Instruction.Store16 || - inst == Instruction.Store8; + return inst is Instruction.Load or + Instruction.Load16 or + Instruction.Load8 or + Instruction.Store or + Instruction.Store16 or + Instruction.Store8; } } } diff --git a/src/ARMeilleure/CodeGen/X86/X86Register.cs b/src/ARMeilleure/CodeGen/X86/X86Register.cs index 0a6563663..bcce4f974 100644 --- a/src/ARMeilleure/CodeGen/X86/X86Register.cs +++ b/src/ARMeilleure/CodeGen/X86/X86Register.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace ARMeilleure.CodeGen.X86 { - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum X86Register { Invalid = -1, diff --git a/src/ARMeilleure/Decoders/Decoder.cs b/src/ARMeilleure/Decoders/Decoder.cs index 3946e2f2e..29c939f5d 100644 --- a/src/ARMeilleure/Decoders/Decoder.cs +++ b/src/ARMeilleure/Decoders/Decoder.cs @@ -254,8 +254,8 @@ namespace ARMeilleure.Decoders } // Compare and branch instructions are always conditional. - if (opCode.Instruction.Name == InstName.Cbz || - opCode.Instruction.Name == InstName.Cbnz) + if (opCode.Instruction.Name is InstName.Cbz or + InstName.Cbnz) { return false; } @@ -274,9 +274,10 @@ namespace ARMeilleure.Decoders { if (opCode is OpCodeT32) { - return opCode.Instruction.Name != InstName.Tst && opCode.Instruction.Name != InstName.Teq && - opCode.Instruction.Name != InstName.Cmp && opCode.Instruction.Name != InstName.Cmn; + return opCode.Instruction.Name is not InstName.Tst and not InstName.Teq and + not InstName.Cmp and not InstName.Cmn; } + return true; } @@ -284,7 +285,7 @@ namespace ARMeilleure.Decoders // register (Rt == 15 or (mask & (1 << 15)) != 0), and cases where there is // a write back to PC (wback == true && Rn == 15), however the later may // be "undefined" depending on the CPU, so compilers should not produce that. - if (opCode is IOpCode32Mem || opCode is IOpCode32MemMult) + if (opCode is IOpCode32Mem or IOpCode32MemMult) { int rt, rn; @@ -326,15 +327,15 @@ namespace ARMeilleure.Decoders } // Explicit branch instructions. - return opCode is IOpCode32BImm || - opCode is IOpCode32BReg; + return opCode is IOpCode32BImm or + IOpCode32BReg; } private static bool IsCall(OpCode opCode) { - return opCode.Instruction.Name == InstName.Bl || - opCode.Instruction.Name == InstName.Blr || - opCode.Instruction.Name == InstName.Blx; + return opCode.Instruction.Name is InstName.Bl or + InstName.Blr or + InstName.Blx; } private static bool IsException(OpCode opCode) @@ -344,9 +345,9 @@ namespace ARMeilleure.Decoders private static bool IsTrap(OpCode opCode) { - return opCode.Instruction.Name == InstName.Brk || - opCode.Instruction.Name == InstName.Trap || - opCode.Instruction.Name == InstName.Und; + return opCode.Instruction.Name is InstName.Brk or + InstName.Trap or + InstName.Und; } public static OpCode DecodeOpCode(IMemoryManager memory, ulong address, ExecutionMode mode) diff --git a/src/ARMeilleure/Decoders/DecoderHelper.cs b/src/ARMeilleure/Decoders/DecoderHelper.cs index c39a8a88b..b0026ac91 100644 --- a/src/ARMeilleure/Decoders/DecoderHelper.cs +++ b/src/ARMeilleure/Decoders/DecoderHelper.cs @@ -162,6 +162,7 @@ namespace ARMeilleure.Decoders } } } + return false; } } diff --git a/src/ARMeilleure/Decoders/OpCode32SimdDupGP.cs b/src/ARMeilleure/Decoders/OpCode32SimdDupGP.cs index 57adea5e6..9f2d6b60b 100644 --- a/src/ARMeilleure/Decoders/OpCode32SimdDupGP.cs +++ b/src/ARMeilleure/Decoders/OpCode32SimdDupGP.cs @@ -20,6 +20,7 @@ namespace ARMeilleure.Decoders Instruction = InstDescriptor.Undefined; return; } + Q = ((opCode >> 21) & 0x1) != 0; RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64; diff --git a/src/ARMeilleure/Decoders/OpCode32SimdMemPair.cs b/src/ARMeilleure/Decoders/OpCode32SimdMemPair.cs index b35ac039b..0c4b912e7 100644 --- a/src/ARMeilleure/Decoders/OpCode32SimdMemPair.cs +++ b/src/ARMeilleure/Decoders/OpCode32SimdMemPair.cs @@ -40,7 +40,7 @@ namespace ARMeilleure.Decoders Rn = (opCode >> 16) & 0xf; WBack = Rm != RegisterAlias.Aarch32Pc; - RegisterIndex = Rm != RegisterAlias.Aarch32Pc && Rm != RegisterAlias.Aarch32Sp; + RegisterIndex = Rm is not RegisterAlias.Aarch32Pc and not RegisterAlias.Aarch32Sp; Regs = _regsMap[(opCode >> 8) & 0xf]; diff --git a/src/ARMeilleure/Decoders/OpCode32SimdMemSingle.cs b/src/ARMeilleure/Decoders/OpCode32SimdMemSingle.cs index 5df45000f..203d78ffe 100644 --- a/src/ARMeilleure/Decoders/OpCode32SimdMemSingle.cs +++ b/src/ARMeilleure/Decoders/OpCode32SimdMemSingle.cs @@ -45,7 +45,7 @@ namespace ARMeilleure.Decoders Rn = (opCode >> 16) & 0xf; WBack = Rm != RegisterAlias.Aarch32Pc; - RegisterIndex = Rm != RegisterAlias.Aarch32Pc && Rm != RegisterAlias.Aarch32Sp; + RegisterIndex = Rm is not RegisterAlias.Aarch32Pc and not RegisterAlias.Aarch32Sp; } } } diff --git a/src/ARMeilleure/Decoders/OpCodeMemImm.cs b/src/ARMeilleure/Decoders/OpCodeMemImm.cs index 4d5eeb1ed..8c55116fe 100644 --- a/src/ARMeilleure/Decoders/OpCodeMemImm.cs +++ b/src/ARMeilleure/Decoders/OpCodeMemImm.cs @@ -28,8 +28,8 @@ namespace ARMeilleure.Decoders MemOp type = WBack ? (MemOp)((opCode >> 10) & 3) : MemOp.Unsigned; PostIdx = type == MemOp.PostIndexed; - Unscaled = type == MemOp.Unscaled || - type == MemOp.Unprivileged; + Unscaled = type is MemOp.Unscaled or + MemOp.Unprivileged; // Unscaled and Unprivileged doesn't write back, // but they do use the 9-bits Signed Immediate. diff --git a/src/ARMeilleure/Decoders/OpCodeTable.cs b/src/ARMeilleure/Decoders/OpCodeTable.cs index d5e630f9b..d0cf9aec1 100644 --- a/src/ARMeilleure/Decoders/OpCodeTable.cs +++ b/src/ARMeilleure/Decoders/OpCodeTable.cs @@ -1381,6 +1381,7 @@ namespace ARMeilleure.Decoders { thumbEncoding = $"1110{thumbEncoding.AsSpan(4)}"; } + SetT32(thumbEncoding, name, emitter, makeOpT32); } @@ -1409,6 +1410,7 @@ namespace ARMeilleure.Decoders { throw new ArgumentException("Invalid ASIMD instruction encoding"); } + SetT32(thumbEncoding, name, emitter, makeOpT32); } diff --git a/src/ARMeilleure/Diagnostics/IRDumper.cs b/src/ARMeilleure/Diagnostics/IRDumper.cs index dcde1e360..c0397021c 100644 --- a/src/ARMeilleure/Diagnostics/IRDumper.cs +++ b/src/ARMeilleure/Diagnostics/IRDumper.cs @@ -9,7 +9,7 @@ namespace ARMeilleure.Diagnostics { class IRDumper { - private const string Indentation = " "; + private const char Indentation = ' '; private int _indentLevel; @@ -30,14 +30,11 @@ namespace ARMeilleure.Diagnostics private void Indent() { - _builder.EnsureCapacity(_builder.Capacity + _indentLevel * Indentation.Length); + if (_indentLevel == 0) + return; - for (int index = 0; index < _indentLevel; index++) - { -#pragma warning disable CA1834 // Use StringBuilder.Append(char) for single character strings - _builder.Append(Indentation); -#pragma warning restore CA1834 - } + _builder.EnsureCapacity(_builder.Capacity + _indentLevel); + _builder.Append(Indentation, _indentLevel); } private void IncreaseIndentation() @@ -235,8 +232,8 @@ namespace ARMeilleure.Diagnostics { _builder.Append('.').Append(operation.Intrinsic); } - else if (operation.Instruction == Instruction.BranchIf || - operation.Instruction == Instruction.Compare) + else if (operation.Instruction is Instruction.BranchIf or + Instruction.Compare) { comparison = true; } @@ -262,6 +259,7 @@ namespace ARMeilleure.Diagnostics DumpOperand(source); } } + break; } diff --git a/src/ARMeilleure/Instructions/InstEmitAlu32.cs b/src/ARMeilleure/Instructions/InstEmitAlu32.cs index 2e659fd5f..d7514040c 100644 --- a/src/ARMeilleure/Instructions/InstEmitAlu32.cs +++ b/src/ARMeilleure/Instructions/InstEmitAlu32.cs @@ -899,6 +899,7 @@ namespace ARMeilleure.Instructions { n = context.ShiftLeft(n, Const(shift)); } + break; case ShiftType.Asr: if (shift == 32) @@ -909,6 +910,7 @@ namespace ARMeilleure.Instructions { n = context.ShiftRightSI(n, Const(shift)); } + break; } diff --git a/src/ARMeilleure/Instructions/InstEmitAluHelper.cs b/src/ARMeilleure/Instructions/InstEmitAluHelper.cs index 4d4a31f7b..fe1c66d3c 100644 --- a/src/ARMeilleure/Instructions/InstEmitAluHelper.cs +++ b/src/ARMeilleure/Instructions/InstEmitAluHelper.cs @@ -266,7 +266,7 @@ namespace ARMeilleure.Instructions } } - private static Exception InvalidOpCodeType(OpCode opCode) + private static InvalidOperationException InvalidOpCodeType(OpCode opCode) { return new InvalidOperationException($"Invalid OpCode type \"{opCode?.GetType().Name ?? "null"}\"."); } @@ -318,6 +318,7 @@ namespace ARMeilleure.Instructions { m = GetRrxC(context, m, setCarry); } + break; } } diff --git a/src/ARMeilleure/Instructions/InstEmitHashHelper.cs b/src/ARMeilleure/Instructions/InstEmitHashHelper.cs index 9b1ad8721..19a607dfc 100644 --- a/src/ARMeilleure/Instructions/InstEmitHashHelper.cs +++ b/src/ARMeilleure/Instructions/InstEmitHashHelper.cs @@ -17,7 +17,7 @@ namespace ARMeilleure.Instructions public static Operand EmitCrc32(ArmEmitterContext context, Operand crc, Operand value, int size, bool castagnoli) { Debug.Assert(crc.Type.IsInteger() && value.Type.IsInteger()); - Debug.Assert(size >= 0 && size < 4); + Debug.Assert(size is >= 0 and < 4); Debug.Assert((size < 3) || (value.Type == OperandType.I64)); if (castagnoli && Optimizations.UseSse42) diff --git a/src/ARMeilleure/Instructions/InstEmitHelper.cs b/src/ARMeilleure/Instructions/InstEmitHelper.cs index 7a515f94f..a633e39ee 100644 --- a/src/ARMeilleure/Instructions/InstEmitHelper.cs +++ b/src/ARMeilleure/Instructions/InstEmitHelper.cs @@ -90,6 +90,7 @@ namespace ARMeilleure.Instructions { value = context.ConvertI64ToI32(value); } + Operand reg = Register(GetRegisterAlias(context.Mode, regIndex), RegisterType.Integer, OperandType.I32); context.Copy(reg, value); diff --git a/src/ARMeilleure/Instructions/InstEmitMemoryEx.cs b/src/ARMeilleure/Instructions/InstEmitMemoryEx.cs index 8c95b33c5..e4283e5a3 100644 --- a/src/ARMeilleure/Instructions/InstEmitMemoryEx.cs +++ b/src/ARMeilleure/Instructions/InstEmitMemoryEx.cs @@ -140,7 +140,7 @@ namespace ARMeilleure.Instructions if (pair) { - Debug.Assert(op.Size == 2 || op.Size == 3, "Invalid size for pairwise store."); + Debug.Assert(op.Size is 2 or 3, "Invalid size for pairwise store."); Operand t2 = GetIntOrZR(context, op.Rt2); diff --git a/src/ARMeilleure/Instructions/InstEmitMemoryExHelper.cs b/src/ARMeilleure/Instructions/InstEmitMemoryExHelper.cs index 7fca5b853..fd2562b14 100644 --- a/src/ARMeilleure/Instructions/InstEmitMemoryExHelper.cs +++ b/src/ARMeilleure/Instructions/InstEmitMemoryExHelper.cs @@ -42,6 +42,7 @@ namespace ARMeilleure.Instructions { context.Store(exValuePtr, Const(0UL)); } + if (size < 4) { context.Store(context.Add(exValuePtr, Const(exValuePtr.Type, 8L)), Const(0UL)); diff --git a/src/ARMeilleure/Instructions/InstEmitMemoryHelper.cs b/src/ARMeilleure/Instructions/InstEmitMemoryHelper.cs index ace6fe1ce..bb7e997b2 100644 --- a/src/ARMeilleure/Instructions/InstEmitMemoryHelper.cs +++ b/src/ARMeilleure/Instructions/InstEmitMemoryHelper.cs @@ -59,7 +59,7 @@ namespace ARMeilleure.Instructions { Operand value = GetInt(context, rt); - if (ext == Extension.Sx32 || ext == Extension.Sx64) + if (ext is Extension.Sx32 or Extension.Sx64) { OperandType destType = ext == Extension.Sx64 ? OperandType.I64 : OperandType.I32; @@ -123,9 +123,9 @@ namespace ARMeilleure.Instructions private static bool IsSimd(ArmEmitterContext context) { - return context.CurrOp is IOpCodeSimd && - !(context.CurrOp is OpCodeSimdMemMs || - context.CurrOp is OpCodeSimdMemSs); + return context.CurrOp is IOpCodeSimd and + not (OpCodeSimdMemMs or + OpCodeSimdMemSs); } public static Operand EmitReadInt(ArmEmitterContext context, Operand address, int size) @@ -717,7 +717,7 @@ namespace ARMeilleure.Instructions }; } - private static Exception InvalidOpCodeType(OpCode opCode) + private static InvalidOperationException InvalidOpCodeType(OpCode opCode) { return new InvalidOperationException($"Invalid OpCode type \"{opCode?.GetType().Name ?? "null"}\"."); } @@ -768,6 +768,7 @@ namespace ARMeilleure.Instructions { m = InstEmitAluHelper.GetRrxC(context, m, setCarry); } + break; } } diff --git a/src/ARMeilleure/Instructions/InstEmitMul.cs b/src/ARMeilleure/Instructions/InstEmitMul.cs index 89dc09938..cb48deb03 100644 --- a/src/ARMeilleure/Instructions/InstEmitMul.cs +++ b/src/ARMeilleure/Instructions/InstEmitMul.cs @@ -33,7 +33,6 @@ namespace ARMeilleure.Instructions public static void Umsubl(ArmEmitterContext context) => EmitMull(context, MullFlags.Subtract); [Flags] - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] private enum MullFlags { Subtract = 0, diff --git a/src/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs b/src/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs index 694633f97..cee7a4ed8 100644 --- a/src/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs +++ b/src/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs @@ -5266,7 +5266,7 @@ namespace ARMeilleure.Instructions private static Operand EmitSse2Sll_128(ArmEmitterContext context, Operand op, int shift) { // The upper part of op is assumed to be zero. - Debug.Assert(shift >= 0 && shift < 64); + Debug.Assert(shift is >= 0 and < 64); if (shift == 0) { diff --git a/src/ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs b/src/ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs index 284f3f576..bcd6ce09e 100644 --- a/src/ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs +++ b/src/ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs @@ -231,10 +231,12 @@ namespace ARMeilleure.Instructions { result |= (long)((i >= end || i < start) ? 0x80 : b++) << (i * 8); } + for (int i = 8; i < 16; i++) { result2 |= (long)((i >= end || i < start) ? 0x80 : b++) << ((i - 8) * 8); } + return (result2, result); } @@ -261,6 +263,7 @@ namespace ARMeilleure.Instructions nMaskHigh = nMaskLow + 0x0808080808080808L; mMaskHigh = mMaskLow + 0x0808080808080808L; } + nMask = X86GetElements(context, nMaskHigh, nMaskLow); mMask = X86GetElements(context, mMaskHigh, mMaskLow); Operand nPart = context.AddIntrinsic(Intrinsic.X86Pshufb, n, nMask); @@ -285,6 +288,7 @@ namespace ARMeilleure.Instructions { extract = EmitVectorExtractZx32(context, op.Qn, op.In + byteOff, op.Size); } + byteOff++; res = EmitVectorInsert(context, res, extract, op.Id + index, op.Size); @@ -1304,6 +1308,7 @@ namespace ARMeilleure.Instructions case 2: return context.AddIntrinsic(Intrinsic.X86Shufps, op1, op1, Const(1 | (0 << 2) | (3 << 4) | (2 << 6))); } + break; case 2: // Rev32 @@ -1316,6 +1321,7 @@ namespace ARMeilleure.Instructions mask = X86GetElements(context, 0x0d0c0f0e_09080b0aL, 0x05040706_01000302L); return context.AddIntrinsic(Intrinsic.X86Pshufb, op1, mask); } + break; case 1: // Rev16 @@ -1341,6 +1347,7 @@ namespace ARMeilleure.Instructions case 3: return context.ByteSwap(op1); } + break; case 1: switch (op.Size) @@ -1355,6 +1362,7 @@ namespace ARMeilleure.Instructions context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op1, Const(0x0000ffff00000000ul)), Const(16)), context.ShiftLeft(context.BitwiseAnd(op1, Const(0x00000000ffff0000ul)), Const(16)))); } + break; case 2: // Swap upper and lower halves. diff --git a/src/ARMeilleure/Instructions/InstEmitSimdCvt.cs b/src/ARMeilleure/Instructions/InstEmitSimdCvt.cs index a5d4744f7..cf427eeae 100644 --- a/src/ARMeilleure/Instructions/InstEmitSimdCvt.cs +++ b/src/ARMeilleure/Instructions/InstEmitSimdCvt.cs @@ -1119,7 +1119,7 @@ namespace ARMeilleure.Instructions private static Operand EmitFPConvert(ArmEmitterContext context, Operand value, int size, bool signed) { - Debug.Assert(value.Type == OperandType.I32 || value.Type == OperandType.I64); + Debug.Assert(value.Type is OperandType.I32 or OperandType.I64); Debug.Assert((uint)size < 2); OperandType type = size == 0 ? OperandType.FP32 : OperandType.FP64; @@ -1136,7 +1136,7 @@ namespace ARMeilleure.Instructions private static Operand EmitScalarFcvts(ArmEmitterContext context, Operand value, int fBits) { - Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64); + Debug.Assert(value.Type is OperandType.FP32 or OperandType.FP64); value = EmitF2iFBitsMul(context, value, fBits); @@ -1160,7 +1160,7 @@ namespace ARMeilleure.Instructions private static Operand EmitScalarFcvtu(ArmEmitterContext context, Operand value, int fBits) { - Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64); + Debug.Assert(value.Type is OperandType.FP32 or OperandType.FP64); value = EmitF2iFBitsMul(context, value, fBits); @@ -1184,7 +1184,7 @@ namespace ARMeilleure.Instructions private static Operand EmitF2iFBitsMul(ArmEmitterContext context, Operand value, int fBits) { - Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64); + Debug.Assert(value.Type is OperandType.FP32 or OperandType.FP64); if (fBits == 0) { @@ -1203,7 +1203,7 @@ namespace ARMeilleure.Instructions private static Operand EmitI2fFBitsMul(ArmEmitterContext context, Operand value, int fBits) { - Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64); + Debug.Assert(value.Type is OperandType.FP32 or OperandType.FP64); if (fBits == 0) { diff --git a/src/ARMeilleure/Instructions/InstEmitSimdCvt32.cs b/src/ARMeilleure/Instructions/InstEmitSimdCvt32.cs index c35ffede4..f93552977 100644 --- a/src/ARMeilleure/Instructions/InstEmitSimdCvt32.cs +++ b/src/ARMeilleure/Instructions/InstEmitSimdCvt32.cs @@ -385,6 +385,7 @@ namespace ARMeilleure.Instructions { res = context.AddIntrinsic(Intrinsic.X86Cvtsd2ss, context.VectorZero(), res); } + res = context.AddIntrinsic(Intrinsic.X86Vcvtps2ph, res, Const(X86GetRoundControl(FPRoundingMode.ToNearest))); res = context.VectorExtract16(res, 0); InsertScalar16(context, op.Vd, op.T, res); @@ -397,6 +398,7 @@ namespace ARMeilleure.Instructions { res = context.AddIntrinsic(Intrinsic.X86Cvtss2sd, context.VectorZero(), res); } + res = context.VectorExtract(op.Size == 1 ? OperandType.I64 : OperandType.I32, res, 0); InsertScalar(context, op.Vd, res); } @@ -635,7 +637,7 @@ namespace ARMeilleure.Instructions private static Operand EmitFPConvert(ArmEmitterContext context, Operand value, OperandType type, bool signed) { - Debug.Assert(value.Type == OperandType.I32 || value.Type == OperandType.I64); + Debug.Assert(value.Type is OperandType.I32 or OperandType.I64); if (signed) { diff --git a/src/ARMeilleure/Instructions/InstEmitSimdHelper.cs b/src/ARMeilleure/Instructions/InstEmitSimdHelper.cs index d86830f70..11d0c93b4 100644 --- a/src/ARMeilleure/Instructions/InstEmitSimdHelper.cs +++ b/src/ARMeilleure/Instructions/InstEmitSimdHelper.cs @@ -363,7 +363,7 @@ namespace ARMeilleure.Instructions public static Operand EmitCountSetBits8(ArmEmitterContext context, Operand op) // "size" is 8 (SIMD&FP Inst.). { - Debug.Assert(op.Type == OperandType.I32 || op.Type == OperandType.I64); + Debug.Assert(op.Type is OperandType.I32 or OperandType.I64); Operand op0 = context.Subtract(op, context.BitwiseAnd(context.ShiftRightUI(op, Const(1)), Const(op.Type, 0x55L))); @@ -489,7 +489,7 @@ namespace ARMeilleure.Instructions public static Operand EmitRoundByRMode(ArmEmitterContext context, Operand op) { - Debug.Assert(op.Type == OperandType.FP32 || op.Type == OperandType.FP64); + Debug.Assert(op.Type is OperandType.FP32 or OperandType.FP64); Operand lbl1 = Label(); Operand lbl2 = Label(); @@ -1676,7 +1676,7 @@ namespace ARMeilleure.Instructions int eSize = 8 << size; Debug.Assert(op.Type == OperandType.I64); - Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64); + Debug.Assert(eSize is 8 or 16 or 32 or 64); Operand lbl1 = Label(); Operand lblEnd = Label(); @@ -1709,7 +1709,7 @@ namespace ARMeilleure.Instructions int eSize = 8 << size; Debug.Assert(op.Type == OperandType.I64); - Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64); + Debug.Assert(eSize is 8 or 16 or 32 or 64); Operand lblEnd = Label(); @@ -1735,7 +1735,7 @@ namespace ARMeilleure.Instructions int eSizeDst = 8 << sizeDst; Debug.Assert(op.Type == OperandType.I64); - Debug.Assert(eSizeDst == 8 || eSizeDst == 16 || eSizeDst == 32); + Debug.Assert(eSizeDst is 8 or 16 or 32); Operand lbl1 = Label(); Operand lblEnd = Label(); @@ -1768,7 +1768,7 @@ namespace ARMeilleure.Instructions int eSizeDst = 8 << sizeDst; Debug.Assert(op.Type == OperandType.I64); - Debug.Assert(eSizeDst == 8 || eSizeDst == 16 || eSizeDst == 32); + Debug.Assert(eSizeDst is 8 or 16 or 32); Operand lblEnd = Label(); diff --git a/src/ARMeilleure/Instructions/InstEmitSimdHelper32.cs b/src/ARMeilleure/Instructions/InstEmitSimdHelper32.cs index 2f021a1a1..c053fe27b 100644 --- a/src/ARMeilleure/Instructions/InstEmitSimdHelper32.cs +++ b/src/ARMeilleure/Instructions/InstEmitSimdHelper32.cs @@ -31,7 +31,7 @@ namespace ARMeilleure.Instructions { Debug.Assert(type != OperandType.V128); - if (type == OperandType.FP64 || type == OperandType.I64) + if (type is OperandType.FP64 or OperandType.I64) { // From dreg. return context.VectorExtract(type, GetVecA32(reg >> 1), reg & 1); @@ -48,7 +48,7 @@ namespace ARMeilleure.Instructions Debug.Assert(value.Type != OperandType.V128); Operand vec, insert; - if (value.Type == OperandType.FP64 || value.Type == OperandType.I64) + if (value.Type is OperandType.FP64 or OperandType.I64) { // From dreg. vec = GetVecA32(reg >> 1); @@ -71,7 +71,7 @@ namespace ARMeilleure.Instructions public static void InsertScalar16(ArmEmitterContext context, int reg, bool top, Operand value) { - Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.I32); + Debug.Assert(value.Type is OperandType.FP32 or OperandType.I32); Operand vec, insert; vec = GetVecA32(reg >> 2); @@ -880,6 +880,7 @@ namespace ARMeilleure.Instructions { res = EmitMoveDoubleWordToSide(context, res, side, op.Vd); } + res = EmitDoubleWordInsert(context, d, res, op.Vd); } diff --git a/src/ARMeilleure/Instructions/InstEmitSimdHelper32Arm64.cs b/src/ARMeilleure/Instructions/InstEmitSimdHelper32Arm64.cs index 568c07122..a1ca417b4 100644 --- a/src/ARMeilleure/Instructions/InstEmitSimdHelper32Arm64.cs +++ b/src/ARMeilleure/Instructions/InstEmitSimdHelper32Arm64.cs @@ -146,6 +146,7 @@ namespace ARMeilleure.Instructions { res = EmitMoveDoubleWordToSide(context, res, side, op.Vd); } + res = EmitDoubleWordInsert(context, d, res, op.Vd); } diff --git a/src/ARMeilleure/Instructions/InstEmitSimdLogical32.cs b/src/ARMeilleure/Instructions/InstEmitSimdLogical32.cs index 26d093447..1b0ef341b 100644 --- a/src/ARMeilleure/Instructions/InstEmitSimdLogical32.cs +++ b/src/ARMeilleure/Instructions/InstEmitSimdLogical32.cs @@ -268,6 +268,7 @@ namespace ARMeilleure.Instructions { m = context.BitwiseNot(m); } + return context.BitwiseExclusiveOr( context.BitwiseAnd(m, context.BitwiseExclusiveOr(d, n)), d); diff --git a/src/ARMeilleure/Instructions/InstEmitSimdMemory32.cs b/src/ARMeilleure/Instructions/InstEmitSimdMemory32.cs index 3808ef929..4d39b5fde 100644 --- a/src/ARMeilleure/Instructions/InstEmitSimdMemory32.cs +++ b/src/ARMeilleure/Instructions/InstEmitSimdMemory32.cs @@ -110,6 +110,7 @@ namespace ARMeilleure.Instructions EmitStoreSimd(context, address, d >> 1, index, op.Size); } } + offset += eBytes; d += op.Increment; } diff --git a/src/ARMeilleure/Instructions/InstEmitSimdShift.cs b/src/ARMeilleure/Instructions/InstEmitSimdShift.cs index ee7340adb..3469434c0 100644 --- a/src/ARMeilleure/Instructions/InstEmitSimdShift.cs +++ b/src/ARMeilleure/Instructions/InstEmitSimdShift.cs @@ -1634,7 +1634,7 @@ namespace ARMeilleure.Instructions int eSize = 8 << size; Debug.Assert(op.Type == OperandType.I64); - Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64); + Debug.Assert(eSize is 8 or 16 or 32 or 64); Operand res = context.AllocateLocal(OperandType.I64); @@ -1657,7 +1657,7 @@ namespace ARMeilleure.Instructions int eSize = 8 << size; Debug.Assert(op.Type == OperandType.I64); - Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64); + Debug.Assert(eSize is 8 or 16 or 32 or 64); Operand lblEnd = Label(); @@ -1732,7 +1732,7 @@ namespace ARMeilleure.Instructions Debug.Assert(op.Type == OperandType.I64); Debug.Assert(shiftLsB.Type == OperandType.I32); - Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64); + Debug.Assert(eSize is 8 or 16 or 32 or 64); Operand lbl1 = Label(); Operand lblEnd = Label(); @@ -1769,7 +1769,7 @@ namespace ARMeilleure.Instructions Debug.Assert(op.Type == OperandType.I64); Debug.Assert(shiftLsB.Type == OperandType.I32); - Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64); + Debug.Assert(eSize is 8 or 16 or 32 or 64); Operand lbl1 = Label(); Operand lbl2 = Label(); @@ -1813,6 +1813,7 @@ namespace ARMeilleure.Instructions ? EmitSignedSrcSatQ(context, shl, size, signedDst: true) : EmitUnsignedSrcSatQ(context, shl, size, signedDst: false)); } + context.Branch(lblEnd); context.MarkLabel(lblEnd); @@ -1850,6 +1851,7 @@ namespace ARMeilleure.Instructions { context.Copy(res, sar); } + context.Branch(lblEnd); context.MarkLabel(lblEnd); @@ -1906,6 +1908,7 @@ namespace ARMeilleure.Instructions Operand right = context.BitwiseOr(shr, context.ShiftRightUI(oneShl63UL, context.Subtract(shift, one))); context.Copy(res, context.ConditionalSelect(isEqual, oneUL, right)); } + context.Branch(lblEnd); context.MarkLabel(lblEnd); diff --git a/src/ARMeilleure/Instructions/NativeInterface.cs b/src/ARMeilleure/Instructions/NativeInterface.cs index 9d6279613..b4922629b 100644 --- a/src/ARMeilleure/Instructions/NativeInterface.cs +++ b/src/ARMeilleure/Instructions/NativeInterface.cs @@ -69,13 +69,13 @@ namespace ARMeilleure.Instructions [UnmanagedCallersOnly] public static ulong GetCtrEl0() { - return GetContext().CtrEl0; + return ExecutionContext.CtrEl0; } [UnmanagedCallersOnly] public static ulong GetDczidEl0() { - return GetContext().DczidEl0; + return ExecutionContext.DczidEl0; } [UnmanagedCallersOnly] diff --git a/src/ARMeilleure/Instructions/SoftFloat.cs b/src/ARMeilleure/Instructions/SoftFloat.cs index a2bb23be8..ccc45cc64 100644 --- a/src/ARMeilleure/Instructions/SoftFloat.cs +++ b/src/ARMeilleure/Instructions/SoftFloat.cs @@ -24,7 +24,7 @@ namespace ARMeilleure.Instructions { uint src = (uint)idx + 256u; - Debug.Assert(256u <= src && src < 512u); + Debug.Assert(src is >= 256u and < 512u); src = (src << 1) + 1u; @@ -32,7 +32,7 @@ namespace ARMeilleure.Instructions uint dst = (aux + 1u) >> 1; - Debug.Assert(256u <= dst && dst < 512u); + Debug.Assert(dst is >= 256u and < 512u); tbl[idx] = (byte)(dst - 256u); } @@ -48,7 +48,7 @@ namespace ARMeilleure.Instructions { uint src = (uint)idx + 128u; - Debug.Assert(128u <= src && src < 512u); + Debug.Assert(src is >= 128u and < 512u); if (src < 256u) { @@ -69,7 +69,7 @@ namespace ARMeilleure.Instructions uint dst = (aux + 1u) >> 1; - Debug.Assert(256u <= dst && dst < 512u); + Debug.Assert(dst is >= 256u and < 512u); tbl[idx] = (byte)(dst - 256u); } @@ -322,7 +322,7 @@ namespace ARMeilleure.Instructions float result; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { if ((context.Fpcr & FPCR.Dn) != 0) { @@ -498,7 +498,7 @@ namespace ARMeilleure.Instructions double result; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { if ((context.Fpcr & FPCR.Dn) != 0) { @@ -676,7 +676,7 @@ namespace ARMeilleure.Instructions ushort resultBits; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { if (altHp) { @@ -1086,7 +1086,7 @@ namespace ARMeilleure.Instructions { return FPMaxFpscrImpl(value1, value2, standardFpscr == 1); } - + private static float FPMaxFpscrImpl(float value1, float value2, bool standardFpscr) { ExecutionContext context = NativeInterface.GetContext(); @@ -1522,7 +1522,7 @@ namespace ARMeilleure.Instructions float result; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { result = FPProcessNaN(type, op, context, fpcr); } @@ -1689,7 +1689,7 @@ namespace ARMeilleure.Instructions float result; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { result = FPProcessNaN(type, op, context, fpcr); } @@ -1726,7 +1726,7 @@ namespace ARMeilleure.Instructions float result; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { result = FPProcessNaN(type, op, context, fpcr); } @@ -1920,7 +1920,7 @@ namespace ARMeilleure.Instructions float result; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { result = FPProcessNaN(type, op, context, fpcr); } @@ -2211,7 +2211,7 @@ namespace ARMeilleure.Instructions ushort resultBits; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { if (altHp) { @@ -3057,7 +3057,7 @@ namespace ARMeilleure.Instructions double result; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { result = FPProcessNaN(type, op, context, fpcr); } @@ -3224,7 +3224,7 @@ namespace ARMeilleure.Instructions double result; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { result = FPProcessNaN(type, op, context, fpcr); } @@ -3261,7 +3261,7 @@ namespace ARMeilleure.Instructions double result; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { result = FPProcessNaN(type, op, context, fpcr); } @@ -3455,7 +3455,7 @@ namespace ARMeilleure.Instructions double result; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { result = FPProcessNaN(type, op, context, fpcr); } diff --git a/src/ARMeilleure/IntermediateRepresentation/Intrinsic.cs b/src/ARMeilleure/IntermediateRepresentation/Intrinsic.cs index b9cab6674..9d87c13b3 100644 --- a/src/ARMeilleure/IntermediateRepresentation/Intrinsic.cs +++ b/src/ARMeilleure/IntermediateRepresentation/Intrinsic.cs @@ -4,7 +4,6 @@ using System.Diagnostics.CodeAnalysis; namespace ARMeilleure.IntermediateRepresentation { [Flags] - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum Intrinsic : ushort { // X86 (SSE and AVX) diff --git a/src/ARMeilleure/IntermediateRepresentation/Operand.cs b/src/ARMeilleure/IntermediateRepresentation/Operand.cs index 9966308e6..2b3545004 100644 --- a/src/ARMeilleure/IntermediateRepresentation/Operand.cs +++ b/src/ARMeilleure/IntermediateRepresentation/Operand.cs @@ -446,7 +446,7 @@ namespace ARMeilleure.IntermediateRepresentation Data* data = null; // If constant or register, then try to look up in the intern table before allocating. - if (kind == OperandKind.Constant || kind == OperandKind.Register) + if (kind is OperandKind.Constant or OperandKind.Register) { uint hash = (uint)HashCode.Combine(kind, type, value); diff --git a/src/ARMeilleure/IntermediateRepresentation/OperandType.cs b/src/ARMeilleure/IntermediateRepresentation/OperandType.cs index 67ebdcde4..fec22eed6 100644 --- a/src/ARMeilleure/IntermediateRepresentation/OperandType.cs +++ b/src/ARMeilleure/IntermediateRepresentation/OperandType.cs @@ -16,8 +16,8 @@ namespace ARMeilleure.IntermediateRepresentation { public static bool IsInteger(this OperandType type) { - return type == OperandType.I32 || - type == OperandType.I64; + return type is OperandType.I32 or + OperandType.I64; } public static RegisterType ToRegisterType(this OperandType type) diff --git a/src/ARMeilleure/Memory/MemoryManagerType.cs b/src/ARMeilleure/Memory/MemoryManagerType.cs index bc8ae2635..cad7c3558 100644 --- a/src/ARMeilleure/Memory/MemoryManagerType.cs +++ b/src/ARMeilleure/Memory/MemoryManagerType.cs @@ -47,12 +47,12 @@ namespace ARMeilleure.Memory { public static bool IsHostMapped(this MemoryManagerType type) { - return type == MemoryManagerType.HostMapped || type == MemoryManagerType.HostMappedUnsafe; + return type is MemoryManagerType.HostMapped or MemoryManagerType.HostMappedUnsafe; } public static bool IsHostTracked(this MemoryManagerType type) { - return type == MemoryManagerType.HostTracked || type == MemoryManagerType.HostTrackedUnsafe; + return type is MemoryManagerType.HostTracked or MemoryManagerType.HostTrackedUnsafe; } public static bool IsHostMappedOrTracked(this MemoryManagerType type) diff --git a/src/ARMeilleure/State/ExecutionContext.cs b/src/ARMeilleure/State/ExecutionContext.cs index 6996ec221..223e59d79 100644 --- a/src/ARMeilleure/State/ExecutionContext.cs +++ b/src/ARMeilleure/State/ExecutionContext.cs @@ -16,10 +16,8 @@ namespace ARMeilleure.State public ulong Pc => _nativeContext.GetPc(); -#pragma warning disable CA1822 // Mark member as static - public uint CtrEl0 => 0x8444c004; - public uint DczidEl0 => 0x00000004; -#pragma warning restore CA1822 + public static uint CtrEl0 => 0x8444c004; + public static uint DczidEl0 => 0x00000004; public ulong CntfrqEl0 => _counter.Frequency; public ulong CntpctEl0 => _counter.Counter; diff --git a/src/ARMeilleure/State/NativeContext.cs b/src/ARMeilleure/State/NativeContext.cs index 140b6f7a7..c90e522a9 100644 --- a/src/ARMeilleure/State/NativeContext.cs +++ b/src/ARMeilleure/State/NativeContext.cs @@ -111,6 +111,7 @@ namespace ARMeilleure.State { value |= GetStorage().Flags[flag] != 0 ? 1u << flag : 0u; } + return value; } @@ -155,6 +156,7 @@ namespace ARMeilleure.State value |= GetStorage().FpFlags[flag] != 0 ? bit : 0u; } } + return value; } diff --git a/src/ARMeilleure/Translation/Cache/JitCache.cs b/src/ARMeilleure/Translation/Cache/JitCache.cs index e480985b1..7931fb360 100644 --- a/src/ARMeilleure/Translation/Cache/JitCache.cs +++ b/src/ARMeilleure/Translation/Cache/JitCache.cs @@ -24,7 +24,7 @@ namespace ARMeilleure.Translation.Cache private static JitCacheInvalidation _jitCacheInvalidator; - private static List _cacheAllocators = []; + private static readonly List _cacheAllocators = []; private static readonly List _cacheEntries = []; @@ -205,7 +205,6 @@ namespace ARMeilleure.Translation.Cache return allocOffsetNew; } - private static int AlignCodeSize(int codeSize) { return checked(codeSize + (CodeAlignment - 1)) & ~(CodeAlignment - 1); diff --git a/src/ARMeilleure/Translation/Delegates.cs b/src/ARMeilleure/Translation/Delegates.cs index d4f46108c..f44e8dc54 100644 --- a/src/ARMeilleure/Translation/Delegates.cs +++ b/src/ARMeilleure/Translation/Delegates.cs @@ -32,7 +32,7 @@ namespace ARMeilleure.Translation return _delegates.Values[index].FuncPtr; // O(1). } - + public static int GetDelegateIndex(MethodInfo info) { ArgumentNullException.ThrowIfNull(info); @@ -48,7 +48,7 @@ namespace ARMeilleure.Translation return index; } - + private static void SetDelegateInfo(MethodInfo method) { string key = GetKey(method); diff --git a/src/ARMeilleure/Translation/Dominance.cs b/src/ARMeilleure/Translation/Dominance.cs index b62714fdf..e2185bd85 100644 --- a/src/ARMeilleure/Translation/Dominance.cs +++ b/src/ARMeilleure/Translation/Dominance.cs @@ -77,7 +77,7 @@ namespace ARMeilleure.Translation { continue; } - + for (int pBlkIndex = 0; pBlkIndex < block.Predecessors.Count; pBlkIndex++) { BasicBlock current = block.Predecessors[pBlkIndex]; diff --git a/src/ARMeilleure/Translation/IntervalTree.cs b/src/ARMeilleure/Translation/IntervalTree.cs index 2fa431a8b..f4abe3bd5 100644 --- a/src/ARMeilleure/Translation/IntervalTree.cs +++ b/src/ARMeilleure/Translation/IntervalTree.cs @@ -124,7 +124,7 @@ namespace ARMeilleure.Translation /// /// The node to search for values within /// The list to add values to - private void AddToList(IntervalTreeNode node, List list) + private static void AddToList(IntervalTreeNode node, List list) { if (node == null) { @@ -165,6 +165,7 @@ namespace ARMeilleure.Translation return node; } } + return null; } @@ -175,7 +176,7 @@ namespace ARMeilleure.Translation /// End of the range /// Overlaps array to place results in /// Overlaps count to update - private void GetKeys(IntervalTreeNode node, TK start, TK end, ref TK[] overlaps, ref int overlapCount) + private static void GetKeys(IntervalTreeNode node, TK start, TK end, ref TK[] overlaps, ref int overlapCount) { if (node == null || start.CompareTo(node.Max) >= 0) { @@ -311,6 +312,7 @@ namespace ARMeilleure.Translation return false; } } + IntervalTreeNode newNode = new(start, end, value, parent); if (newNode.Parent == null) { @@ -422,12 +424,14 @@ namespace ARMeilleure.Translation { return Maximum(node.Left); } + IntervalTreeNode parent = node.Parent; while (parent != null && node == parent.Left) { node = parent; parent = parent.Parent; } + return parent; } @@ -452,6 +456,7 @@ namespace ARMeilleure.Translation RotateLeft(ParentOf(ptr)); sibling = RightOf(ParentOf(ptr)); } + if (ColorOf(LeftOf(sibling)) == Black && ColorOf(RightOf(sibling)) == Black) { SetColor(sibling, Red); @@ -466,6 +471,7 @@ namespace ARMeilleure.Translation RotateRight(sibling); sibling = RightOf(ParentOf(ptr)); } + SetColor(sibling, ColorOf(ParentOf(ptr))); SetColor(ParentOf(ptr), Black); SetColor(RightOf(sibling), Black); @@ -484,6 +490,7 @@ namespace ARMeilleure.Translation RotateRight(ParentOf(ptr)); sibling = LeftOf(ParentOf(ptr)); } + if (ColorOf(RightOf(sibling)) == Black && ColorOf(LeftOf(sibling)) == Black) { SetColor(sibling, Red); @@ -498,6 +505,7 @@ namespace ARMeilleure.Translation RotateLeft(sibling); sibling = LeftOf(ParentOf(ptr)); } + SetColor(sibling, ColorOf(ParentOf(ptr))); SetColor(ParentOf(ptr), Black); SetColor(LeftOf(sibling), Black); @@ -506,6 +514,7 @@ namespace ARMeilleure.Translation } } } + SetColor(ptr, Black); } @@ -532,6 +541,7 @@ namespace ARMeilleure.Translation balanceNode = ParentOf(balanceNode); RotateLeft(balanceNode); } + SetColor(ParentOf(balanceNode), Black); SetColor(ParentOf(ParentOf(balanceNode)), Red); RotateRight(ParentOf(ParentOf(balanceNode))); @@ -555,12 +565,14 @@ namespace ARMeilleure.Translation balanceNode = ParentOf(balanceNode); RotateRight(balanceNode); } + SetColor(ParentOf(balanceNode), Black); SetColor(ParentOf(ParentOf(balanceNode)), Red); RotateLeft(ParentOf(ParentOf(balanceNode))); } } } + SetColor(_root, Black); } @@ -574,6 +586,7 @@ namespace ARMeilleure.Translation { node.Right.Parent = node; } + IntervalTreeNode nodeParent = ParentOf(node); right.Parent = nodeParent; if (nodeParent == null) @@ -588,6 +601,7 @@ namespace ARMeilleure.Translation { nodeParent.Right = right; } + right.Left = node; node.Parent = right; @@ -605,6 +619,7 @@ namespace ARMeilleure.Translation { node.Left.Parent = node; } + IntervalTreeNode nodeParent = ParentOf(node); left.Parent = nodeParent; if (nodeParent == null) @@ -619,6 +634,7 @@ namespace ARMeilleure.Translation { nodeParent.Left = left; } + left.Right = node; node.Parent = left; diff --git a/src/ARMeilleure/Translation/PTC/Ptc.cs b/src/ARMeilleure/Translation/PTC/Ptc.cs index b3baa4413..f36d4256d 100644 --- a/src/ARMeilleure/Translation/PTC/Ptc.cs +++ b/src/ARMeilleure/Translation/PTC/Ptc.cs @@ -33,7 +33,7 @@ namespace ARMeilleure.Translation.PTC private const string OuterHeaderMagicString = "PTCohd\0\0"; private const string InnerHeaderMagicString = "PTCihd\0\0"; - private const uint InternalVersion = 7007; //! 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 BackupDir = "1"; @@ -193,7 +193,7 @@ namespace ARMeilleure.Translation.PTC _infosStream.Seek(0L, SeekOrigin.Begin); bool foundBadFunction = false; - for (int index = 0; index < GetEntriesCount(); index++) + for (int index = 0; index < _infosStream.Length / Unsafe.SizeOf(); index++) { InfoEntry infoEntry = DeserializeStructure(_infosStream); foreach (ulong address in blacklist) @@ -835,8 +835,6 @@ namespace ARMeilleure.Translation.PTC return; } - - int degreeOfParallelism = Environment.ProcessorCount; if (Optimizations.LowPower) @@ -873,7 +871,7 @@ namespace ARMeilleure.Translation.PTC Debug.Assert(Profiler.IsAddressInStaticCodeRange(address)); - TranslatedFunction func = translator.Translate(address, executionMode, highCq); + TranslatedFunction func = translator.Translate(address, executionMode, highCq, pptcTranslation: true); if (func == null) { @@ -896,13 +894,12 @@ namespace ARMeilleure.Translation.PTC } } - List threads = Enumerable.Range(0, degreeOfParallelism) - .Select(idx => + .Select(idx => new Thread(TranslateFuncs) { - IsBackground = true, - Name = "Ptc.TranslateThread." + idx + IsBackground = true, + Name = "Ptc.TranslateThread." + idx } ).ToList(); @@ -912,6 +909,7 @@ namespace ARMeilleure.Translation.PTC { thread.Start(); } + foreach (Thread thread in threads) { thread.Join(); @@ -925,8 +923,8 @@ namespace ARMeilleure.Translation.PTC sw.Stop(); PtcStateChanged?.Invoke(PtcLoadingState.Loaded, _translateCount, _translateTotalCount); - - Logger.Info?.Print(LogClass.Ptc, + + Logger.Info?.Print(LogClass.Ptc, $"{_translateCount} of {_translateTotalCount} functions translated in {sw.Elapsed.TotalSeconds} seconds " + $"| {"function".ToQuantity(_translateTotalCount - _translateCount)} blacklisted " + $"| Thread count: {degreeOfParallelism}"); @@ -1164,8 +1162,8 @@ namespace ARMeilleure.Translation.PTC public void Close() { - if (State == PtcState.Enabled || - State == PtcState.Continuing) + if (State is PtcState.Enabled or + PtcState.Continuing) { State = PtcState.Closing; } diff --git a/src/ARMeilleure/Translation/PTC/PtcProfiler.cs b/src/ARMeilleure/Translation/PTC/PtcProfiler.cs index f3aaa58ff..c7e399433 100644 --- a/src/ARMeilleure/Translation/PTC/PtcProfiler.cs +++ b/src/ARMeilleure/Translation/PTC/PtcProfiler.cs @@ -1,5 +1,6 @@ using ARMeilleure.State; using Humanizer; +using Microsoft.IO; using Ryujinx.Common; using Ryujinx.Common.Logging; using Ryujinx.Common.Memory; @@ -26,7 +27,7 @@ namespace ARMeilleure.Translation.PTC private const uint InternalVersion = 7007; //! Not to be incremented manually for each change to the ARMeilleure project. - private static readonly uint[] _migrateInternalVersions = + private static readonly uint[] _migrateInternalVersions = [ 1866, 5518, @@ -75,7 +76,7 @@ namespace ARMeilleure.Translation.PTC Enabled = false; } - private void TimerElapsed(object _, ElapsedEventArgs __) + private void TimerElapsed(object _, ElapsedEventArgs __) => new Thread(PreSave) { Name = "Ptc.DiskWriter" }.Start(); public void AddEntry(ulong address, ExecutionMode mode, bool highCq, bool blacklist = false) @@ -151,7 +152,7 @@ namespace ARMeilleure.Translation.PTC if (!funcProfile.Blacklist) continue; - if (!funcs.Contains(ptr)) + if (!funcs.Contains(ptr)) funcs.Add(ptr); } @@ -219,7 +220,7 @@ namespace ARMeilleure.Translation.PTC return false; } - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); Debug.Assert(stream.Seek(0L, SeekOrigin.Begin) == 0L && stream.Length == 0L); try @@ -293,10 +294,10 @@ namespace ARMeilleure.Translation.PTC { if (migrateEntryFunc != null) { - return DeserializeAndUpdateDictionary(stream, (Stream stream) => { return new FuncProfile(DeserializeStructure(stream)); }, migrateEntryFunc); + return DeserializeAndUpdateDictionary(stream, stream => { return new FuncProfile(DeserializeStructure(stream)); }, migrateEntryFunc); } - return DeserializeDictionary(stream, (Stream stream) => { return new FuncProfile(DeserializeStructure(stream)); }); + return DeserializeDictionary(stream, stream => { return new FuncProfile(DeserializeStructure(stream)); }); } private static ReadOnlySpan GetReadOnlySpan(MemoryStream memoryStream) @@ -467,8 +468,8 @@ namespace ARMeilleure.Translation.PTC public void Start() { - if (_ptc.State == PtcState.Enabled || - _ptc.State == PtcState.Continuing) + if (_ptc.State is PtcState.Enabled or + PtcState.Continuing) { Enabled = true; diff --git a/src/ARMeilleure/Translation/Translator.cs b/src/ARMeilleure/Translation/Translator.cs index 14c80f24b..d8528cfd6 100644 --- a/src/ARMeilleure/Translation/Translator.cs +++ b/src/ARMeilleure/Translation/Translator.cs @@ -219,7 +219,7 @@ namespace ARMeilleure.Translation } } - internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false) + internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false, bool pptcTranslation = false) { ArmEmitterContext context = new( Memory, @@ -246,7 +246,7 @@ namespace ARMeilleure.Translation context.Branch(context.GetLabel(address)); } - ControlFlowGraph cfg = EmitAndGetCFG(context, blocks, out Range funcRange, out Counter counter); + ControlFlowGraph cfg = EmitAndGetCFG(context, blocks, out Range funcRange, out Counter counter, pptcTranslation); if (cfg == null) { @@ -326,7 +326,8 @@ namespace ARMeilleure.Translation ArmEmitterContext context, Block[] blocks, out Range range, - out Counter counter) + out Counter counter, + bool pptcTranslation) { counter = null; @@ -411,7 +412,10 @@ namespace ARMeilleure.Translation if (opCode.Instruction.Emitter != null) { opCode.Instruction.Emitter(context); - if (opCode.Instruction.Name == InstName.Und && blkIndex == 0) + // if we're pre-compiling PPTC functions, and we hit an Undefined instruction as the first + // instruction in the block, mark the function as blacklisted + // this way, we don't pre-compile Exlaunch hooks, which allows ExeFS mods to run with PPTC + if (pptcTranslation && opCode.Instruction.Name == InstName.Und && blkIndex == 0) { range = new Range(rangeStart, rangeEnd); return null; diff --git a/src/Ryujinx.Audio.Backends.OpenAL/OpenALHardwareDeviceDriver.cs b/src/Ryujinx.Audio.Backends.OpenAL/OpenALHardwareDeviceDriver.cs index 25f91f8e9..8be6197f6 100644 --- a/src/Ryujinx.Audio.Backends.OpenAL/OpenALHardwareDeviceDriver.cs +++ b/src/Ryujinx.Audio.Backends.OpenAL/OpenALHardwareDeviceDriver.cs @@ -178,7 +178,7 @@ namespace Ryujinx.Audio.Backends.OpenAL public bool SupportsChannelCount(uint channelCount) { - return channelCount == 1 || channelCount == 2 || channelCount == 6; + return channelCount is 1 or 2 or 6; } public bool SupportsDirection(Direction direction) diff --git a/src/Ryujinx.Audio.Backends.SDL2/SDL2HardwareDeviceDriver.cs b/src/Ryujinx.Audio.Backends.SDL2/SDL2HardwareDeviceDriver.cs index 2d04073d7..d5381209e 100644 --- a/src/Ryujinx.Audio.Backends.SDL2/SDL2HardwareDeviceDriver.cs +++ b/src/Ryujinx.Audio.Backends.SDL2/SDL2HardwareDeviceDriver.cs @@ -24,10 +24,8 @@ namespace Ryujinx.Audio.Backends.SDL2 // TODO: Add this to SDL2-CS // NOTE: We use a DllImport here because of marshaling issue for spec. -#pragma warning disable SYSLIB1054 [DllImport("SDL2")] private static extern int SDL_GetDefaultAudioInfo(nint name, out SDL_AudioSpec spec, int isCapture); -#pragma warning restore SYSLIB1054 public SDL2HardwareDeviceDriver() { diff --git a/src/Ryujinx.Audio/Backends/CompatLayer/CompatLayerHardwareDeviceDriver.cs b/src/Ryujinx.Audio/Backends/CompatLayer/CompatLayerHardwareDeviceDriver.cs index a2c2cdcd0..8bc2a6016 100644 --- a/src/Ryujinx.Audio/Backends/CompatLayer/CompatLayerHardwareDeviceDriver.cs +++ b/src/Ryujinx.Audio/Backends/CompatLayer/CompatLayerHardwareDeviceDriver.cs @@ -162,7 +162,7 @@ namespace Ryujinx.Audio.Backends.CompatLayer public bool SupportsChannelCount(uint channelCount) { - return channelCount == 1 || channelCount == 2 || channelCount == 6; + return channelCount is 1 or 2 or 6; } public bool SupportsSampleFormat(SampleFormat sampleFormat) @@ -184,7 +184,7 @@ namespace Ryujinx.Audio.Backends.CompatLayer public bool SupportsDirection(Direction direction) { - return direction == Direction.Input || direction == Direction.Output; + return direction is Direction.Input or Direction.Output; } } } diff --git a/src/Ryujinx.Audio/Backends/Dummy/DummyHardwareDeviceDriver.cs b/src/Ryujinx.Audio/Backends/Dummy/DummyHardwareDeviceDriver.cs index 5991b816f..2cd15c092 100644 --- a/src/Ryujinx.Audio/Backends/Dummy/DummyHardwareDeviceDriver.cs +++ b/src/Ryujinx.Audio/Backends/Dummy/DummyHardwareDeviceDriver.cs @@ -73,12 +73,12 @@ namespace Ryujinx.Audio.Backends.Dummy public bool SupportsDirection(Direction direction) { - return direction == Direction.Output || direction == Direction.Input; + return direction is Direction.Output or Direction.Input; } public bool SupportsChannelCount(uint channelCount) { - return channelCount == 1 || channelCount == 2 || channelCount == 6; + return channelCount is 1 or 2 or 6; } } } diff --git a/src/Ryujinx.Audio/Common/AudioDeviceSession.cs b/src/Ryujinx.Audio/Common/AudioDeviceSession.cs index a0e04c80d..6ba001e80 100644 --- a/src/Ryujinx.Audio/Common/AudioDeviceSession.cs +++ b/src/Ryujinx.Audio/Common/AudioDeviceSession.cs @@ -109,7 +109,7 @@ namespace Ryujinx.Audio.Common /// The state of the session public AudioDeviceState GetState() { - Debug.Assert(_state == AudioDeviceState.Started || _state == AudioDeviceState.Stopped); + Debug.Assert(_state is AudioDeviceState.Started or AudioDeviceState.Stopped); return _state; } diff --git a/src/Ryujinx.Audio/Input/AudioInputManager.cs b/src/Ryujinx.Audio/Input/AudioInputManager.cs index 5defef0f7..3869867e0 100644 --- a/src/Ryujinx.Audio/Input/AudioInputManager.cs +++ b/src/Ryujinx.Audio/Input/AudioInputManager.cs @@ -166,7 +166,7 @@ namespace Ryujinx.Audio.Input /// /// If true, filter disconnected devices /// The list of all audio inputs name - public string[] ListAudioIns(bool filtered) + public static string[] ListAudioIns(bool filtered) { if (filtered) { diff --git a/src/Ryujinx.Audio/Input/AudioInputSystem.cs b/src/Ryujinx.Audio/Input/AudioInputSystem.cs index 65b99745d..d1d4b0381 100644 --- a/src/Ryujinx.Audio/Input/AudioInputSystem.cs +++ b/src/Ryujinx.Audio/Input/AudioInputSystem.cs @@ -91,12 +91,12 @@ namespace Ryujinx.Audio.Input return ResultCode.DeviceNotFound; } - if (configuration.SampleRate != 0 && configuration.SampleRate != Constants.TargetSampleRate) + if (configuration.SampleRate is not 0 and not Constants.TargetSampleRate) { return ResultCode.UnsupportedSampleRate; } - if (configuration.ChannelCount != 0 && configuration.ChannelCount != 1 && configuration.ChannelCount != 2 && configuration.ChannelCount != 6) + if (configuration.ChannelCount is not 0 and not 1 and not 2 and not 6) { return ResultCode.UnsupportedChannelConfiguration; } diff --git a/src/Ryujinx.Audio/Integration/IHardwareDevice.cs b/src/Ryujinx.Audio/Integration/IHardwareDevice.cs index f9ade9dbc..42d543f55 100644 --- a/src/Ryujinx.Audio/Integration/IHardwareDevice.cs +++ b/src/Ryujinx.Audio/Integration/IHardwareDevice.cs @@ -47,7 +47,7 @@ namespace Ryujinx.Audio.Integration { uint channelCount = GetChannelCount(); - Debug.Assert(channelCount > 0 && channelCount <= Constants.ChannelCountMax); + Debug.Assert(channelCount is > 0 and <= Constants.ChannelCountMax); return channelCount != Constants.ChannelCountMax; } diff --git a/src/Ryujinx.Audio/Output/AudioOutputManager.cs b/src/Ryujinx.Audio/Output/AudioOutputManager.cs index 556088bc2..4e2971743 100644 --- a/src/Ryujinx.Audio/Output/AudioOutputManager.cs +++ b/src/Ryujinx.Audio/Output/AudioOutputManager.cs @@ -165,7 +165,7 @@ namespace Ryujinx.Audio.Output /// Get the list of all audio outputs name. /// /// The list of all audio outputs name - public string[] ListAudioOuts() + public static string[] ListAudioOuts() { return [Constants.DefaultDeviceOutputName]; } diff --git a/src/Ryujinx.Audio/Output/AudioOutputSystem.cs b/src/Ryujinx.Audio/Output/AudioOutputSystem.cs index dc7d52ced..3cf6e0722 100644 --- a/src/Ryujinx.Audio/Output/AudioOutputSystem.cs +++ b/src/Ryujinx.Audio/Output/AudioOutputSystem.cs @@ -91,12 +91,12 @@ namespace Ryujinx.Audio.Output return ResultCode.DeviceNotFound; } - if (configuration.SampleRate != 0 && configuration.SampleRate != Constants.TargetSampleRate) + if (configuration.SampleRate is not 0 and not Constants.TargetSampleRate) { return ResultCode.UnsupportedSampleRate; } - if (configuration.ChannelCount != 0 && configuration.ChannelCount != 1 && configuration.ChannelCount != 2 && configuration.ChannelCount != 6) + if (configuration.ChannelCount is not 0 and not 1 and not 2 and not 6) { return ResultCode.UnsupportedChannelConfiguration; } diff --git a/src/Ryujinx.Audio/Renderer/Device/VirtualDevice.cs b/src/Ryujinx.Audio/Renderer/Device/VirtualDevice.cs index 439be6bd8..f5ba9a271 100644 --- a/src/Ryujinx.Audio/Renderer/Device/VirtualDevice.cs +++ b/src/Ryujinx.Audio/Renderer/Device/VirtualDevice.cs @@ -58,7 +58,7 @@ namespace Ryujinx.Audio.Renderer.Device /// The new master volume. public void UpdateMasterVolume(float volume) { - Debug.Assert(volume >= 0.0f && volume <= 1.0f); + Debug.Assert(volume is >= 0.0f and <= 1.0f); MasterVolume = volume; } diff --git a/src/Ryujinx.Audio/Renderer/Device/VirtualDeviceSessionRegistry.cs b/src/Ryujinx.Audio/Renderer/Device/VirtualDeviceSessionRegistry.cs index 4ad70619e..5c42ed991 100644 --- a/src/Ryujinx.Audio/Renderer/Device/VirtualDeviceSessionRegistry.cs +++ b/src/Ryujinx.Audio/Renderer/Device/VirtualDeviceSessionRegistry.cs @@ -17,9 +17,7 @@ namespace Ryujinx.Audio.Renderer.Device /// The default . /// /// This is used when the USB device is the default one on older revision. -#pragma warning disable CA1822 // Mark member as static - public VirtualDevice DefaultDevice => VirtualDevice.Devices[0]; -#pragma warning restore CA1822 + public static VirtualDevice DefaultDevice => VirtualDevice.Devices[0]; ///

/// The current active . diff --git a/src/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs b/src/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs index 8b497fe2a..1a5802a37 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs @@ -81,14 +81,14 @@ namespace Ryujinx.Audio.Renderer.Dsp [MethodImpl(MethodImplOptions.AggressiveInlining)] private static short GetCoefficientAtIndex(ReadOnlySpan coefficients, int index) { - if ((uint)index >= (uint)coefficients.Length) + if ((uint)index < (uint)coefficients.Length) { - Logger.Error?.Print(LogClass.AudioRenderer, $"Out of bound read for coefficient at index {index}"); - - return 0; + return coefficients[index]; } - return coefficients[index]; + Logger.Error?.Print(LogClass.AudioRenderer, $"Out of bound read for coefficient at index {index}"); + + return 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs index 21cf69504..ecd3c3c93 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs @@ -129,7 +129,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command delayFeedbackCrossGain, 0.0f, delayFeedbackBaseGain, delayFeedbackCrossGain, 0.0f, delayFeedbackCrossGain, delayFeedbackCrossGain, delayFeedbackBaseGain); - for (int i = 0; i < sampleCount; i++) { Vector4 channelInput = new() diff --git a/src/Ryujinx.Audio/Renderer/Dsp/State/DelayState.cs b/src/Ryujinx.Audio/Renderer/Dsp/State/DelayState.cs index 17ad2a40d..1dfc2d28b 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/State/DelayState.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/State/DelayState.cs @@ -40,7 +40,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.State DelayFeedbackBaseGain = (1.0f - channelSpread) * FeedbackGain; - if (parameter.ChannelCount == 4 || parameter.ChannelCount == 6) + if (parameter.ChannelCount is 4 or 6) { DelayFeedbackCrossGain = channelSpread * 0.5f * FeedbackGain; } diff --git a/src/Ryujinx.Audio/Renderer/Dsp/UpsamplerHelper.cs b/src/Ryujinx.Audio/Renderer/Dsp/UpsamplerHelper.cs index 5732cdb21..8d833b712 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/UpsamplerHelper.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/UpsamplerHelper.cs @@ -27,6 +27,7 @@ namespace Ryujinx.Audio.Renderer.Dsp { return 1.0f; } + return (MathF.Sin(MathF.PI * x) / (MathF.PI * x)); } @@ -141,6 +142,7 @@ namespace Ryujinx.Audio.Renderer.Dsp state.Phase = (state.Phase + 1) % 6; } + break; case 3.0f: for (int i = 0; i < outputSampleCount; i++) @@ -161,6 +163,7 @@ namespace Ryujinx.Audio.Renderer.Dsp state.Phase = (state.Phase + 1) % 3; } + break; case 1.5f: // Upsample by 3 then decimate by 2. @@ -183,6 +186,7 @@ namespace Ryujinx.Audio.Renderer.Dsp state.Phase = (state.Phase + 1) % 3; } + break; default: throw new ArgumentOutOfRangeException(nameof(state), state.Scale, null); diff --git a/src/Ryujinx.Audio/Renderer/Parameter/EffectInParameterVersion1.cs b/src/Ryujinx.Audio/Renderer/Parameter/EffectInParameterVersion1.cs index 46686e3b4..73fea4c36 100644 --- a/src/Ryujinx.Audio/Renderer/Parameter/EffectInParameterVersion1.cs +++ b/src/Ryujinx.Audio/Renderer/Parameter/EffectInParameterVersion1.cs @@ -91,7 +91,7 @@ namespace Ryujinx.Audio.Renderer.Parameter /// Returns true if the channel count is valid. public static bool IsChannelCountValid(int channelCount) { - return channelCount == 1 || channelCount == 2 || channelCount == 4 || channelCount == 6; + return channelCount is 1 or 2 or 4 or 6; } } } diff --git a/src/Ryujinx.Audio/Renderer/Parameter/EffectInParameterVersion2.cs b/src/Ryujinx.Audio/Renderer/Parameter/EffectInParameterVersion2.cs index 3854c7148..779bc8fb7 100644 --- a/src/Ryujinx.Audio/Renderer/Parameter/EffectInParameterVersion2.cs +++ b/src/Ryujinx.Audio/Renderer/Parameter/EffectInParameterVersion2.cs @@ -91,7 +91,7 @@ namespace Ryujinx.Audio.Renderer.Parameter /// Returns true if the channel count is valid. public static bool IsChannelCountValid(int channelCount) { - return channelCount == 1 || channelCount == 2 || channelCount == 4 || channelCount == 6; + return channelCount is 1 or 2 or 4 or 6; } } } diff --git a/src/Ryujinx.Audio/Renderer/Server/AudioRenderSystem.cs b/src/Ryujinx.Audio/Renderer/Server/AudioRenderSystem.cs index 33082225a..ee2f23479 100644 --- a/src/Ryujinx.Audio/Renderer/Server/AudioRenderSystem.cs +++ b/src/Ryujinx.Audio/Renderer/Server/AudioRenderSystem.cs @@ -532,13 +532,13 @@ namespace Ryujinx.Audio.Renderer.Server CommandType commandType = command.CommandType; - if (commandType == CommandType.AdpcmDataSourceVersion1 || - commandType == CommandType.AdpcmDataSourceVersion2 || - commandType == CommandType.PcmInt16DataSourceVersion1 || - commandType == CommandType.PcmInt16DataSourceVersion2 || - commandType == CommandType.PcmFloatDataSourceVersion1 || - commandType == CommandType.PcmFloatDataSourceVersion2 || - commandType == CommandType.Performance) + if (commandType is CommandType.AdpcmDataSourceVersion1 or + CommandType.AdpcmDataSourceVersion2 or + CommandType.PcmInt16DataSourceVersion1 or + CommandType.PcmInt16DataSourceVersion2 or + CommandType.PcmFloatDataSourceVersion1 or + CommandType.PcmFloatDataSourceVersion2 or + CommandType.Performance) { break; } diff --git a/src/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs b/src/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs index 4c353b37e..d65897e45 100644 --- a/src/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs +++ b/src/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs @@ -467,7 +467,6 @@ namespace Ryujinx.Audio.Renderer.Server } } - /// /// Generate a new . /// diff --git a/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion2.cs b/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion2.cs index ef1326924..1e9b6c53e 100644 --- a/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion2.cs +++ b/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion2.cs @@ -20,7 +20,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(PerformanceCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -32,7 +32,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(ClearMixBufferCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); float costPerBuffer = 668.8f; float baseCost = 193.2f; @@ -48,7 +48,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(BiquadFilterCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -62,7 +62,7 @@ namespace Ryujinx.Audio.Renderer.Server { const float CostPerSample = 7.245f; - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); int volumeCount = 0; @@ -79,7 +79,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(MixRampCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -91,7 +91,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(DepopPrepareCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -103,7 +103,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(VolumeRampCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -115,7 +115,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(PcmInt16DataSourceCommandVersion1 command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); float costPerSample = 1195.5f; float baseCost = 7797.0f; @@ -131,7 +131,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(AdpcmDataSourceCommandVersion1 command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); float costPerSample = 3564.1f; float baseCost = 6225.5f; @@ -147,7 +147,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(DepopForMixBuffersCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -159,7 +159,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(CopyMixBufferCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -171,7 +171,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(MixCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -183,7 +183,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(DelayCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -234,7 +234,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(ReverbCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -285,7 +285,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(Reverb3dCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -335,7 +335,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(AuxiliaryBufferCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -357,7 +357,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(VolumeCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -369,7 +369,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(CircularBufferSinkCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); float costPerBuffer = 1726.0f; float baseCost = 1369.7f; @@ -385,7 +385,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(DownMixSurroundToStereoCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -397,7 +397,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(UpsampleCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -409,8 +409,8 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(DeviceSinkCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); - Debug.Assert(command.InputCount == 2 || command.InputCount == 6); + Debug.Assert(_sampleCount is 160 or 240); + Debug.Assert(command.InputCount is 2 or 6); if (command.InputCount == 2) { @@ -433,7 +433,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(PcmFloatDataSourceCommandVersion1 command) { // NOTE: This was added between REV7 and REV8 and for some reasons the estimator v2 was changed... - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); float costPerSample = 3490.9f; float baseCost = 10091.0f; diff --git a/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion3.cs b/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion3.cs index 31a5347b4..85e016019 100644 --- a/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion3.cs +++ b/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion3.cs @@ -23,7 +23,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(PerformanceCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -35,7 +35,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(ClearMixBufferCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); float costPerBuffer = 440.68f; float baseCost = 0; @@ -50,7 +50,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(BiquadFilterCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -64,7 +64,7 @@ namespace Ryujinx.Audio.Renderer.Server { float costPerSample = 6.4434f; - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -86,7 +86,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(MixRampCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -103,7 +103,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(VolumeRampCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -115,7 +115,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(PcmInt16DataSourceCommandVersion1 command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); float costPerSample = 710.143f; float baseCost = 7853.286f; @@ -131,7 +131,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(AdpcmDataSourceCommandVersion1 command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); float costPerSample = 3564.1f; float baseCost = 9736.702f; @@ -147,7 +147,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(DepopForMixBuffersCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -159,7 +159,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(CopyMixBufferCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -171,7 +171,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(MixCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -183,7 +183,7 @@ namespace Ryujinx.Audio.Renderer.Server public virtual uint Estimate(DelayCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -233,7 +233,7 @@ namespace Ryujinx.Audio.Renderer.Server public virtual uint Estimate(ReverbCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -283,7 +283,7 @@ namespace Ryujinx.Audio.Renderer.Server public virtual uint Estimate(Reverb3dCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -333,7 +333,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(AuxiliaryBufferCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -355,7 +355,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(VolumeCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -367,7 +367,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(CircularBufferSinkCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); float costPerBuffer = 770.26f; float baseCost = 0f; @@ -382,7 +382,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(DownMixSurroundToStereoCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -394,7 +394,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(UpsampleCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -406,8 +406,8 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(DeviceSinkCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); - Debug.Assert(command.InputCount == 2 || command.InputCount == 6); + Debug.Assert(SampleCount is 160 or 240); + Debug.Assert(command.InputCount is 2 or 6); if (command.InputCount == 2) { @@ -429,7 +429,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(PcmFloatDataSourceCommandVersion1 command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); float costPerSample = 3490.9f; float baseCost = 10090.9f; @@ -445,7 +445,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(DataSourceVersion2Command command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); (float baseCost, float costPerSample) = GetCostByFormat(SampleCount, command.SampleFormat, command.SrcQuality); @@ -454,7 +454,7 @@ namespace Ryujinx.Audio.Renderer.Server private static (float, float) GetCostByFormat(uint sampleCount, SampleFormat format, SampleRateConversionQuality quality) { - Debug.Assert(sampleCount == 160 || sampleCount == 240); + Debug.Assert(sampleCount is 160 or 240); switch (format) { @@ -546,7 +546,7 @@ namespace Ryujinx.Audio.Renderer.Server private uint EstimateLimiterCommandCommon(LimiterParameter parameter, bool enabled) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -596,14 +596,14 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(LimiterCommandVersion1 command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); return EstimateLimiterCommandCommon(command.Parameter, command.IsEffectEnabled); } public uint Estimate(LimiterCommandVersion2 command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (!command.Parameter.StatisticsEnabled || !command.IsEffectEnabled) { diff --git a/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion4.cs b/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion4.cs index fb357120d..3cb04e385 100644 --- a/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion4.cs +++ b/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion4.cs @@ -12,7 +12,7 @@ namespace Ryujinx.Audio.Renderer.Server public override uint Estimate(MultiTapBiquadFilterCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -24,7 +24,7 @@ namespace Ryujinx.Audio.Renderer.Server public override uint Estimate(CaptureBufferCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { diff --git a/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs b/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs index bc9ba073d..fe6103f2b 100644 --- a/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs +++ b/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs @@ -13,7 +13,7 @@ namespace Ryujinx.Audio.Renderer.Server public override uint Estimate(DelayCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -63,7 +63,7 @@ namespace Ryujinx.Audio.Renderer.Server public override uint Estimate(ReverbCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -113,7 +113,7 @@ namespace Ryujinx.Audio.Renderer.Server public override uint Estimate(Reverb3dCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -163,7 +163,7 @@ namespace Ryujinx.Audio.Renderer.Server public override uint Estimate(CompressorCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -241,7 +241,7 @@ namespace Ryujinx.Audio.Renderer.Server public override uint Estimate(BiquadFilterAndMixCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (command.HasVolumeRamp) { @@ -265,7 +265,7 @@ namespace Ryujinx.Audio.Renderer.Server public override uint Estimate(MultiTapBiquadFilterAndMixCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (command.HasVolumeRamp) { diff --git a/src/Ryujinx.Audio/Renderer/Server/MemoryPool/PoolMapper.cs b/src/Ryujinx.Audio/Renderer/Server/MemoryPool/PoolMapper.cs index f67d0c124..535e2fd79 100644 --- a/src/Ryujinx.Audio/Renderer/Server/MemoryPool/PoolMapper.cs +++ b/src/Ryujinx.Audio/Renderer/Server/MemoryPool/PoolMapper.cs @@ -257,7 +257,7 @@ namespace Ryujinx.Audio.Renderer.Server.MemoryPool const uint PageSize = 0x1000; - if (inputState != MemoryPoolUserState.RequestAttach && inputState != MemoryPoolUserState.RequestDetach) + if (inputState is not MemoryPoolUserState.RequestAttach and not MemoryPoolUserState.RequestDetach) { return UpdateResult.Success; } diff --git a/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion1.cs b/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion1.cs index ce8f33685..5b5242f0d 100644 --- a/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion1.cs +++ b/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion1.cs @@ -153,7 +153,7 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter /// The volume for the given destination. public float GetMixVolume(int destinationIndex) { - Debug.Assert(destinationIndex >= 0 && destinationIndex < Constants.MixBufferCountMax); + Debug.Assert(destinationIndex is >= 0 and < Constants.MixBufferCountMax); return MixBufferVolume[destinationIndex]; } @@ -165,7 +165,7 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter /// The volume for the given destination. public float GetMixVolumePrev(int destinationIndex) { - Debug.Assert(destinationIndex >= 0 && destinationIndex < Constants.MixBufferCountMax); + Debug.Assert(destinationIndex is >= 0 and < Constants.MixBufferCountMax); return PreviousMixBufferVolume[destinationIndex]; } diff --git a/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion2.cs b/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion2.cs index 5f96ef3aa..1a4a38e44 100644 --- a/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion2.cs +++ b/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion2.cs @@ -160,7 +160,7 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter /// The volume for the given destination. public float GetMixVolume(int destinationIndex) { - Debug.Assert(destinationIndex >= 0 && destinationIndex < Constants.MixBufferCountMax); + Debug.Assert(destinationIndex is >= 0 and < Constants.MixBufferCountMax); return MixBufferVolume[destinationIndex]; } @@ -172,7 +172,7 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter /// The volume for the given destination. public float GetMixVolumePrev(int destinationIndex) { - Debug.Assert(destinationIndex >= 0 && destinationIndex < Constants.MixBufferCountMax); + Debug.Assert(destinationIndex is >= 0 and < Constants.MixBufferCountMax); return PreviousMixBufferVolume[destinationIndex]; } diff --git a/src/Ryujinx.Audio/Renderer/Server/StateUpdater.cs b/src/Ryujinx.Audio/Renderer/Server/StateUpdater.cs index f8d87f2d1..9c4d1243a 100644 --- a/src/Ryujinx.Audio/Renderer/Server/StateUpdater.cs +++ b/src/Ryujinx.Audio/Renderer/Server/StateUpdater.cs @@ -86,9 +86,9 @@ namespace Ryujinx.Audio.Renderer.Server PoolMapper.UpdateResult updateResult = mapper.Update(ref memoryPool, in parameter, ref outStatus); - if (updateResult != PoolMapper.UpdateResult.Success && - updateResult != PoolMapper.UpdateResult.MapError && - updateResult != PoolMapper.UpdateResult.UnmapError) + if (updateResult is not PoolMapper.UpdateResult.Success and + not PoolMapper.UpdateResult.MapError and + not PoolMapper.UpdateResult.UnmapError) { if (updateResult != PoolMapper.UpdateResult.InvalidParameter) { diff --git a/src/Ryujinx.Audio/Renderer/Server/Voice/WaveBuffer.cs b/src/Ryujinx.Audio/Renderer/Server/Voice/WaveBuffer.cs index a9946ba44..1c76e7280 100644 --- a/src/Ryujinx.Audio/Renderer/Server/Voice/WaveBuffer.cs +++ b/src/Ryujinx.Audio/Renderer/Server/Voice/WaveBuffer.cs @@ -20,7 +20,6 @@ namespace Ryujinx.Audio.Renderer.Server.Voice /// Only used by . public AddressInfo ContextAddressInfo; - /// /// First sample to play of the wavebuffer. /// diff --git a/src/Ryujinx.BuildValidationTasks/LocalesValidationTask.cs b/src/Ryujinx.BuildValidationTasks/LocalesValidationTask.cs index bc2131035..17f9be5a0 100644 --- a/src/Ryujinx.BuildValidationTasks/LocalesValidationTask.cs +++ b/src/Ryujinx.BuildValidationTasks/LocalesValidationTask.cs @@ -1,14 +1,21 @@ using System; using System.Collections.Generic; -using System.Linq; using System.IO; -using System.Text.Json; +using System.Linq; using System.Text.Encodings.Web; +using System.Text.Json; namespace Ryujinx.BuildValidationTasks { public class LocalesValidationTask : IValidationTask { + static readonly JsonSerializerOptions _jsonOptions = new() + { + WriteIndented = true, + NewLine = "\n", + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping + }; + public LocalesValidationTask() { } public bool Execute(string projectPath, bool isGitRunner) @@ -38,8 +45,6 @@ namespace Ryujinx.BuildValidationTasks throw new JsonException(e.Message); //shorter and easier stacktrace } - - bool encounteredIssue = false; for (int i = 0; i < json.Locales.Count; i++) @@ -83,14 +88,7 @@ namespace Ryujinx.BuildValidationTasks if (isGitRunner && encounteredIssue) throw new JsonException("1 or more locales are invalid!"); - JsonSerializerOptions jsonOptions = new() - { - WriteIndented = true, - NewLine = "\n", - Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping - }; - - string jsonString = JsonSerializer.Serialize(json, jsonOptions); + string jsonString = JsonSerializer.Serialize(json, _jsonOptions); using (StreamWriter sw = new(path)) { diff --git a/src/Ryujinx.Common/Collections/IntervalTree.cs b/src/Ryujinx.Common/Collections/IntervalTree.cs index 695487dda..27503c5b7 100644 --- a/src/Ryujinx.Common/Collections/IntervalTree.cs +++ b/src/Ryujinx.Common/Collections/IntervalTree.cs @@ -122,7 +122,7 @@ namespace Ryujinx.Common.Collections /// /// The node to search for RangeNodes within /// The list to add RangeNodes to - private void AddToList(IntervalTreeNode node, List> list) + private static void AddToList(IntervalTreeNode node, List> list) { if (node == null) { @@ -163,6 +163,7 @@ namespace Ryujinx.Common.Collections return node; } } + return null; } @@ -173,7 +174,7 @@ namespace Ryujinx.Common.Collections /// End of the range /// Overlaps array to place results in /// Overlaps count to update - private void GetValues(IntervalTreeNode node, TKey start, TKey end, ref TValue[] overlaps, ref int overlapCount) + private static void GetValues(IntervalTreeNode node, TKey start, TKey end, ref TValue[] overlaps, ref int overlapCount) { if (node == null || start.CompareTo(node.Max) >= 0) { @@ -313,6 +314,7 @@ namespace Ryujinx.Common.Collections return node; } } + IntervalTreeNode newNode = new(start, end, value, parent); if (newNode.Parent == null) { diff --git a/src/Ryujinx.Common/Collections/IntrusiveRedBlackTree.cs b/src/Ryujinx.Common/Collections/IntrusiveRedBlackTree.cs index 9e56f707b..423cd22c8 100644 --- a/src/Ryujinx.Common/Collections/IntrusiveRedBlackTree.cs +++ b/src/Ryujinx.Common/Collections/IntrusiveRedBlackTree.cs @@ -64,6 +64,7 @@ namespace Ryujinx.Common.Collections return node; } } + return null; } @@ -112,6 +113,7 @@ namespace Ryujinx.Common.Collections return node; } } + newNode.Parent = parent; if (parent == null) { @@ -125,6 +127,7 @@ namespace Ryujinx.Common.Collections { parent.Right = newNode; } + Count++; return newNode; } @@ -274,6 +277,7 @@ namespace Ryujinx.Common.Collections return node; } } + return null; } } diff --git a/src/Ryujinx.Common/Collections/IntrusiveRedBlackTreeImpl.cs b/src/Ryujinx.Common/Collections/IntrusiveRedBlackTreeImpl.cs index 49f97223a..abd3723fe 100644 --- a/src/Ryujinx.Common/Collections/IntrusiveRedBlackTreeImpl.cs +++ b/src/Ryujinx.Common/Collections/IntrusiveRedBlackTreeImpl.cs @@ -39,12 +39,14 @@ namespace Ryujinx.Common.Collections { return Minimum(node.Right); } + T parent = node.Parent; while (parent != null && node == parent.Right) { node = parent; parent = parent.Parent; } + return parent; } @@ -59,12 +61,14 @@ namespace Ryujinx.Common.Collections { return Maximum(node.Left); } + T parent = node.Parent; while (parent != null && node == parent.Left) { node = parent; parent = parent.Parent; } + return parent; } @@ -120,6 +124,7 @@ namespace Ryujinx.Common.Collections RotateLeft(ParentOf(ptr)); sibling = RightOf(ParentOf(ptr)); } + if (ColorOf(LeftOf(sibling)) == Black && ColorOf(RightOf(sibling)) == Black) { SetColor(sibling, Red); @@ -134,6 +139,7 @@ namespace Ryujinx.Common.Collections RotateRight(sibling); sibling = RightOf(ParentOf(ptr)); } + SetColor(sibling, ColorOf(ParentOf(ptr))); SetColor(ParentOf(ptr), Black); SetColor(RightOf(sibling), Black); @@ -152,6 +158,7 @@ namespace Ryujinx.Common.Collections RotateRight(ParentOf(ptr)); sibling = LeftOf(ParentOf(ptr)); } + if (ColorOf(RightOf(sibling)) == Black && ColorOf(LeftOf(sibling)) == Black) { SetColor(sibling, Red); @@ -166,6 +173,7 @@ namespace Ryujinx.Common.Collections RotateLeft(sibling); sibling = LeftOf(ParentOf(ptr)); } + SetColor(sibling, ColorOf(ParentOf(ptr))); SetColor(ParentOf(ptr), Black); SetColor(LeftOf(sibling), Black); @@ -174,6 +182,7 @@ namespace Ryujinx.Common.Collections } } } + SetColor(ptr, Black); } @@ -200,6 +209,7 @@ namespace Ryujinx.Common.Collections balanceNode = ParentOf(balanceNode); RotateLeft(balanceNode); } + SetColor(ParentOf(balanceNode), Black); SetColor(ParentOf(ParentOf(balanceNode)), Red); RotateRight(ParentOf(ParentOf(balanceNode))); @@ -223,12 +233,14 @@ namespace Ryujinx.Common.Collections balanceNode = ParentOf(balanceNode); RotateRight(balanceNode); } + SetColor(ParentOf(balanceNode), Black); SetColor(ParentOf(ParentOf(balanceNode)), Red); RotateLeft(ParentOf(ParentOf(balanceNode))); } } } + SetColor(Root, Black); } @@ -242,6 +254,7 @@ namespace Ryujinx.Common.Collections { node.Right.Parent = node; } + T nodeParent = ParentOf(node); right.Parent = nodeParent; if (nodeParent == null) @@ -256,6 +269,7 @@ namespace Ryujinx.Common.Collections { nodeParent.Right = right; } + right.Left = node; node.Parent = right; } @@ -271,6 +285,7 @@ namespace Ryujinx.Common.Collections { node.Left.Parent = node; } + T nodeParent = ParentOf(node); left.Parent = nodeParent; if (nodeParent == null) @@ -285,6 +300,7 @@ namespace Ryujinx.Common.Collections { nodeParent.Left = left; } + left.Right = node; node.Parent = left; } diff --git a/src/Ryujinx.Common/Collections/TreeDictionary.cs b/src/Ryujinx.Common/Collections/TreeDictionary.cs index 18f48188a..af104d268 100644 --- a/src/Ryujinx.Common/Collections/TreeDictionary.cs +++ b/src/Ryujinx.Common/Collections/TreeDictionary.cs @@ -78,6 +78,7 @@ namespace Ryujinx.Common.Collections { return node.Key; } + return default; } @@ -94,6 +95,7 @@ namespace Ryujinx.Common.Collections { return node.Key; } + return default; } @@ -111,6 +113,7 @@ namespace Ryujinx.Common.Collections return successor != null ? successor.Key : default; } + return default; } @@ -128,6 +131,7 @@ namespace Ryujinx.Common.Collections return predecessor != null ? predecessor.Key : default; } + return default; } @@ -147,6 +151,7 @@ namespace Ryujinx.Common.Collections { nodes.Enqueue(this.Root); } + while (nodes.TryDequeue(out Node node)) { list.Add(new KeyValuePair(node.Key, node.Value)); @@ -154,11 +159,13 @@ namespace Ryujinx.Common.Collections { nodes.Enqueue(node.Left); } + if (node.Right != null) { nodes.Enqueue(node.Right); } } + return list; } @@ -184,7 +191,7 @@ namespace Ryujinx.Common.Collections /// /// The node to search for nodes within /// The list to add node to - private void AddToList(Node node, List> list) + private static void AddToList(Node node, List> list) { if (node == null) { @@ -225,6 +232,7 @@ namespace Ryujinx.Common.Collections return node; } } + return null; } @@ -274,6 +282,7 @@ namespace Ryujinx.Common.Collections return node; } } + Node newNode = new(key, value, parent); if (newNode.Parent == null) { @@ -287,6 +296,7 @@ namespace Ryujinx.Common.Collections { parent.Right = newNode; } + Count++; return newNode; } @@ -392,6 +402,7 @@ namespace Ryujinx.Common.Collections ptr = parent; parent = parent.Parent; } + return parent; } } @@ -400,6 +411,7 @@ namespace Ryujinx.Common.Collections return tmp; } } + return null; } @@ -444,6 +456,7 @@ namespace Ryujinx.Common.Collections ptr = parent; parent = parent.Parent; } + return parent; } } @@ -452,6 +465,7 @@ namespace Ryujinx.Common.Collections return tmp; } } + return null; } @@ -502,6 +516,7 @@ namespace Ryujinx.Common.Collections { return node.Key.Equals(item.Key) && node.Value.Equals(item.Value); } + return false; } @@ -588,6 +603,7 @@ namespace Ryujinx.Common.Collections { queue.Enqueue(node.Left); } + if (null != node.Right) { queue.Enqueue(node.Right); diff --git a/src/Ryujinx.Common/Configuration/AppDataManager.cs b/src/Ryujinx.Common/Configuration/AppDataManager.cs index ca8e389ba..cb26be2d5 100644 --- a/src/Ryujinx.Common/Configuration/AppDataManager.cs +++ b/src/Ryujinx.Common/Configuration/AppDataManager.cs @@ -280,6 +280,7 @@ namespace Ryujinx.Common.Configuration { Logger.Error?.Print(LogClass.Application, $"Unable to resolve the symlink for Ryujinx application data: {symlinkException}. Follow the symlink at {correctApplicationDataDirectoryPath} and move your data back to the Application Support folder."); } + return; } @@ -304,6 +305,7 @@ namespace Ryujinx.Common.Configuration { Logger.Error?.Print(LogClass.Application, $"Unable to resolve the symlink for Ryujinx application data: {symlinkException}. Follow the symlink at {correctApplicationDataDirectoryPath} and move your data back to the Application Support folder."); } + return; } diff --git a/src/Ryujinx.Common/Configuration/AspectRatioExtensions.cs b/src/Ryujinx.Common/Configuration/AspectRatioExtensions.cs index 05dbe67d9..f3a9e1646 100644 --- a/src/Ryujinx.Common/Configuration/AspectRatioExtensions.cs +++ b/src/Ryujinx.Common/Configuration/AspectRatioExtensions.cs @@ -35,8 +35,8 @@ namespace Ryujinx.Common.Configuration #pragma warning restore IDE0055 }; } - - + + public static float ToFloatY(this AspectRatio aspectRatio) { diff --git a/src/Ryujinx.Common/Configuration/DirtyHack.cs b/src/Ryujinx.Common/Configuration/DirtyHack.cs index 71ac88f56..ae3416a27 100644 --- a/src/Ryujinx.Common/Configuration/DirtyHack.cs +++ b/src/Ryujinx.Common/Configuration/DirtyHack.cs @@ -1,4 +1,4 @@ -using Gommon; +using Gommon; using System; using System.Collections.Generic; using System.Linq; @@ -17,9 +17,9 @@ namespace Ryujinx.Common.Configuration { public DirtyHack Hack => hack; public int Value => value; - - - + + + public ulong Pack() => Raw.PackBitFields(PackedFormat); public static EnabledDirtyHack Unpack(ulong packedHack) @@ -28,26 +28,26 @@ namespace Ryujinx.Common.Configuration // ReSharper disable once PatternAlwaysMatches if (unpackedFields is not [uint hack, uint value]) throw new Exception("The unpack operation on the integer resulted in an invalid unpacked result."); - + return new EnabledDirtyHack((DirtyHack)hack, (int)value); } - + private uint[] Raw => [(uint)Hack, (uint)Value.CoerceAtLeast(0)]; - + public static readonly byte[] PackedFormat = [8, 32]; } public class DirtyHacks : Dictionary { - public DirtyHacks(IEnumerable hacks) + public DirtyHacks(IEnumerable hacks) => hacks.ForEach(edh => Add(edh.Hack, edh.Value)); - public DirtyHacks(ulong[] packedHacks) : this(packedHacks.Select(EnabledDirtyHack.Unpack)) {} + public DirtyHacks(ulong[] packedHacks) : this(packedHacks.Select(EnabledDirtyHack.Unpack)) { } - public ulong[] PackEntries() + public ulong[] PackEntries() => Entries.Select(it => it.Pack()).ToArray(); - - public EnabledDirtyHack[] Entries + + public EnabledDirtyHack[] Entries => this .Select(it => new EnabledDirtyHack(it.Key, it.Value)) .ToArray(); diff --git a/src/Ryujinx.Common/Configuration/Hid/Controller/GenericControllerInputConfig.cs b/src/Ryujinx.Common/Configuration/Hid/Controller/GenericControllerInputConfig.cs index fbb19767c..c99da6f4a 100644 --- a/src/Ryujinx.Common/Configuration/Hid/Controller/GenericControllerInputConfig.cs +++ b/src/Ryujinx.Common/Configuration/Hid/Controller/GenericControllerInputConfig.cs @@ -78,7 +78,7 @@ namespace Ryujinx.Common.Configuration.Hid.Controller /// Controller Rumble Settings /// public RumbleConfigController Rumble { get; set; } - + /// /// Controller LED Settings /// diff --git a/src/Ryujinx.Common/Configuration/Hid/Controller/JoyconConfigControllerStick.cs b/src/Ryujinx.Common/Configuration/Hid/Controller/JoyconConfigControllerStick.cs index 076530744..70af4071d 100644 --- a/src/Ryujinx.Common/Configuration/Hid/Controller/JoyconConfigControllerStick.cs +++ b/src/Ryujinx.Common/Configuration/Hid/Controller/JoyconConfigControllerStick.cs @@ -1,7 +1,7 @@ namespace Ryujinx.Common.Configuration.Hid.Controller { - public class JoyconConfigControllerStick - where TButton : unmanaged + public class JoyconConfigControllerStick + where TButton : unmanaged where TStick : unmanaged { public TStick Joystick { get; set; } diff --git a/src/Ryujinx.Common/Configuration/Hid/Controller/LedConfigController.cs b/src/Ryujinx.Common/Configuration/Hid/Controller/LedConfigController.cs index 93b75d32c..5edeff0ac 100644 --- a/src/Ryujinx.Common/Configuration/Hid/Controller/LedConfigController.cs +++ b/src/Ryujinx.Common/Configuration/Hid/Controller/LedConfigController.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Common.Configuration.Hid.Controller +namespace Ryujinx.Common.Configuration.Hid.Controller { public class LedConfigController { @@ -6,17 +6,17 @@ /// Enable LED color changing by the emulator /// public bool EnableLed { get; set; } - + /// /// Ignores the color and disables the LED entirely. /// public bool TurnOffLed { get; set; } - + /// /// Ignores the color and uses the rainbow color functionality for the LED. /// public bool UseRainbow { get; set; } - + /// /// Packed RGB int of the color /// diff --git a/src/Ryujinx.Common/Configuration/VSyncMode.cs b/src/Ryujinx.Common/Configuration/VSyncMode.cs index e0bf2591f..21505bf2a 100644 --- a/src/Ryujinx.Common/Configuration/VSyncMode.cs +++ b/src/Ryujinx.Common/Configuration/VSyncMode.cs @@ -6,7 +6,7 @@ namespace Ryujinx.Common.Configuration Unbounded, Custom } - + public static class VSyncModeExtensions { public static VSyncMode Next(this VSyncMode vsync, bool customEnabled = false) => diff --git a/src/Ryujinx.Common/GraphicsDriver/NVAPI/NvapiUnicodeString.cs b/src/Ryujinx.Common/GraphicsDriver/NVAPI/NvapiUnicodeString.cs index f3e0ffd02..5b0992dce 100644 --- a/src/Ryujinx.Common/GraphicsDriver/NVAPI/NvapiUnicodeString.cs +++ b/src/Ryujinx.Common/GraphicsDriver/NVAPI/NvapiUnicodeString.cs @@ -22,7 +22,7 @@ namespace Ryujinx.Common.GraphicsDriver.NVAPI int index = text.IndexOf('\0'); if (index > -1) { - text = text.Remove(index); + text = text[..index]; } return text; diff --git a/src/Ryujinx.Common/Hash128.cs b/src/Ryujinx.Common/Hash128.cs index baee3e7d2..e95a15caa 100644 --- a/src/Ryujinx.Common/Hash128.cs +++ b/src/Ryujinx.Common/Hash128.cs @@ -528,7 +528,7 @@ namespace Ryujinx.Common private static Hash128 Xxh3Len1To3128b(ReadOnlySpan input, ReadOnlySpan secret, ulong seed) { - Debug.Assert(1 <= input.Length && input.Length <= 3); + Debug.Assert(input.Length is >= 1 and <= 3); byte c1 = input[0]; byte c2 = input[input.Length >> 1]; @@ -550,7 +550,7 @@ namespace Ryujinx.Common private static Hash128 Xxh3Len4To8128b(ReadOnlySpan input, ReadOnlySpan secret, ulong seed) { - Debug.Assert(4 <= input.Length && input.Length <= 8); + Debug.Assert(input.Length is >= 4 and <= 8); seed ^= BinaryPrimitives.ReverseEndianness((uint)seed) << 32; @@ -575,7 +575,7 @@ namespace Ryujinx.Common private static Hash128 Xxh3Len9To16128b(ReadOnlySpan input, ReadOnlySpan secret, ulong seed) { - Debug.Assert(9 <= input.Length && input.Length <= 16); + Debug.Assert(input.Length is >= 9 and <= 16); ulong bitFlipL = (BinaryPrimitives.ReadUInt64LittleEndian(secret[32..]) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret[40..])) - seed; ulong bitFlipH = (BinaryPrimitives.ReadUInt64LittleEndian(secret[48..]) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret[56..])) + seed; @@ -647,7 +647,7 @@ namespace Ryujinx.Common private static Hash128 Xxh3Len17To128128b(ReadOnlySpan input, ReadOnlySpan secret, ulong seed) { Debug.Assert(secret.Length >= SecretSizeMin); - Debug.Assert(16 < input.Length && input.Length <= 128); + Debug.Assert(input.Length is > 16 and <= 128); Hash128 acc = new() { @@ -663,10 +663,13 @@ namespace Ryujinx.Common { acc = Xxh128Mix32b(acc, input[48..], input[^64..], secret[96..], seed); } + acc = Xxh128Mix32b(acc, input[32..], input[^48..], secret[64..], seed); } + acc = Xxh128Mix32b(acc, input[16..], input[^32..], secret[32..], seed); } + acc = Xxh128Mix32b(acc, input, input[^16..], secret, seed); Hash128 h128 = new() @@ -683,7 +686,7 @@ namespace Ryujinx.Common private static Hash128 Xxh3Len129To240128b(ReadOnlySpan input, ReadOnlySpan secret, ulong seed) { Debug.Assert(secret.Length >= SecretSizeMin); - Debug.Assert(128 < input.Length && input.Length <= 240); + Debug.Assert(input.Length is > 128 and <= 240); Hash128 acc = new(); diff --git a/src/Ryujinx.Common/Helpers/ConsoleHelper.cs b/src/Ryujinx.Common/Helpers/ConsoleHelper.cs index 105c9881e..2b3c11b1e 100644 --- a/src/Ryujinx.Common/Helpers/ConsoleHelper.cs +++ b/src/Ryujinx.Common/Helpers/ConsoleHelper.cs @@ -19,7 +19,7 @@ namespace Ryujinx.Common.Helper [SupportedOSPlatform("windows")] [LibraryImport("user32")] private static partial nint GetForegroundWindow(); - + [SupportedOSPlatform("windows")] [LibraryImport("user32")] [return: MarshalAs(UnmanagedType.Bool)] diff --git a/src/Ryujinx.Common/Helpers/FileAssociationHelper.cs b/src/Ryujinx.Common/Helpers/FileAssociationHelper.cs index 6e14a796e..b61dd8ee2 100644 --- a/src/Ryujinx.Common/Helpers/FileAssociationHelper.cs +++ b/src/Ryujinx.Common/Helpers/FileAssociationHelper.cs @@ -23,7 +23,7 @@ namespace Ryujinx.Common.Helper public static partial void SHChangeNotify(uint wEventId, uint uFlags, nint dwItem1, nint dwItem2); public static bool IsTypeAssociationSupported => (OperatingSystem.IsLinux() || OperatingSystem.IsWindows()); - + public static bool AreMimeTypesRegistered { get @@ -92,21 +92,21 @@ namespace Ryujinx.Common.Helper [SupportedOSPlatform("windows")] private static bool AreMimeTypesRegisteredWindows() { - return _fileExtensions.Aggregate(false, + return _fileExtensions.Aggregate(false, (current, ext) => current | CheckRegistering(ext) ); - + static bool CheckRegistering(string ext) { RegistryKey key = Registry.CurrentUser.OpenSubKey(@$"Software\Classes\{ext}"); RegistryKey openCmd = key?.OpenSubKey(@"shell\open\command"); - + if (openCmd is null) { return false; } - + string keyValue = (string)openCmd.GetValue(string.Empty); return keyValue is not null && (keyValue.Contains("Ryujinx") || keyValue.Contains(AppDomain.CurrentDomain.FriendlyName)); @@ -116,7 +116,7 @@ namespace Ryujinx.Common.Helper [SupportedOSPlatform("windows")] private static bool InstallWindowsMimeTypes(bool uninstall = false) { - bool registered = _fileExtensions.Aggregate(false, + bool registered = _fileExtensions.Aggregate(false, (current, ext) => current | RegisterExtension(ext, uninstall) ); @@ -124,7 +124,7 @@ namespace Ryujinx.Common.Helper SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSH, nint.Zero, nint.Zero); return registered; - + static bool RegisterExtension(string ext, bool uninstall = false) { string keyString = @$"Software\Classes\{ext}"; @@ -136,6 +136,7 @@ namespace Ryujinx.Common.Helper { return true; } + Logger.Debug?.Print(LogClass.Application, $"Removing type association {ext}"); Registry.CurrentUser.DeleteSubKeyTree(keyString); Logger.Debug?.Print(LogClass.Application, $"Removed type association {ext}"); diff --git a/src/Ryujinx.Common/Helpers/Patterns.cs b/src/Ryujinx.Common/Helpers/Patterns.cs index 84cc1353a..56b555f48 100644 --- a/src/Ryujinx.Common/Helpers/Patterns.cs +++ b/src/Ryujinx.Common/Helpers/Patterns.cs @@ -1,4 +1,4 @@ -using System.Text.RegularExpressions; +using System.Text.RegularExpressions; namespace Ryujinx.Common.Helper { @@ -9,6 +9,7 @@ namespace Ryujinx.Common.Helper public static readonly Regex Numeric = NumericRegex(); public static readonly Regex AmdGcn = AmdGcnRegex(); + public static readonly Regex AmdRdna3 = AmdRdna3Regex(); public static readonly Regex NvidiaConsumerClass = NvidiaConsumerClassRegex(); public static readonly Regex DomainLp1Ns = DomainLp1NsRegex(); @@ -46,6 +47,9 @@ namespace Ryujinx.Common.Helper "Radeon (((HD|R(5|7|9|X)) )?((M?[2-6]\\d{2}(\\D|$))|([7-8]\\d{3}(\\D|$))|Fury|Nano))|(Pro Duo)")] internal static partial Regex AmdGcnRegex(); + [GeneratedRegex("Radeon ([7-8](\\d{2}\\d?)[MS]|PRO [VW]7(\\d{2}\\d?)|RX 7\\d{3}([MS]?| XTX?| GRE)?)")] + public static partial Regex AmdRdna3Regex(); + [GeneratedRegex("NVIDIA GeForce (R|G)?TX? (\\d{3}\\d?)M?")] internal static partial Regex NvidiaConsumerClassRegex(); diff --git a/src/Ryujinx.Common/Helpers/RefEvent.cs b/src/Ryujinx.Common/Helpers/RefEvent.cs index f339dfb7c..5487135ce 100644 --- a/src/Ryujinx.Common/Helpers/RefEvent.cs +++ b/src/Ryujinx.Common/Helpers/RefEvent.cs @@ -1,4 +1,4 @@ -using Gommon; +using Gommon; using System.Collections.Generic; using System.Threading; @@ -7,10 +7,10 @@ namespace Ryujinx.Common.Helper public class RefEvent { public delegate void Handler(ref T arg); - + private readonly Lock _subLock = new(); private readonly List _subscriptions = []; - + public bool HasSubscribers { get diff --git a/src/Ryujinx.Common/Helpers/RunningPlatform.cs b/src/Ryujinx.Common/Helpers/RunningPlatform.cs index 7ec2f18df..8bc7f65aa 100644 --- a/src/Ryujinx.Common/Helpers/RunningPlatform.cs +++ b/src/Ryujinx.Common/Helpers/RunningPlatform.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Runtime.InteropServices; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable InconsistentNaming @@ -9,14 +9,14 @@ namespace Ryujinx.Common.Helper { MacOS, Linux, - Windows + Windows } - + public static class RunningPlatform { - public static readonly OperatingSystemType CurrentOS - = IsMacOS - ? OperatingSystemType.MacOS + public static readonly OperatingSystemType CurrentOS + = IsMacOS + ? OperatingSystemType.MacOS : IsWindows ? OperatingSystemType.Windows : IsLinux @@ -25,21 +25,21 @@ namespace Ryujinx.Common.Helper public static Architecture Architecture => RuntimeInformation.OSArchitecture; public static Architecture CurrentProcessArchitecture => RuntimeInformation.ProcessArchitecture; - + public static bool IsMacOS => OperatingSystem.IsMacOS(); public static bool IsWindows => OperatingSystem.IsWindows(); public static bool IsLinux => OperatingSystem.IsLinux(); - + public static bool IsArm => Architecture is Architecture.Arm64; - + public static bool IsX64 => Architecture is Architecture.X64; public static bool IsIntelMac => IsMacOS && IsX64; public static bool IsArmMac => IsMacOS && IsArm; - + public static bool IsX64Windows => IsWindows && IsX64; public static bool IsArmWindows => IsWindows && IsArm; - + public static bool IsX64Linux => IsLinux && IsX64; public static bool IsArmLinux => IsLinux && IsArmMac; } diff --git a/src/Ryujinx.Common/Logging/Logger.cs b/src/Ryujinx.Common/Logging/Logger.cs index 1830c14df..e6f68599a 100644 --- a/src/Ryujinx.Common/Logging/Logger.cs +++ b/src/Ryujinx.Common/Logging/Logger.cs @@ -158,7 +158,7 @@ namespace Ryujinx.Common.Logging _time.Restart(); } - private static ILogTarget GetTarget(string targetName) + private static ILogTarget GetTarget(string targetName) => _logTargets.FirstOrDefault(target => target.Name.Equals(targetName)); public static void AddTarget(ILogTarget target) diff --git a/src/Ryujinx.Common/Logging/Targets/ConsoleLogTarget.cs b/src/Ryujinx.Common/Logging/Targets/ConsoleLogTarget.cs index 42ba00cd5..391cc5131 100644 --- a/src/Ryujinx.Common/Logging/Targets/ConsoleLogTarget.cs +++ b/src/Ryujinx.Common/Logging/Targets/ConsoleLogTarget.cs @@ -5,7 +5,7 @@ namespace Ryujinx.Common.Logging.Targets { public class ConsoleLogTarget : ILogTarget { - private readonly ILogFormatter _formatter; + private readonly DefaultLogFormatter _formatter; private readonly string _name; diff --git a/src/Ryujinx.Common/Logging/Targets/FileLogTarget.cs b/src/Ryujinx.Common/Logging/Targets/FileLogTarget.cs index 94e9359c8..181bd489a 100644 --- a/src/Ryujinx.Common/Logging/Targets/FileLogTarget.cs +++ b/src/Ryujinx.Common/Logging/Targets/FileLogTarget.cs @@ -8,7 +8,7 @@ namespace Ryujinx.Common.Logging.Targets public class FileLogTarget : ILogTarget { private readonly StreamWriter _logWriter; - private readonly ILogFormatter _formatter; + private readonly DefaultLogFormatter _formatter; private readonly string _name; string ILogTarget.Name { get => _name; } diff --git a/src/Ryujinx.Common/PreciseSleep/NanosleepEvent.cs b/src/Ryujinx.Common/PreciseSleep/NanosleepEvent.cs index f54fb09c1..962bc2a51 100644 --- a/src/Ryujinx.Common/PreciseSleep/NanosleepEvent.cs +++ b/src/Ryujinx.Common/PreciseSleep/NanosleepEvent.cs @@ -54,6 +54,7 @@ namespace Ryujinx.Common.PreciseSleep // Too many threads on the pool. return false; } + _waitEvent.WaitOne(1); _pool.IgnoreSignal(); diff --git a/src/Ryujinx.Common/ReactiveObject.cs b/src/Ryujinx.Common/ReactiveObject.cs index bb2ece81c..0e807eb7a 100644 --- a/src/Ryujinx.Common/ReactiveObject.cs +++ b/src/Ryujinx.Common/ReactiveObject.cs @@ -42,8 +42,8 @@ namespace Ryujinx.Common } } } - - public void LogChangesToValue(string valueName, LogClass logClass = LogClass.Configuration) + + public void LogChangesToValue(string valueName, LogClass logClass = LogClass.Configuration) => Event += (_, e) => ReactiveObjectHelper.LogValueChange(logClass, e, valueName); public static implicit operator T(ReactiveObject obj) => obj.Value; @@ -55,12 +55,12 @@ namespace Ryujinx.Common { if (eventArgs.AreValuesEqual) return; - + string message = string.Create(CultureInfo.InvariantCulture, $"{valueName} set to: {eventArgs.NewValue}"); Logger.Info?.Print(logClass, message); } - + public static void Toggle(this ReactiveObject rBoolean) => rBoolean.Value = !rBoolean.Value; } @@ -78,7 +78,7 @@ namespace Ryujinx.Common if (OldValue == null && NewValue != null) return false; - + if (OldValue != null && NewValue == null) return false; diff --git a/src/Ryujinx.Common/ReleaseInformation.cs b/src/Ryujinx.Common/ReleaseInformation.cs index b539caa6e..a5beb1009 100644 --- a/src/Ryujinx.Common/ReleaseInformation.cs +++ b/src/Ryujinx.Common/ReleaseInformation.cs @@ -1,6 +1,7 @@ using Ryujinx.Common.Utilities; using System; using System.Net.Http; +using System.Net.Http.Json; using System.Reflection; using System.Text.Json.Serialization; using System.Threading.Tasks; @@ -14,83 +15,28 @@ namespace Ryujinx.Common private const string ReleaseChannel = "release"; private const string BuildVersion = "%%RYUJINX_BUILD_VERSION%%"; - public const string BuildGitHash = "%%RYUJINX_BUILD_GIT_HASH%%"; + private const string BuildGitHash = "%%RYUJINX_BUILD_GIT_HASH%%"; private const string ReleaseChannelName = "%%RYUJINX_TARGET_RELEASE_CHANNEL_NAME%%"; private const string ConfigFileName = "%%RYUJINX_CONFIG_FILE_NAME%%"; - public const string ReleaseChannelOwner = "%%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER%%"; - public const string ReleaseChannelSourceRepo = "%%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO%%"; - public const string ReleaseChannelRepo = "%%RYUJINX_TARGET_RELEASE_CHANNEL_REPO%%"; - public static string ConfigName => !ConfigFileName.StartsWith("%%") ? ConfigFileName : "Config.json"; public static bool IsValid => !BuildGitHash.StartsWith("%%") && !ReleaseChannelName.StartsWith("%%") && - !ReleaseChannelOwner.StartsWith("%%") && - !ReleaseChannelSourceRepo.StartsWith("%%") && - !ReleaseChannelRepo.StartsWith("%%") && !ConfigFileName.StartsWith("%%"); public static bool IsCanaryBuild => IsValid && ReleaseChannelName.Equals(CanaryChannel); - + public static bool IsReleaseBuild => IsValid && ReleaseChannelName.Equals(ReleaseChannel); public static string Version => IsValid ? BuildVersion : Assembly.GetEntryAssembly()!.GetCustomAttribute()?.InformationalVersion; - public static string GetChangelogUrl(Version currentVersion, Version newVersion, ReleaseChannels.Channel releaseChannel) => - IsCanaryBuild + public static string GetChangelogUrl(Version currentVersion, Version newVersion) => + IsCanaryBuild ? $"https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-{currentVersion}...Canary-{newVersion}" - : GetChangelogForVersion(newVersion, releaseChannel); - - public static string GetChangelogForVersion(Version version, ReleaseChannels.Channel releaseChannel) => - $"https://github.com/{releaseChannel}/releases/{version}"; - - public static async Task GetReleaseChannelsAsync(HttpClient httpClient) - { - ReleaseChannelPair releaseChannelPair = JsonHelper.Deserialize(await httpClient.GetStringAsync("https://ryujinx.app/api/release-channels"), ReleaseChannelPairContext.Default.ReleaseChannelPair); - return new ReleaseChannels(releaseChannelPair); - } + : $"https://git.ryujinx.app/ryubing/ryujinx/-/releases/{newVersion}"; } - public readonly struct ReleaseChannels - { - internal ReleaseChannels(ReleaseChannelPair channelPair) - { - Stable = new Channel(channelPair.Stable); - Canary = new Channel(channelPair.Canary); - } - public readonly Channel Stable; - public readonly Channel Canary; - - public readonly struct Channel - { - public Channel(string raw) - { - string[] parts = raw.Split('/'); - Owner = parts[0]; - Repo = parts[1]; - } - - public readonly string Owner; - public readonly string Repo; - - public override string ToString() => $"{Owner}/{Repo}"; - - public string GetLatestReleaseApiUrl() => - $"https://api.github.com/repos/{ToString()}/releases/latest"; - } - } - - [JsonSerializable(typeof(ReleaseChannelPair))] - partial class ReleaseChannelPairContext : JsonSerializerContext; - - class ReleaseChannelPair - { - [JsonPropertyName("stable")] - public string Stable { get; set; } - [JsonPropertyName("canary")] - public string Canary { get; set; } - } } diff --git a/src/Ryujinx.Common/Ryujinx.Common.csproj b/src/Ryujinx.Common/Ryujinx.Common.csproj index de163aae7..e31d2f3bc 100644 --- a/src/Ryujinx.Common/Ryujinx.Common.csproj +++ b/src/Ryujinx.Common/Ryujinx.Common.csproj @@ -4,6 +4,7 @@ true $(DefineConstants);$(ExtraDefineConstants) $(DefaultItemExcludes);._* + true diff --git a/src/Ryujinx.Common/RyujinxException.cs b/src/Ryujinx.Common/RyujinxException.cs index dbb5184e4..590072a5d 100644 --- a/src/Ryujinx.Common/RyujinxException.cs +++ b/src/Ryujinx.Common/RyujinxException.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Ryujinx.Common { diff --git a/src/Ryujinx.Common/SharedConstants.cs b/src/Ryujinx.Common/SharedConstants.cs index f40afeb2b..fe7814c67 100644 --- a/src/Ryujinx.Common/SharedConstants.cs +++ b/src/Ryujinx.Common/SharedConstants.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Common +namespace Ryujinx.Common { public static class SharedConstants { diff --git a/src/Ryujinx.Common/SystemInterop/ForceDpiAware.cs b/src/Ryujinx.Common/SystemInterop/ForceDpiAware.cs index 330638171..a89dcd1ad 100644 --- a/src/Ryujinx.Common/SystemInterop/ForceDpiAware.cs +++ b/src/Ryujinx.Common/SystemInterop/ForceDpiAware.cs @@ -57,7 +57,7 @@ namespace Ryujinx.Common.SystemInterop { string xdgSessionType = Environment.GetEnvironmentVariable("XDG_SESSION_TYPE")?.ToLower(); - if (xdgSessionType == null || xdgSessionType == "x11") + if (xdgSessionType is null or "x11") { nint display = XOpenDisplay(null); string dpiString = Marshal.PtrToStringAnsi(XGetDefault(display, "Xft", "dpi")); @@ -65,6 +65,7 @@ namespace Ryujinx.Common.SystemInterop { userDpiScale = XDisplayWidth(display, 0) * 25.4 / XDisplayWidthMM(display, 0); } + _ = XCloseDisplay(display); } else if (xdgSessionType == "wayland") diff --git a/src/Ryujinx.Common/SystemInterop/StdErrAdapter.cs b/src/Ryujinx.Common/SystemInterop/StdErrAdapter.cs index a04c404d8..4936cd874 100644 --- a/src/Ryujinx.Common/SystemInterop/StdErrAdapter.cs +++ b/src/Ryujinx.Common/SystemInterop/StdErrAdapter.cs @@ -12,8 +12,8 @@ namespace Ryujinx.Common.SystemInterop public partial class StdErrAdapter : IDisposable { private bool _disposable; - private Stream _pipeReader; - private Stream _pipeWriter; + private FileStream _pipeReader; + private FileStream _pipeWriter; private CancellationTokenSource _cancellationTokenSource; private Task _worker; @@ -46,7 +46,7 @@ namespace Ryujinx.Common.SystemInterop [SupportedOSPlatform("macos")] private async Task EventWorkerAsync(CancellationToken cancellationToken) { - using TextReader reader = new StreamReader(_pipeReader, leaveOpen: true); + using StreamReader reader = new(_pipeReader, leaveOpen: true); string line; while (cancellationToken.IsCancellationRequested == false && (line = await reader.ReadLineAsync(cancellationToken)) != null) { @@ -92,13 +92,12 @@ namespace Ryujinx.Common.SystemInterop [SupportedOSPlatform("linux")] [SupportedOSPlatform("macos")] - private static Stream CreateFileDescriptorStream(int fd) + private static FileStream CreateFileDescriptorStream(int fd) { return new FileStream( new SafeFileHandle(fd, ownsHandle: true), FileAccess.ReadWrite ); } - } } diff --git a/src/Ryujinx.Common/TitleIDs.cs b/src/Ryujinx.Common/TitleIDs.cs index 3201a5c6b..d753caa33 100644 --- a/src/Ryujinx.Common/TitleIDs.cs +++ b/src/Ryujinx.Common/TitleIDs.cs @@ -6,8 +6,8 @@ namespace Ryujinx.Common public static class TitleIDs { public static ReactiveObject> CurrentApplication { get; } = new(); - - public static string GetDiscordGameAsset(string titleId) + + public static string GetDiscordGameAsset(string titleId) => DiscordGameAssetKeys.Contains(titleId) ? titleId : "game"; public static readonly string[] DiscordGameAssetKeys = @@ -133,7 +133,6 @@ namespace Ryujinx.Common "0100c1f0051b6000", // Donkey Kong Country: Tropical Freeze "0100ed000d390000", // Dr. Kawashima's Brain Training "010067b017588000", // Endless Ocean Luminous - "0100d2f00d5c0000", // Nintendo Switch Sports "01006b5012b32000", // Part Time UFO "0100704000B3A000", // Snipperclips "01006a800016e000", // Super Smash Bros. Ultimate @@ -169,6 +168,8 @@ namespace Ryujinx.Common "010056e00853a000", // A Hat in Time "0100fd1014726000", // Baldurs Gate: Dark Alliance "01008c2019598000", // Bluey: The Video Game + "010096f00ff22000", // Borderlands 2: Game of the Year Edition + "010007400ff24000", // Borderlands: The Pre-Sequel Ultimate Edition "0100c6800b934000", // Brawlhalla "0100dbf01000a000", // Burnout Paradise Remastered "0100744001588000", // Cars 3: Driven to Win @@ -194,6 +195,7 @@ namespace Ryujinx.Common "01008d100d43e000", // Saints Row IV "0100de600beee000", // Saints Row: The Third - The Full Package "01001180021fa000", // Shovel Knight: Specter of Torment + "0100e1D01eb2e000", // Squeakross: Home Squeak Home "0100e65002bb8000", // Stardew Valley "0100d7a01b7a2000", // Star Wars: Bounty Hunter "0100800015926000", // Suika Game diff --git a/src/Ryujinx.Common/Utilities/BitUtils.cs b/src/Ryujinx.Common/Utilities/BitUtils.cs index acbdde1f6..c99a8635d 100644 --- a/src/Ryujinx.Common/Utilities/BitUtils.cs +++ b/src/Ryujinx.Common/Utilities/BitUtils.cs @@ -40,10 +40,10 @@ namespace Ryujinx.Common return (value >> 32) | (value << 32); } - + // Never actually written bit packing logic before, so I looked it up. // This code is from https://gist.github.com/Alan-FGR/04938e93e2bffdf5802ceb218a37c195 - + public static ulong PackBitFields(this uint[] values, byte[] bitFields) { ulong retVal = values[0]; //we set the first value right away @@ -52,6 +52,7 @@ namespace Ryujinx.Common retVal <<= bitFields[f]; // we shift the previous value retVal += values[f];// and add our current value } + return retVal; } @@ -68,6 +69,7 @@ namespace Ryujinx.Common int leftShift = 64 - curPos; // we figure how much left shift we gotta apply for the other numbers to overflow into oblivion retArr[f] = (uint)((packed << leftShift) >> leftShift + lastEnd); // we do magic } + return retArr; } } diff --git a/src/Ryujinx.Common/Utilities/FileSystemUtils.cs b/src/Ryujinx.Common/Utilities/FileSystemUtils.cs index 97510fd9d..6ec92044e 100644 --- a/src/Ryujinx.Common/Utilities/FileSystemUtils.cs +++ b/src/Ryujinx.Common/Utilities/FileSystemUtils.cs @@ -49,7 +49,7 @@ namespace Ryujinx.Common.Utilities public static string SanitizeFileName(string fileName) { - HashSet reservedChars = new(Path.GetInvalidFileNameChars()); + HashSet reservedChars = [.. Path.GetInvalidFileNameChars()]; return string.Concat(fileName.Select(c => reservedChars.Contains(c) ? '_' : c)); } } diff --git a/src/Ryujinx.Common/Utilities/JsonHelper.cs b/src/Ryujinx.Common/Utilities/JsonHelper.cs index 82eeaddc1..2493f3ec4 100644 --- a/src/Ryujinx.Common/Utilities/JsonHelper.cs +++ b/src/Ryujinx.Common/Utilities/JsonHelper.cs @@ -28,13 +28,13 @@ namespace Ryujinx.Common.Utilities ReadCommentHandling = JsonCommentHandling.Skip }; - public static string Serialize(T value, JsonTypeInfo typeInfo) + public static string Serialize(T value, JsonTypeInfo typeInfo) => JsonSerializer.Serialize(value, typeInfo); - public static T Deserialize(string value, JsonTypeInfo typeInfo) + public static T Deserialize(string value, JsonTypeInfo typeInfo) => JsonSerializer.Deserialize(value, typeInfo); - public static T Deserialize(ReadOnlySpan utf8Value, JsonTypeInfo typeInfo) + public static T Deserialize(ReadOnlySpan utf8Value, JsonTypeInfo typeInfo) => JsonSerializer.Deserialize(utf8Value, typeInfo); public static void SerializeToFile(string filePath, T value, JsonTypeInfo typeInfo) diff --git a/src/Ryujinx.Common/Utilities/Rainbow.cs b/src/Ryujinx.Common/Utilities/Rainbow.cs index eb1c187c4..93129bf10 100644 --- a/src/Ryujinx.Common/Utilities/Rainbow.cs +++ b/src/Ryujinx.Common/Utilities/Rainbow.cs @@ -1,4 +1,4 @@ -using Gommon; +using Gommon; using Ryujinx.Common.Helper; using System; using System.Drawing; @@ -31,12 +31,12 @@ namespace Ryujinx.Common.Utilities { CyclingEnabled = false; } - - + + public static float Speed { get; set; } = 1; private static readonly Lock _lock = new(); - + private static Color _color = Color.Blue; public static ref Color Color @@ -55,7 +55,7 @@ namespace Ryujinx.Common.Utilities lock (_lock) { _color = HsbToRgb((_color.GetHue() + Speed) / 360); - + _updatedHandler.Call(ref _color); } } @@ -63,7 +63,7 @@ namespace Ryujinx.Common.Utilities public static void Reset() { _updatedHandler.Clear(); - + lock (_lock) _color = Color.Blue; } @@ -124,6 +124,7 @@ namespace Ryujinx.Common.Utilities break; } } + return Color.FromArgb(Convert.ToByte(255), Convert.ToByte(r), Convert.ToByte(g), Convert.ToByte(b)); } } diff --git a/src/Ryujinx.Common/Utilities/StreamUtils.cs b/src/Ryujinx.Common/Utilities/StreamUtils.cs index 60391a902..e5246dfe7 100644 --- a/src/Ryujinx.Common/Utilities/StreamUtils.cs +++ b/src/Ryujinx.Common/Utilities/StreamUtils.cs @@ -59,7 +59,7 @@ namespace Ryujinx.Common.Utilities public static async Task StreamToBytesAsync(Stream input, CancellationToken cancellationToken = default) { - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); await input.CopyToAsync(stream, cancellationToken); diff --git a/src/Ryujinx.Common/Utilities/XCIFileTrimmer.cs b/src/Ryujinx.Common/Utilities/XCIFileTrimmer.cs index 5b233d1e0..90738798a 100644 --- a/src/Ryujinx.Common/Utilities/XCIFileTrimmer.cs +++ b/src/Ryujinx.Common/Utilities/XCIFileTrimmer.cs @@ -183,7 +183,6 @@ namespace Ryujinx.Common.Utilities { CloseReaders(); } - } else { @@ -205,7 +204,7 @@ namespace Ryujinx.Common.Utilities while (true) { - if (cancelToken.HasValue && cancelToken.Value.IsCancellationRequested) + if (cancelToken.HasValue && cancelToken.Value.IsCancellationRequested) { return false; } @@ -257,7 +256,7 @@ namespace Ryujinx.Common.Utilities { return OperationOutcome.Cancelled; } - else + else { return OperationOutcome.FreeSpaceCheckFailed; } @@ -294,7 +293,7 @@ namespace Ryujinx.Common.Utilities { #if !XCI_TRIMMER_READ_ONLY_MODE - outfileStream.SetLength(TrimmedFileSizeB); + outfileStream.SetLength(TrimmedFileSizeB); #endif return OperationOutcome.Successful; } @@ -367,7 +366,7 @@ namespace Ryujinx.Common.Utilities { return OperationOutcome.Cancelled; } - else + else { return OperationOutcome.Successful; } @@ -404,9 +403,9 @@ namespace Ryujinx.Common.Utilities } long bytesToWrite = Math.Min(XCIFileTrimmer.BufferSize, bytesLeftToWriteB); - + #if !XCI_TRIMMER_READ_ONLY_MODE - outfileStream.Write(buffer, 0, (int)bytesToWrite); + outfileStream.Write(buffer, 0, (int)bytesToWrite); #endif bytesLeftToWriteB -= bytesToWrite; @@ -511,6 +510,7 @@ namespace Ryujinx.Common.Utilities Log?.Write(LogType.Error, $"The source file doesn't look like an XCI file as the Cartridge Size is incorrect (0x{cartSizeId:X2})"); return false; } + _cartSizeB = cartSizeNGB * XCIFileTrimmer.CartSizeMBinFormattedGB * XCIFileTrimmer.BytesInAMegabyte; // Read data size diff --git a/src/Ryujinx.Cpu/AddressTable.cs b/src/Ryujinx.Cpu/AddressTable.cs index 3310f7ddd..91a65e899 100644 --- a/src/Ryujinx.Cpu/AddressTable.cs +++ b/src/Ryujinx.Cpu/AddressTable.cs @@ -51,7 +51,7 @@ namespace ARMeilleure.Common { SparseMemoryBlock block = new(size, pageInit, null); - _trackingEvent = (ulong address, ulong size, bool write) => + _trackingEvent = (address, size, write) => { ulong pointer = (ulong)block.Block.Pointer + address; ensureMapped((IntPtr)pointer); @@ -181,7 +181,7 @@ namespace ARMeilleure.Common public static AddressTable CreateForArm(bool for64Bits, MemoryManagerType type) { // Assume software memory means that we don't want to use any signal handlers. - bool sparse = type != MemoryManagerType.SoftwareMmu && type != MemoryManagerType.SoftwarePageTable; + bool sparse = type is not MemoryManagerType.SoftwareMmu and not MemoryManagerType.SoftwarePageTable; return new AddressTable(AddressTablePresets.GetArmPreset(for64Bits, sparse), sparse); } diff --git a/src/Ryujinx.Cpu/AppleHv/HvAddressSpaceRange.cs b/src/Ryujinx.Cpu/AppleHv/HvAddressSpaceRange.cs index 7754431fa..c8edc6c6f 100644 --- a/src/Ryujinx.Cpu/AppleHv/HvAddressSpaceRange.cs +++ b/src/Ryujinx.Cpu/AppleHv/HvAddressSpaceRange.cs @@ -359,7 +359,7 @@ namespace Ryujinx.Cpu.AppleHv private static void ValidateEntriesCount(int count) { - Debug.Assert(count >= 0 && count <= LevelCount, $"Entries count {count} is invalid."); + Debug.Assert(count is >= 0 and <= LevelCount, $"Entries count {count} is invalid."); } public void Dispose() diff --git a/src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs b/src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs index fc2b76d15..53cea5385 100644 --- a/src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs +++ b/src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs @@ -159,7 +159,7 @@ namespace Ryujinx.Cpu.AppleHv address = SynchronousException(memoryManager, ref vcpu); HvApi.hv_vcpu_set_reg(vcpu.Handle, HvReg.PC, address).ThrowOnError(); } - else if (reason == HvExitReason.Canceled || reason == HvExitReason.VTimerActivated) + else if (reason is HvExitReason.Canceled or HvExitReason.VTimerActivated) { if (GetAndClearInterruptRequested()) { diff --git a/src/Ryujinx.Cpu/ITickSource.cs b/src/Ryujinx.Cpu/ITickSource.cs index 4aff612f0..3eba8b524 100644 --- a/src/Ryujinx.Cpu/ITickSource.cs +++ b/src/Ryujinx.Cpu/ITickSource.cs @@ -9,12 +9,12 @@ namespace Ryujinx.Cpu public interface ITickSource : ICounter { public const long RealityTickScalar = 100; - + /// /// Time elapsed since the counter was created. /// TimeSpan ElapsedTime { get; } - + /// /// Clock tick scalar, in percent points (100 = 1.0). /// diff --git a/src/Ryujinx.Cpu/Jit/HostTracked/AddressIntrusiveRedBlackTree.cs b/src/Ryujinx.Cpu/Jit/HostTracked/AddressIntrusiveRedBlackTree.cs index 0e2443303..d3a24c8bf 100644 --- a/src/Ryujinx.Cpu/Jit/HostTracked/AddressIntrusiveRedBlackTree.cs +++ b/src/Ryujinx.Cpu/Jit/HostTracked/AddressIntrusiveRedBlackTree.cs @@ -29,6 +29,7 @@ namespace Ryujinx.Cpu.Jit.HostTracked return node; } } + return null; } } diff --git a/src/Ryujinx.Cpu/Jit/HostTracked/AddressSpacePartitionAllocator.cs b/src/Ryujinx.Cpu/Jit/HostTracked/AddressSpacePartitionAllocator.cs index f39b295cd..c22fbd5df 100644 --- a/src/Ryujinx.Cpu/Jit/HostTracked/AddressSpacePartitionAllocator.cs +++ b/src/Ryujinx.Cpu/Jit/HostTracked/AddressSpacePartitionAllocator.cs @@ -115,7 +115,7 @@ namespace Ryujinx.Cpu.Jit.HostTracked } private readonly AddressIntrusiveRedBlackTree _mappingTree; - + // type is not Lock due to the unique usage of this mechanism, // an arbitrary object is used as the lock passed in by constructor. private readonly object _lock; @@ -177,7 +177,7 @@ namespace Ryujinx.Cpu.Jit.HostTracked private readonly MemoryTracking _tracking; private readonly Func _readPtCallback; - + // type is not Lock due to the unique usage of this mechanism, // an arbitrary object is used as the lock passed in by constructor. private readonly object _lock; diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/InstName.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/InstName.cs index 2ee67aa0a..809fbf25e 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/InstName.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/InstName.cs @@ -531,7 +531,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32 { public static bool IsCall(this InstName name) { - return name == InstName.BlI || name == InstName.BlxR; + return name is InstName.BlI or InstName.BlxR; } public static bool IsSystem(this InstName name) diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/InstTableT32.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/InstTableT32.cs index 09222f43e..0a0774845 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/InstTableT32.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/InstTableT32.cs @@ -526,7 +526,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32 new(0x00000041, 0x00000041) ]; - List insts = + List insts = [ new(0xF1400000, 0xFBE08000, InstName.AdcI, T.AdcIT1, IsaVersion.v80, InstFlags.Rd), new(0xEB400000, 0xFFE08000, InstName.AdcR, T.AdcRT2, IsaVersion.v80, InstFlags.Rd), diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/Compiler.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/Compiler.cs index 3121d4f95..643d1e20d 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/Compiler.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/Compiler.cs @@ -493,7 +493,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 { delta = targetIndex - branchIndex; - if (delta >= -Encodable26BitsOffsetLimit && delta < Encodable26BitsOffsetLimit) + if (delta is >= (-Encodable26BitsOffsetLimit) and < Encodable26BitsOffsetLimit) { writer.WriteInstructionAt(branchIndex, encoding | (uint)(delta & 0x3ffffff)); @@ -559,7 +559,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 } } - Debug.Assert(name == InstName.B || name == InstName.Cbnz, $"Unknown branch instruction \"{name}\"."); + Debug.Assert(name is InstName.B or InstName.Cbnz, $"Unknown branch instruction \"{name}\"."); } private static void RewriteCallInstructionWithTarget(in Context context, uint targetAddress, uint nextAddress, int branchIndex) @@ -745,6 +745,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 InstEmitSystem.WriteUdf(context.Writer, context.RegisterAllocator, context.TailMerger, context.GetReservedStackOffset(), pc, imm); break; } + context.LoadFromContext(); break; case BranchType.ReadCntpct: diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitAlu.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitAlu.cs index c0762819e..30479137c 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitAlu.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitAlu.cs @@ -736,6 +736,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 { m = GetRrxC(context, dest, m, carryOut); } + break; } } diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs index 6a8c2abdd..8190bd7ea 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs @@ -142,7 +142,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 int tempRegister; int tempGuestAddress = -1; - bool inlineLookup = guestAddress.Kind != OperandKind.Constant && + bool inlineLookup = guestAddress.Kind != OperandKind.Constant && funcTable is { Sparse: true }; if (guestAddress.Kind == OperandKind.Constant) diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonCommon.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonCommon.cs index dce6556e4..eb5b56364 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonCommon.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonCommon.cs @@ -118,7 +118,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 public static void EmitScalarUnaryF(CodeGenContext context, uint rd, uint rm, uint size, Action action) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; @@ -133,7 +133,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 public static void EmitScalarUnaryF(CodeGenContext context, uint rd, uint rm, uint size, Action action, Action actionHalf) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; @@ -161,7 +161,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 uint sf, Action action) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; @@ -182,7 +182,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 uint sf, Action action) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; @@ -197,7 +197,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 public static void EmitScalarUnaryFixedF(CodeGenContext context, uint rd, uint rm, uint fbits, uint size, bool is16Bit, Action action) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; @@ -214,7 +214,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 public static void EmitScalarBinaryF(CodeGenContext context, uint rd, uint rn, uint rm, uint size, Action action) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; @@ -252,7 +252,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 public static void EmitScalarTernaryRdF(CodeGenContext context, uint rd, uint rn, uint rm, uint size, Action action) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; @@ -276,7 +276,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 uint size, Action action) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; @@ -300,7 +300,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 bool negD, bool negProduct) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; @@ -918,7 +918,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 Action action, Action actionHalf) { - Debug.Assert(sz == 0 || sz == 1); + Debug.Assert(sz is 0 or 1); if (q == 0) { @@ -962,7 +962,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 Action action, Action actionHalf) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); Debug.Assert(size != 3 || q == 1); if (q == 0) @@ -1007,7 +1007,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 uint q, Action action) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); Debug.Assert(size != 3 || q == 1); (uint immb, uint immh) = GetImmbImmh(fbits, size); @@ -1040,7 +1040,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 Action action, Action actionHalf) { - Debug.Assert(sz == 0 || sz == 1); + Debug.Assert(sz is 0 or 1); if (q == 0) { @@ -1100,7 +1100,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 Action action, Action actionHalf) { - Debug.Assert(sz == 0 || sz == 1); + Debug.Assert(sz is 0 or 1); if (q == 0) { @@ -1148,7 +1148,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 uint q, bool negProduct) { - Debug.Assert(sz == 0 || sz == 1); + Debug.Assert(sz is 0 or 1); if (q == 0) { diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMemory.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMemory.cs index e77dc0a29..18017351a 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMemory.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMemory.cs @@ -467,7 +467,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 private static void EmitMemory1234InstructionCore(CodeGenContext context, uint rn, uint rm, int bytes, Action callback) { bool wBack = rm != RegisterUtils.PcRegister; - bool registerIndex = rm != RegisterUtils.PcRegister && rm != RegisterUtils.SpRegister; + bool registerIndex = rm is not RegisterUtils.PcRegister and not RegisterUtils.SpRegister; Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMove.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMove.cs index 08a0673aa..f22cb5839 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMove.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMove.cs @@ -252,7 +252,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 } else { - Debug.Assert(opc1 == 0 || opc1 == 1); + Debug.Assert(opc1 is 0 or 1); Debug.Assert(opc2 == 0); index = opc1 & 1u; @@ -307,7 +307,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 } else { - Debug.Assert(opc1 == 0 || opc1 == 1); + Debug.Assert(opc1 is 0 or 1); Debug.Assert(opc2 == 0); Debug.Assert(!u); diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSystem.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSystem.cs index 21e40b6aa..10a3298e7 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSystem.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSystem.cs @@ -60,6 +60,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 return; } } + break; } } @@ -109,6 +110,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 break; } } + break; } @@ -142,6 +144,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 context.Arm64Assembler.B(0); return; } + break; } diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpCompare.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpCompare.cs index c1b51750f..66873818e 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpCompare.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpCompare.cs @@ -27,7 +27,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 private static void EmitVcmpVcmpe(CodeGenContext context, uint cond, uint rd, uint rm, uint size, bool zero, bool e) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; uint ftype = size ^ 2u; diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpConvert.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpConvert.cs index 8e4886950..aef833256 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpConvert.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpConvert.cs @@ -231,7 +231,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 { bool unsigned = (op & 1) == 0; - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; diff --git a/src/Ryujinx.Cpu/LightningJit/Arm64/InstName.cs b/src/Ryujinx.Cpu/LightningJit/Arm64/InstName.cs index 3391a2c14..af3b872a5 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm64/InstName.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm64/InstName.cs @@ -1044,7 +1044,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64 { public static bool IsCall(this InstName name) { - return name == InstName.Bl || name == InstName.Blr; + return name is InstName.Bl or InstName.Blr; } public static bool IsControlFlowOrException(this InstName name) diff --git a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Compiler.cs b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Compiler.cs index 1e087591c..e45d74f9b 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Compiler.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Compiler.cs @@ -545,6 +545,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 context.GetReservedStackOffset(), isTail: true); } + break; case InstName.Ret: @@ -565,6 +566,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 context.TailMerger.AddUnconditionalReturn(writer, asm); } + break; case InstName.BCond: @@ -574,7 +576,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 case InstName.Tbz: uint branchMask; - if (name == InstName.Tbnz || name == InstName.Tbz) + if (name is InstName.Tbnz or InstName.Tbz) { originalOffset = ImmUtils.ExtractSImm14Times4(encoding); branchMask = 0x3fff; @@ -631,7 +633,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 { delta = targetIndex - branchIndex; - if (delta >= -Encodable26BitsOffsetLimit && delta < Encodable26BitsOffsetLimit) + if (delta is >= (-Encodable26BitsOffsetLimit) and < Encodable26BitsOffsetLimit) { writer.WriteInstructionAt(branchIndex, (encoding & ~0x3ffffffu) | (uint)(delta & 0x3ffffff)); break; @@ -652,7 +654,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 case InstName.Tbz: uint branchMask; - if (name == InstName.Tbnz || name == InstName.Tbz) + if (name is InstName.Tbnz or InstName.Tbz) { originalOffset = ImmUtils.ExtractSImm14Times4(encoding); branchMask = 0x3fff; @@ -709,6 +711,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 writer.WriteInstructionAt(movedBranchIndex, (encoding & ~(branchMask << 5)) | (uint)((delta & branchMask) << 5)); WriteTailCallConstant(context, ref asm, blockIndex, targetAddress); } + break; default: diff --git a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Decoder.cs b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Decoder.cs index 33d319668..ad221c7aa 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Decoder.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Decoder.cs @@ -72,7 +72,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 case InstName.Cbz: case InstName.Tbnz: case InstName.Tbz: - if (name == InstName.Tbnz || name == InstName.Tbz) + if (name is InstName.Tbnz or InstName.Tbz) { originalOffset = ImmUtils.ExtractSImm14Times4(encoding); } @@ -369,7 +369,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 case InstName.Cbz: case InstName.Tbnz: case InstName.Tbz: - int imm = name == InstName.Tbnz || name == InstName.Tbz + int imm = name is InstName.Tbnz or InstName.Tbz ? ImmUtils.ExtractSImm14Times4(encoding) : ImmUtils.ExtractSImm19Times4(encoding); diff --git a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs index 98939839c..1bd69bc4b 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs @@ -230,7 +230,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 case InstName.Bl: case InstName.Blr: case InstName.Br: - if (name == InstName.BUncond || name == InstName.Bl) + if (name is InstName.BUncond or InstName.Bl) { int imm = ImmUtils.ExtractSImm26Times4(encoding); @@ -283,6 +283,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 isTail); } } + break; default: diff --git a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstTable.cs b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstTable.cs index b1dc9b30c..984545800 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstTable.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstTable.cs @@ -451,7 +451,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 new(0x00000000, 0x20001000) ]; - List insts = + List insts = [ new(0x5AC02000, 0x7FFFFC00, InstName.Abs, IsaVersion.v89, InstFlags.RdRn), new(0x5EE0B800, 0xFFFFFC00, InstName.AbsAdvsimdS, IsaVersion.v80, InstFlags.RdRnFpSimd), diff --git a/src/Ryujinx.Cpu/LightningJit/Cache/JitCache.cs b/src/Ryujinx.Cpu/LightningJit/Cache/JitCache.cs index 96bb05819..4ab54ecb7 100644 --- a/src/Ryujinx.Cpu/LightningJit/Cache/JitCache.cs +++ b/src/Ryujinx.Cpu/LightningJit/Cache/JitCache.cs @@ -150,7 +150,7 @@ namespace Ryujinx.Cpu.LightningJit.Cache for (int i = _activeRegionIndex; i < _jitRegions.Count; i++) { int allocOffset = _cacheAllocator.Allocate(codeSize); - + if (allocOffset >= 0) { _jitRegions[i].ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize); @@ -163,11 +163,11 @@ namespace Ryujinx.Cpu.LightningJit.Cache ReservedRegion newRegion = new(_jitRegions[0].Allocator, CacheSize); _jitRegions.Add(newRegion); _activeRegionIndex = _jitRegions.Count - 1; - + int newRegionNumber = _activeRegionIndex; Logger.Warning?.Print(LogClass.Cpu, $"JIT Cache Region {exhaustedRegion} exhausted, creating new Cache Region {newRegionNumber} ({((long)(newRegionNumber + 1) * CacheSize).Bytes()} Total Allocation)."); - + _cacheAllocator = new CacheMemoryAllocator(CacheSize); int allocOffsetNew = _cacheAllocator.Allocate(codeSize); diff --git a/src/Ryujinx.Cpu/LightningJit/CodeGen/Arm64/Assembler.cs b/src/Ryujinx.Cpu/LightningJit/CodeGen/Arm64/Assembler.cs index dd130dbeb..3eeda20bf 100644 --- a/src/Ryujinx.Cpu/LightningJit/CodeGen/Arm64/Assembler.cs +++ b/src/Ryujinx.Cpu/LightningJit/CodeGen/Arm64/Assembler.cs @@ -4360,6 +4360,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64 instI |= 1 << 22; // sh flag imm >>= 12; } + WriteInstructionAuto(instI | (EncodeUImm12(imm, 0) << 10), rd, rn); } else diff --git a/src/Ryujinx.Cpu/LightningJit/CodeGen/Arm64/CodeGenCommon.cs b/src/Ryujinx.Cpu/LightningJit/CodeGen/Arm64/CodeGenCommon.cs index db6a71593..f1aca983f 100644 --- a/src/Ryujinx.Cpu/LightningJit/CodeGen/Arm64/CodeGenCommon.cs +++ b/src/Ryujinx.Cpu/LightningJit/CodeGen/Arm64/CodeGenCommon.cs @@ -28,7 +28,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64 // Any value AND all ones will be equal itself, so it's effectively a no-op. // Any value OR all ones will be equal all ones, so one can just use MOV. // Any value XOR all ones will be equal its inverse, so one can just use MVN. - if (value == 0 || value == ulong.MaxValue) + if (value is 0 or ulong.MaxValue) { immN = 0; immS = 0; diff --git a/src/Ryujinx.Cpu/LightningJit/CodeGen/OperandType.cs b/src/Ryujinx.Cpu/LightningJit/CodeGen/OperandType.cs index 6191f791b..cd36c6781 100644 --- a/src/Ryujinx.Cpu/LightningJit/CodeGen/OperandType.cs +++ b/src/Ryujinx.Cpu/LightningJit/CodeGen/OperandType.cs @@ -16,7 +16,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen { public static bool IsInteger(this OperandType type) { - return type == OperandType.I32 || type == OperandType.I64; + return type is OperandType.I32 or OperandType.I64; } public static int GetSizeInBytes(this OperandType type) diff --git a/src/Ryujinx.Cpu/LightningJit/Translator.cs b/src/Ryujinx.Cpu/LightningJit/Translator.cs index 5f3fe8783..f3ae0a9c5 100644 --- a/src/Ryujinx.Cpu/LightningJit/Translator.cs +++ b/src/Ryujinx.Cpu/LightningJit/Translator.cs @@ -54,7 +54,7 @@ namespace Ryujinx.Cpu.LightningJit } } - private static IStackWalker CreateStackWalker() + private static StackWalker CreateStackWalker() { if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64) { diff --git a/src/Ryujinx.Cpu/TickSource.cs b/src/Ryujinx.Cpu/TickSource.cs index 3bc01d6b9..3aa616a8d 100644 --- a/src/Ryujinx.Cpu/TickSource.cs +++ b/src/Ryujinx.Cpu/TickSource.cs @@ -14,33 +14,30 @@ namespace Ryujinx.Cpu /// public ulong Counter => (ulong)(ElapsedSeconds * Frequency); - - - public long TickScalar { get; set; } + public long TickScalar { get; set; } + private static long _acumElapsedTicks; - private static long _lastElapsedTicks; - private long ElapsedTicks { get { long elapsedTicks = _tickCounter.ElapsedTicks; - + _acumElapsedTicks += (elapsedTicks - _lastElapsedTicks) * TickScalar / 100; _lastElapsedTicks = elapsedTicks; - + return _acumElapsedTicks; } } /// - + public TimeSpan ElapsedTime => Stopwatch.GetElapsedTime(0, ElapsedTicks); /// diff --git a/src/Ryujinx.Graphics.GAL/IRenderer.cs b/src/Ryujinx.Graphics.GAL/IRenderer.cs index 9d822e7c2..cc51ed67b 100644 --- a/src/Ryujinx.Graphics.GAL/IRenderer.cs +++ b/src/Ryujinx.Graphics.GAL/IRenderer.cs @@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.GAL Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend Threading ({backendThreading}): True"); return new ThreadedRenderer(this); } - + Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend Threading ({backendThreading}): False"); return this; diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/BufferMap.cs b/src/Ryujinx.Graphics.GAL/Multithreading/BufferMap.cs index 48bec3633..5e273d420 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/BufferMap.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/BufferMap.cs @@ -77,7 +77,6 @@ namespace Ryujinx.Graphics.GAL.Multithreading { // Blocks until the handle is available. - lock (_bufferMap) { if (_bufferMap.TryGetValue(handle, out BufferHandle result)) diff --git a/src/Ryujinx.Graphics.GAL/Target.cs b/src/Ryujinx.Graphics.GAL/Target.cs index 73497546e..1c184981d 100644 --- a/src/Ryujinx.Graphics.GAL/Target.cs +++ b/src/Ryujinx.Graphics.GAL/Target.cs @@ -18,17 +18,17 @@ namespace Ryujinx.Graphics.GAL { public static bool IsMultisample(this Target target) { - return target == Target.Texture2DMultisample || target == Target.Texture2DMultisampleArray; + return target is Target.Texture2DMultisample or Target.Texture2DMultisampleArray; } public static bool HasDepthOrLayers(this Target target) { - return target == Target.Texture3D || - target == Target.Texture1DArray || - target == Target.Texture2DArray || - target == Target.Texture2DMultisampleArray || - target == Target.Cubemap || - target == Target.CubemapArray; + return target is Target.Texture3D or + Target.Texture1DArray or + Target.Texture2DArray or + Target.Texture2DMultisampleArray or + Target.Cubemap or + Target.CubemapArray; } } } diff --git a/src/Ryujinx.Graphics.GAL/TextureCreateInfo.cs b/src/Ryujinx.Graphics.GAL/TextureCreateInfo.cs index 79c84db01..27a2ac896 100644 --- a/src/Ryujinx.Graphics.GAL/TextureCreateInfo.cs +++ b/src/Ryujinx.Graphics.GAL/TextureCreateInfo.cs @@ -98,9 +98,9 @@ namespace Ryujinx.Graphics.GAL public int GetLayers() { - if (Target == Target.Texture2DArray || - Target == Target.Texture2DMultisampleArray || - Target == Target.CubemapArray) + if (Target is Target.Texture2DArray or + Target.Texture2DMultisampleArray or + Target.CubemapArray) { return Depth; } diff --git a/src/Ryujinx.Graphics.GAL/ViewportSwizzle.cs b/src/Ryujinx.Graphics.GAL/ViewportSwizzle.cs index 9352c8162..69de93ad5 100644 --- a/src/Ryujinx.Graphics.GAL/ViewportSwizzle.cs +++ b/src/Ryujinx.Graphics.GAL/ViewportSwizzle.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.Graphics.GAL { - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] public enum ViewportSwizzle { PositiveX = 0, diff --git a/src/Ryujinx.Graphics.Gpu/Engine/DeviceStateWithShadow.cs b/src/Ryujinx.Graphics.Gpu/Engine/DeviceStateWithShadow.cs index ccfba79a4..aacaf2f4b 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/DeviceStateWithShadow.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/DeviceStateWithShadow.cs @@ -85,8 +85,8 @@ namespace Ryujinx.Graphics.Gpu.Engine { _state.WriteWithRedundancyCheck(offset, value, out changed); } - else if (shadowRamControl == SetMmeShadowRamControlMode.MethodTrack || - shadowRamControl == SetMmeShadowRamControlMode.MethodTrackWithFilter) + else if (shadowRamControl is SetMmeShadowRamControlMode.MethodTrack or + SetMmeShadowRamControlMode.MethodTrackWithFilter) { _shadowState.Write(offset, value); _state.WriteWithRedundancyCheck(offset, value, out changed); diff --git a/src/Ryujinx.Graphics.Gpu/Engine/MME/MacroJitCompiler.cs b/src/Ryujinx.Graphics.Gpu/Engine/MME/MacroJitCompiler.cs index ea8bb2d61..cd711f1b3 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/MME/MacroJitCompiler.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/MME/MacroJitCompiler.cs @@ -290,6 +290,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME _ilGen.Emit(OpCodes.Shl); break; } + break; case AluOperation.ReadImmediate: diff --git a/src/Ryujinx.Graphics.Gpu/Engine/SetMmeShadowRamControlMode.cs b/src/Ryujinx.Graphics.Gpu/Engine/SetMmeShadowRamControlMode.cs index b9a5c74a3..c07cb1044 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/SetMmeShadowRamControlMode.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/SetMmeShadowRamControlMode.cs @@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.Gpu.Engine { public static bool IsTrack(this SetMmeShadowRamControlMode mode) { - return mode == SetMmeShadowRamControlMode.MethodTrack || mode == SetMmeShadowRamControlMode.MethodTrackWithFilter; + return mode is SetMmeShadowRamControlMode.MethodTrack or SetMmeShadowRamControlMode.MethodTrackWithFilter; } public static bool IsPassthrough(this SetMmeShadowRamControlMode mode) diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeContext.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeContext.cs index eba1b6030..ed9da4a5c 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeContext.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeContext.cs @@ -285,6 +285,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw { data[index] = index; } + break; case PrimitiveTopology.LineLoop: data[^1] = 0; @@ -294,6 +295,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw data[index] = index >> 1; data[index + 1] = (index >> 1) + 1; } + break; case PrimitiveTopology.LineStrip: for (int index = 0; index < ((data.Length - 1) & ~1); index += 2) @@ -301,6 +303,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw data[index] = index >> 1; data[index + 1] = (index >> 1) + 1; } + break; case PrimitiveTopology.TriangleStrip: int tsTrianglesCount = data.Length / 3; @@ -330,6 +333,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw data[baseIndex + 2] = tsOutIndex++; } } + break; case PrimitiveTopology.TriangleFan: case PrimitiveTopology.Polygon: @@ -342,6 +346,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw data[index + 1] = tfOutIndex; data[index + 2] = ++tfOutIndex; } + break; case PrimitiveTopology.Quads: int qQuadsCount = data.Length / 6; @@ -358,6 +363,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw data[index + 4] = qIndex + 2; data[index + 5] = qIndex + 3; } + break; case PrimitiveTopology.QuadStrip: int qsQuadsCount = data.Length / 6; @@ -384,6 +390,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw data[index + 4] = qIndex + 2; data[index + 5] = qIndex + 3; } + break; case PrimitiveTopology.LineStripAdjacency: for (int index = 0; index < ((data.Length - 3) & ~3); index += 4) @@ -395,6 +402,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw data[index + 2] = lIndex + 2; data[index + 3] = lIndex + 3; } + break; case PrimitiveTopology.TriangleStripAdjacency: int tsaTrianglesCount = data.Length / 6; @@ -433,6 +441,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw data[baseIndex + 5] = tsaOutIndex++; } } + break; } diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeState.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeState.cs index 0d59275ff..a66ea7dbe 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeState.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeState.cs @@ -170,8 +170,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw int vbStride = vertexBuffer.UnpackStride(); ulong vbSize = GetVertexBufferSize(address, endAddress.Pack(), vbStride, _indexed, instanced, _firstVertex, _count); - ulong oldVbSize = vbSize; - ulong attributeOffset = (ulong)vertexAttrib.UnpackOffset(); int componentSize = format.GetScalarSize(); @@ -477,7 +475,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw private readonly ulong GetVertexBufferSize(ulong vbAddress, ulong vbEndAddress, int vbStride, bool indexed, bool instanced, int firstVertex, int vertexCount) { IndexType indexType = _state.State.IndexBufferState.Type; - bool indexTypeSmall = indexType == IndexType.UByte || indexType == IndexType.UShort; + bool indexTypeSmall = indexType is IndexType.UByte or IndexType.UShort; ulong vbSize = vbEndAddress - vbAddress + 1; ulong size; diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/IndirectDrawType.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/IndirectDrawType.cs index 331b1976b..402e3ff80 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/IndirectDrawType.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/IndirectDrawType.cs @@ -5,7 +5,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed /// /// Indirect draw type, which can be indexed or non-indexed, with or without a draw count. /// - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum IndirectDrawType { /// diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/SpecializationStateUpdater.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/SpecializationStateUpdater.cs index 4eea80687..c76adbca6 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/SpecializationStateUpdater.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/SpecializationStateUpdater.cs @@ -253,9 +253,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed { value |= AttributeType.Packed; - if (type == VertexAttribType.Snorm || - type == VertexAttribType.Sint || - type == VertexAttribType.Sscaled) + if (type is VertexAttribType.Snorm or + VertexAttribType.Sint or + VertexAttribType.Sscaled) { value |= AttributeType.PackedRgb10A2Signed; } diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs index 4620821cb..e6af3fb5e 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs @@ -1104,7 +1104,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed private void UpdateVertexBufferState() { IndexType indexType = _state.State.IndexBufferState.Type; - bool indexTypeSmall = indexType == IndexType.UByte || indexType == IndexType.UShort; + bool indexTypeSmall = indexType is IndexType.UByte or IndexType.UShort; _drawState.IsAnyVbInstanced = false; diff --git a/src/Ryujinx.Graphics.Gpu/GpuContext.cs b/src/Ryujinx.Graphics.Gpu/GpuContext.cs index d1c608dd6..d0b8277da 100644 --- a/src/Ryujinx.Graphics.Gpu/GpuContext.cs +++ b/src/Ryujinx.Graphics.Gpu/GpuContext.cs @@ -91,13 +91,13 @@ namespace Ryujinx.Graphics.Gpu /// Support buffer updater. /// internal SupportBufferUpdater SupportBufferUpdater { get; } - + /// /// Enabled dirty hacks. /// Used for workarounds to emulator bugs we can't fix/don't know how to fix yet. /// internal DirtyHacks DirtyHacks { get; } - + /// /// Host hardware capabilities. diff --git a/src/Ryujinx.Graphics.Gpu/GraphicsConfig.cs b/src/Ryujinx.Graphics.Gpu/GraphicsConfig.cs index 066ac28f7..715a4d92b 100644 --- a/src/Ryujinx.Graphics.Gpu/GraphicsConfig.cs +++ b/src/Ryujinx.Graphics.Gpu/GraphicsConfig.cs @@ -1,6 +1,5 @@ namespace Ryujinx.Graphics.Gpu { -#pragma warning disable CA2211 // Non-constant fields should not be visible /// /// General GPU and graphics configuration. /// @@ -9,25 +8,25 @@ namespace Ryujinx.Graphics.Gpu /// /// Resolution scale. /// - public static float ResScale = 1f; + public static float ResScale { get; set; } = 1f; /// /// Max Anisotropy. Values range from 0 - 16. Set to -1 to let the game decide. /// - public static float MaxAnisotropy = -1; + public static float MaxAnisotropy { get; set; } = -1; /// /// Base directory used to write shader code dumps. /// Set to null to disable code dumping. /// - public static string ShadersDumpPath; + public static string ShadersDumpPath { get; set; } /// /// Fast GPU time calculates the internal GPU time ticks as if the GPU was capable of /// processing commands almost instantly, instead of using the host timer. /// This can avoid lower resolution on some games when GPU performance is poor. /// - public static bool FastGpuTime = true; + public static bool FastGpuTime { get; set; } = true; /// /// Enables or disables fast 2d engine texture copies entirely on CPU when possible. @@ -35,43 +34,42 @@ namespace Ryujinx.Graphics.Gpu /// as textures will not need to be created for the copy, and the data does not need to be /// flushed from GPU. /// - public static bool Fast2DCopy = true; + public static bool Fast2DCopy { get; set; } = true; /// /// Enables or disables the Just-in-Time compiler for GPU Macro code. /// - public static bool EnableMacroJit = true; + public static bool EnableMacroJit { get; set; } = true; /// /// Enables or disables high-level emulation of common GPU Macro code. /// - public static bool EnableMacroHLE = true; - + public static bool EnableMacroHLE { get; set; } = true; + /// /// Title id of the current running game. /// Used by the shader cache. /// - public static string TitleId; + public static string TitleId { get; set; } /// /// Enables or disables the shader cache. /// - public static bool EnableShaderCache; + public static bool EnableShaderCache { get; set; } /// /// Enables or disables shader SPIR-V compilation. /// - public static bool EnableSpirvCompilationOnVulkan = true; + public static bool EnableSpirvCompilationOnVulkan { get; set; } = true; /// /// Enables or disables recompression of compressed textures that are not natively supported by the host. /// - public static bool EnableTextureRecompression = false; + public static bool EnableTextureRecompression { get; set; } = false; /// /// Enables or disables color space passthrough, if available. /// - public static bool EnableColorSpacePassthrough = false; + public static bool EnableColorSpacePassthrough { get; set; } = false; } -#pragma warning restore CA2211 } diff --git a/src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs b/src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs index afdbcbd3e..99b34112f 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs @@ -56,7 +56,6 @@ namespace Ryujinx.Graphics.Gpu.Image private const ulong TextureSizeCapacity8GiB = 6 * GiB; private const ulong TextureSizeCapacity12GiB = 12 * GiB; - private const float MemoryScaleFactor = 0.50f; private ulong _maxCacheMemoryUsage = DefaultTextureSizeCapacity; diff --git a/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs b/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs index 45e1971a8..ee217714c 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs @@ -10,7 +10,6 @@ namespace Ryujinx.Graphics.Gpu.Image static class FormatTable { #pragma warning disable IDE0055 // Disable formatting - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] private enum TextureFormat : uint { // Formats @@ -249,7 +248,6 @@ namespace Ryujinx.Graphics.Gpu.Image A5B5G5R1Unorm = A5B5G5R1 | RUnorm | GUnorm | BUnorm | AUnorm, // 0x24913 } - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] private enum VertexAttributeFormat : uint { // Width diff --git a/src/Ryujinx.Graphics.Gpu/Image/Pool.cs b/src/Ryujinx.Graphics.Gpu/Image/Pool.cs index e12fedc74..3cc65a92b 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/Pool.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/Pool.cs @@ -248,6 +248,7 @@ namespace Ryujinx.Graphics.Gpu.Image Items = null; } + _memoryTracking.Dispose(); } } diff --git a/src/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs b/src/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs index c742e1796..cd97d68dd 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs @@ -175,6 +175,7 @@ namespace Ryujinx.Graphics.Gpu.Image case SamplerMinFilter.Linear: return MinFilter.Linear; } + break; case SamplerMipFilter.Nearest: @@ -185,6 +186,7 @@ namespace Ryujinx.Graphics.Gpu.Image case SamplerMinFilter.Linear: return MinFilter.LinearMipmapNearest; } + break; case SamplerMipFilter.Linear: @@ -195,6 +197,7 @@ namespace Ryujinx.Graphics.Gpu.Image case SamplerMinFilter.Linear: return MinFilter.LinearMipmapLinear; } + break; } diff --git a/src/Ryujinx.Graphics.Gpu/Image/Texture.cs b/src/Ryujinx.Graphics.Gpu/Image/Texture.cs index 984d614d4..9540df548 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/Texture.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/Texture.cs @@ -1355,7 +1355,7 @@ namespace Ryujinx.Graphics.Gpu.Image /// True if anisotropic filtering can be forced, false otherwise private bool CanTextureForceAnisotropy() { - if (!(Target == Target.Texture2D || Target == Target.Texture2DArray)) + if (Target is not (Target.Texture2D or Target.Texture2DArray)) { return false; } @@ -1379,16 +1379,16 @@ namespace Ryujinx.Graphics.Gpu.Image { case Target.Texture1D: case Target.Texture1DArray: - return target == Target.Texture1D || target == Target.Texture1DArray; + return target is Target.Texture1D or Target.Texture1DArray; case Target.Texture2D: case Target.Texture2DArray: - return target == Target.Texture2D || target == Target.Texture2DArray; + return target is Target.Texture2D or Target.Texture2DArray; case Target.Cubemap: case Target.CubemapArray: - return target == Target.Cubemap || target == Target.CubemapArray; + return target is Target.Cubemap or Target.CubemapArray; case Target.Texture2DMultisample: case Target.Texture2DMultisampleArray: - return target == Target.Texture2DMultisample || target == Target.Texture2DMultisampleArray; + return target is Target.Texture2DMultisample or Target.Texture2DMultisampleArray; case Target.Texture3D: return target == Target.Texture3D; default: diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs index aa1ac1d57..35f099c67 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs @@ -784,8 +784,8 @@ namespace Ryujinx.Graphics.Gpu.Image samplerHandle = samplerWordOffset; } - if (handleType == TextureHandleType.SeparateSamplerId || - handleType == TextureHandleType.SeparateConstantSamplerHandle) + if (handleType is TextureHandleType.SeparateSamplerId or + TextureHandleType.SeparateConstantSamplerHandle) { samplerHandle <<= 20; } diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs index 8bed6363b..f2cbca832 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs @@ -207,8 +207,8 @@ namespace Ryujinx.Graphics.Gpu.Image return false; // Flushing this format is not supported, as it may have been converted to another host format. } - if (info.Target == Target.Texture2DMultisample || - info.Target == Target.Texture2DMultisampleArray) + if (info.Target is Target.Texture2DMultisample or + Target.Texture2DMultisampleArray) { return false; // Flushing multisample textures is not supported, the host does not allow getting their data. } @@ -758,43 +758,45 @@ namespace Ryujinx.Graphics.Gpu.Image { case Target.Texture1D: case Target.Texture1DArray: - result = rhs.Target == Target.Texture1D || - rhs.Target == Target.Texture1DArray; + result = rhs.Target is Target.Texture1D or + Target.Texture1DArray; break; case Target.Texture2D: - result = rhs.Target == Target.Texture2D || - rhs.Target == Target.Texture2DArray; + result = rhs.Target is Target.Texture2D or + Target.Texture2DArray; break; case Target.Texture2DArray: - result = rhs.Target == Target.Texture2D || - rhs.Target == Target.Texture2DArray; + result = rhs.Target is Target.Texture2D or + Target.Texture2DArray; - if (rhs.Target == Target.Cubemap || rhs.Target == Target.CubemapArray) + if (rhs.Target is Target.Cubemap or Target.CubemapArray) { return caps.SupportsCubemapView ? TextureViewCompatibility.Full : TextureViewCompatibility.CopyOnly; } + break; case Target.Cubemap: case Target.CubemapArray: - result = rhs.Target == Target.Cubemap || - rhs.Target == Target.CubemapArray; + result = rhs.Target is Target.Cubemap or + Target.CubemapArray; - if (rhs.Target == Target.Texture2D || rhs.Target == Target.Texture2DArray) + if (rhs.Target is Target.Texture2D or Target.Texture2DArray) { return caps.SupportsCubemapView ? TextureViewCompatibility.Full : TextureViewCompatibility.CopyOnly; } + break; case Target.Texture2DMultisample: case Target.Texture2DMultisampleArray: - if (rhs.Target == Target.Texture2D || rhs.Target == Target.Texture2DArray) + if (rhs.Target is Target.Texture2D or Target.Texture2DArray) { return TextureViewCompatibility.CopyOnly; } - result = rhs.Target == Target.Texture2DMultisample || - rhs.Target == Target.Texture2DMultisampleArray; + result = rhs.Target is Target.Texture2DMultisample or + Target.Texture2DMultisampleArray; break; case Target.Texture3D: diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs index 8c27e286a..7f38df129 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs @@ -218,7 +218,6 @@ namespace Ryujinx.Graphics.Gpu.Image } } - /// /// Flushes incompatible overlaps if the storage format requires it, and they have been modified. /// This allows unsupported host formats to accept data written to format aliased textures. @@ -1133,7 +1132,6 @@ namespace Ryujinx.Graphics.Gpu.Image SignalAllDirty(); } - /// /// Removes a view from the group, removing it from all overlap lists. /// diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureInfo.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureInfo.cs index 94d2e0bfc..cb2ccf54d 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureInfo.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureInfo.cs @@ -216,7 +216,7 @@ namespace Ryujinx.Graphics.Gpu.Image /// The number of texture layers public static int GetLayers(Target target, int depthOrLayers) { - if (target == Target.Texture2DArray || target == Target.Texture2DMultisampleArray) + if (target is Target.Texture2DArray or Target.Texture2DMultisampleArray) { return depthOrLayers; } @@ -241,7 +241,7 @@ namespace Ryujinx.Graphics.Gpu.Image /// The number of texture slices public int GetSlices() { - if (Target == Target.Texture3D || Target == Target.Texture2DArray || Target == Target.Texture2DMultisampleArray) + if (Target is Target.Texture3D or Target.Texture2DArray or Target.Texture2DMultisampleArray) { return DepthOrLayers; } diff --git a/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs b/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs index 4a16fa90a..fd1609c23 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs @@ -454,6 +454,7 @@ namespace Ryujinx.Graphics.Gpu.Image // If this is null, a request was already queued to decrement reference. texture.DecrementReferenceCount(this, request.ID); } + continue; } } @@ -544,7 +545,7 @@ namespace Ryujinx.Graphics.Gpu.Image int width = target == Target.TextureBuffer ? descriptor.UnpackBufferTextureWidth() : descriptor.UnpackWidth(); int height = descriptor.UnpackHeight(); - if (target == Target.Texture2DMultisample || target == Target.Texture2DMultisampleArray) + if (target is Target.Texture2DMultisample or Target.Texture2DMultisampleArray) { // This is divided back before the backend texture is created. width *= samplesInX; @@ -699,8 +700,8 @@ namespace Ryujinx.Graphics.Gpu.Image { int maxSize = width; - if (target != Target.Texture1D && - target != Target.Texture1DArray) + if (target is not Target.Texture1D and + not Target.Texture1DArray) { maxSize = Math.Max(maxSize, height); } @@ -761,8 +762,8 @@ namespace Ryujinx.Graphics.Gpu.Image /// True if the swizzle component is equal to the red or green, false otherwise private static bool IsRG(SwizzleComponent component) { - return component == SwizzleComponent.Red || - component == SwizzleComponent.Green; + return component is SwizzleComponent.Red or + SwizzleComponent.Green; } /// diff --git a/src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs b/src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs index 227ff1253..a2448d76f 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs @@ -705,7 +705,7 @@ namespace Ryujinx.Graphics.Gpu.Memory { BufferHandle handle = Handle; - return (ulong address, ulong size, ulong _) => + return (address, size, _) => { FlushImpl(handle, address, size); }; diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs index 56bc9143f..a9b1f50e2 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs @@ -63,7 +63,7 @@ namespace Ryujinx.Graphics.Gpu.Memory // Backend managed is always auto, unified memory is always host. _desiredType = BufferBackingType.HostMemory; - _canSwap = _systemMemoryType != SystemMemoryType.BackendManaged && _systemMemoryType != SystemMemoryType.UnifiedMemory; + _canSwap = _systemMemoryType is not SystemMemoryType.BackendManaged and not SystemMemoryType.UnifiedMemory; if (_canSwap) { diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferStage.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferStage.cs index d56abda28..8a9f37658 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/BufferStage.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferStage.cs @@ -29,10 +29,7 @@ namespace Ryujinx.Graphics.Gpu.Memory StorageRead = 0x40, StorageWrite = 0x80, - -#pragma warning disable CA1069 // Enums values should not be duplicated StorageAtomic = 0xc0 -#pragma warning restore CA1069 // Enums values should not be duplicated } /// diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferUpdater.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferUpdater.cs index fab78971d..f7fc65a4e 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/BufferUpdater.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferUpdater.cs @@ -76,7 +76,7 @@ namespace Ryujinx.Graphics.Gpu.Memory BufferRange range = new(_handle, 0, data.Length); _renderer.Pipeline.SetUniformBuffers([new BufferAssignment(0, range)]); } - }; + } _renderer.SetBufferData(_handle, _startOffset, data[_startOffset.._endOffset]); diff --git a/src/Ryujinx.Graphics.Gpu/Memory/PhysicalMemory.cs b/src/Ryujinx.Graphics.Gpu/Memory/PhysicalMemory.cs index 8a78b99e0..0b1424b8a 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/PhysicalMemory.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/PhysicalMemory.cs @@ -157,6 +157,7 @@ namespace Ryujinx.Graphics.Gpu.Memory { _cpuMemory.GetSpan(currentRange.Address, size, tracked).CopyTo(data.Slice(offset, size)); } + offset += size; } @@ -204,6 +205,7 @@ namespace Ryujinx.Graphics.Gpu.Memory { GetSpan(currentRange.Address, size).CopyTo(memorySpan.Slice(offset, size)); } + offset += size; } @@ -339,6 +341,7 @@ namespace Ryujinx.Graphics.Gpu.Memory { writeCallback(currentRange.Address, data.Slice(offset, size)); } + offset += size; } } diff --git a/src/Ryujinx.Graphics.Gpu/Memory/PteKind.cs b/src/Ryujinx.Graphics.Gpu/Memory/PteKind.cs index 1585328f0..bdaddc1ee 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/PteKind.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/PteKind.cs @@ -262,7 +262,7 @@ namespace Ryujinx.Graphics.Gpu.Memory /// True if pitch, false otherwise public static bool IsPitch(this PteKind kind) { - return kind == PteKind.Pitch || kind == PteKind.PitchNoSwizzle; + return kind is PteKind.Pitch or PteKind.PitchNoSwizzle; } } } diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BackgroundDiskCacheWriter.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BackgroundDiskCacheWriter.cs index e0f17ba9c..0e89a20a1 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BackgroundDiskCacheWriter.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BackgroundDiskCacheWriter.cs @@ -108,6 +108,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache { Logger.Error?.Print(LogClass.Gpu, $"Error writing shader to disk cache. {ioException.Message}"); } + break; } } diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BinarySerializer.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BinarySerializer.cs index 3837092c9..76975c13b 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BinarySerializer.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BinarySerializer.cs @@ -203,6 +203,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache { offset += stream.Read(data[offset..]); } + stream.Dispose(); break; case CompressionAlgorithm.Brotli: @@ -211,6 +212,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache { offset += stream.Read(data[offset..]); } + stream.Dispose(); break; } diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGuestStorage.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGuestStorage.cs index f8fa06482..1e2f9146f 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGuestStorage.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGuestStorage.cs @@ -379,8 +379,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache /// Code and constant buffer data hash /// Entry index private int WriteNewEntry( - Stream tocFileStream, - Stream dataFileStream, + FileStream tocFileStream, + FileStream dataFileStream, ref TocHeader header, ReadOnlySpan data, ReadOnlySpan cb1Data, diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs index 22ffe4812..6444b18e3 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs @@ -737,7 +737,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache /// Magic value to be written /// Shader codegen version, only valid for the host file /// File creation timestamp - private static void CreateToc(Stream tocFileStream, ref TocHeader header, uint magic, uint codegenVersion, ulong timestamp) + private static void CreateToc(FileStream tocFileStream, ref TocHeader header, uint magic, uint codegenVersion, ulong timestamp) { BinarySerializer writer = new(tocFileStream); diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ShaderBinarySerializer.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ShaderBinarySerializer.cs index 8e8bf8e5e..f30973a09 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ShaderBinarySerializer.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ShaderBinarySerializer.cs @@ -1,3 +1,4 @@ +using Microsoft.IO; using Ryujinx.Common; using Ryujinx.Common.Memory; using Ryujinx.Graphics.GAL; @@ -12,7 +13,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache { public static byte[] Pack(ShaderSource[] sources) { - using MemoryStream output = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream output = MemoryStreamManager.Shared.GetStream(); output.Write(sources.Length); diff --git a/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs b/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs index 765bef7d4..694b67ab9 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs @@ -133,7 +133,7 @@ namespace Ryujinx.Graphics.Gpu.Shader }; } - bool isQuad = Topology == PrimitiveTopology.Quads || Topology == PrimitiveTopology.QuadStrip; + bool isQuad = Topology is PrimitiveTopology.Quads or PrimitiveTopology.QuadStrip; bool halvePrimitiveId = !hostSupportsQuads && !hasGeometryShader && isQuad; return new GpuGraphicsState( diff --git a/src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs b/src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs index 1134b0c6b..f78bad75d 100644 --- a/src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs +++ b/src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs @@ -12,8 +12,8 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native private static readonly Dictionary _librariesWhitelist = new() { - { AvCodecLibraryName, (58, 61) }, - { AvUtilLibraryName, (56, 59) }, + { AvCodecLibraryName, (59, 60) }, + { AvUtilLibraryName, (57, 58) }, }; private static string FormatLibraryNameForCurrentOs(string libraryName, int version) @@ -36,7 +36,6 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native } } - private static bool TryLoadWhitelistedLibrary(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out nint handle) { handle = nint.Zero; diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/BitDepth.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/BitDepth.cs index 1f0c65c7b..fdf0aff9c 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/BitDepth.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/BitDepth.cs @@ -6,4 +6,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 Bits10 = 10, // < 10 bits Bits12 = 12, // < 12 bits } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/CodecErr.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/CodecErr.cs index 9bcf4ac01..331e0c13f 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/CodecErr.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/CodecErr.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9 +namespace Ryujinx.Graphics.Nvdec.Vp9 { internal enum CodecErr { @@ -49,18 +49,18 @@ /// UnsupFeature, - /// - /// The coded data for this stream is corrupt or incomplete. - /// - /// - /// There was a problem decoding the current frame.
- /// This return code should only be used - /// for failures that prevent future pictures from being properly decoded.
- ///
- /// This error MAY be treated as fatal to the stream or MAY be treated as fatal to the current GOP.
- /// If decoding is continued for the current GOP, artifacts may be present. - ///
- CorruptFrame, + /// + /// The coded data for this stream is corrupt or incomplete. + /// + /// + /// There was a problem decoding the current frame.
+ /// This return code should only be used + /// for failures that prevent future pictures from being properly decoded.
+ ///
+ /// This error MAY be treated as fatal to the stream or MAY be treated as fatal to the current GOP.
+ /// If decoding is continued for the current GOP, artifacts may be present. + ///
+ CorruptFrame, /// /// An application-supplied parameter is not valid. @@ -72,4 +72,4 @@ /// ListEnd } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Common/BitUtils.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Common/BitUtils.cs index 900b9d1c1..82a2aa47f 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Common/BitUtils.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Common/BitUtils.cs @@ -56,4 +56,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common return numValues > 0 ? GetMsb(numValues) + 1 : 0; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Common/MemoryAllocator.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Common/MemoryAllocator.cs index 6d108d86e..c98052094 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Common/MemoryAllocator.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Common/MemoryAllocator.cs @@ -61,7 +61,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common ArrayPtr allocation = new(ptr, length); - allocation.AsSpan().Fill(default); + allocation.AsSpan().Clear(); return allocation; } diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Common/MemoryUtil.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Common/MemoryUtil.cs index 66c41f8cc..afdc6b0b2 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Common/MemoryUtil.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Common/MemoryUtil.cs @@ -20,4 +20,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common new Span(ptr, length).Fill(value); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Constants.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Constants.cs index 4d7f919e5..69a34239d 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Constants.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Constants.cs @@ -1,4 +1,4 @@ -using Ryujinx.Graphics.Nvdec.Vp9.Types; +using Ryujinx.Graphics.Nvdec.Vp9.Types; namespace Ryujinx.Graphics.Nvdec.Vp9 { @@ -97,4 +97,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 public const int SkipContexts = 3; public const int InterModeContexts = 7; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/DSubExp.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/DSubExp.cs index 72cfba8f3..b25f04ad0 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/DSubExp.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/DSubExp.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using System.Diagnostics; namespace Ryujinx.Graphics.Nvdec.Vp9 { @@ -44,4 +44,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 return Prob.MaxProb - InvRecenterNonneg(v, Prob.MaxProb - 1 - m); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/DecodeFrame.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/DecodeFrame.cs index 3e7d6b030..541f29e96 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/DecodeFrame.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/DecodeFrame.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Dsp; using Ryujinx.Graphics.Nvdec.Vp9.Types; @@ -63,7 +63,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { for (int j = 0; j < Constants.InterModes - 1; ++j) { - r.DiffUpdateProb( ref fc.InterModeProb[i][j]); + r.DiffUpdateProb(ref fc.InterModeProb[i][j]); } } } @@ -172,15 +172,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { if (txSize <= TxSize.Tx16X16 && eob <= 10) { - dqcoeff.AsSpan().Slice(0, 4 * (4 << (int)txSize)).Clear(); + dqcoeff.AsSpan()[..(4 * (4 << (int)txSize))].Clear(); } else if (txSize == TxSize.Tx32X32 && eob <= 34) { - dqcoeff.AsSpan().Slice(0, 256).Clear(); + dqcoeff.AsSpan()[..256].Clear(); } else { - dqcoeff.AsSpan().Slice(0, 16 << ((int)txSize << 1)).Clear(); + dqcoeff.AsSpan()[..(16 << ((int)txSize << 1))].Clear(); } } } @@ -263,15 +263,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { if (txType == TxType.DctDct && txSize <= TxSize.Tx16X16 && eob <= 10) { - dqcoeff.AsSpan().Slice(0, 4 * (4 << (int)txSize)).Clear(); + dqcoeff.AsSpan()[..(4 * (4 << (int)txSize))].Clear(); } else if (txSize == TxSize.Tx32X32 && eob <= 34) { - dqcoeff.AsSpan().Slice(0, 256).Clear(); + dqcoeff.AsSpan()[..256].Clear(); } else { - dqcoeff.AsSpan().Slice(0, 16 << ((int)txSize << 1)).Clear(); + dqcoeff.AsSpan()[..(16 << ((int)txSize << 1))].Clear(); } } } @@ -289,7 +289,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 PredictionMode mode = plane == 0 ? mi.Mode : mi.UvMode; int dstOffset = (4 * row * pd.Dst.Stride) + (4 * col); byte* dst = &pd.Dst.Buf.ToPointer()[dstOffset]; - Span dstSpan = pd.Dst.Buf.AsSpan().Slice(dstOffset); + Span dstSpan = pd.Dst.Buf.AsSpan()[dstOffset..]; if (mi.SbType < BlockSize.Block8X8) { @@ -329,7 +329,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 ref MacroBlockDPlane pd = ref xd.Plane[plane]; Luts.ScanOrder sc = Luts.DefaultScanOrders[(int)txSize]; int eob = Detokenize.DecodeBlockTokens(ref twd, plane, sc, col, row, txSize, mi.SegmentId); - Span dst = pd.Dst.Buf.AsSpan().Slice((4 * row * pd.Dst.Stride) + (4 * col)); + Span dst = pd.Dst.Buf.AsSpan()[((4 * row * pd.Dst.Stride) + (4 * col))..]; if (eob > 0) { @@ -1024,8 +1024,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 // Update the partition context at the end notes. Set partition bits // of block sizes larger than the current one to be one, and partition // bits of smaller block sizes to be zero. - aboveCtx.Slice(0, bw).Fill(Luts.PartitionContextLookup[(int)subsize].Above); - leftCtx.Slice(0, bw).Fill(Luts.PartitionContextLookup[(int)subsize].Left); + aboveCtx[..bw].Fill(Luts.PartitionContextLookup[(int)subsize].Above); + leftCtx[..bw].Fill(Luts.PartitionContextLookup[(int)subsize].Left); } private static PartitionType ReadPartition( @@ -1174,7 +1174,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { for (int m = 0; m < Entropy.UnconstrainedNodes; ++m) { - r.DiffUpdateProb( ref coefProbs[i][j][k][l][m]); + r.DiffUpdateProb(ref coefProbs[i][j][k][l][m]); } } } @@ -1262,9 +1262,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 private static void SetupFrameSize(MemoryAllocator allocator, ref Vp9Common cm, ref ReadBitBuffer rb) { - int width = 0, height = 0; ref BufferPool pool = ref cm.BufferPool.Value; - rb.ReadFrameSize(out width, out height); + rb.ReadFrameSize(out int width, out int height); cm.ResizeContextBuffers(allocator, width, height); SetupRenderSize(ref cm, ref rb); @@ -1608,13 +1607,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 GetTileBuffers(ref cm, data, tileCols, ref tileBuffers); - tileBuffers.AsSpan().Slice(0, tileCols).Sort(CompareTileBuffers); + tileBuffers.AsSpan()[..tileCols].Sort(CompareTileBuffers); if (numWorkers == tileCols) { TileBuffer largest = tileBuffers[0]; Span buffers = tileBuffers.AsSpan(); - buffers.Slice(1).CopyTo(buffers.Slice(0, tileBuffers.Length - 1)); + buffers[1..].CopyTo(buffers[..(tileBuffers.Length - 1)]); tileBuffers[tileCols - 1] = largest; } else @@ -1734,9 +1733,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 private static bool ReadSyncCode(ref ReadBitBuffer rb) { - return rb.ReadLiteral(8) == SyncCode0 && - rb.ReadLiteral(8) == SyncCode1 && - rb.ReadLiteral(8) == SyncCode2; + int readSyncCode0 = rb.ReadLiteral(8); + int readSyncCode1 = rb.ReadLiteral(8); + int readSyncCode2 = rb.ReadLiteral(8); + + return readSyncCode0 == SyncCode0 && + readSyncCode1 == SyncCode1 && + readSyncCode2 == SyncCode2; } private static void RefCntFb(ref Array12 bufs, ref int idx, int newIdx) @@ -2014,7 +2017,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 for (int i = 0; i < Constants.IntraInterContexts; i++) { - r.DiffUpdateProb( ref fc.IntraInterProb[i]); + r.DiffUpdateProb(ref fc.IntraInterProb[i]); } cm.ReferenceMode = cm.ReadFrameReferenceMode(ref r); @@ -2029,7 +2032,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { for (int i = 0; i < Constants.IntraModes - 1; ++i) { - r.DiffUpdateProb( ref fc.YModeProb[j][i]); + r.DiffUpdateProb(ref fc.YModeProb[j][i]); } } @@ -2037,7 +2040,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { for (int i = 0; i < Constants.PartitionTypes - 1; ++i) { - r.DiffUpdateProb( ref fc.PartitionProb[j][i]); + r.DiffUpdateProb(ref fc.PartitionProb[j][i]); } } @@ -2119,7 +2122,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 allocator.Free(cm.TileWorkerData); } - cm.CheckMemError( ref cm.TileWorkerData, allocator.Allocate(numTileWorkers)); + cm.CheckMemError(ref cm.TileWorkerData, allocator.Allocate(numTileWorkers)); cm.TotalTiles = tileRows * tileCols; } @@ -2168,4 +2171,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/DecodeMv.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/DecodeMv.cs index 8b7ad4de1..b2c8d494d 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/DecodeMv.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/DecodeMv.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Dsp; using Ryujinx.Graphics.Nvdec.Vp9.Types; using Ryujinx.Graphics.Video; @@ -59,9 +59,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { switch (maxTxSize) { - case TxSize.Tx8X8: return fc.Tx8x8Prob[ctx].AsSpan(); - case TxSize.Tx16X16: return fc.Tx16x16Prob[ctx].AsSpan(); - case TxSize.Tx32X32: return fc.Tx32x32Prob[ctx].AsSpan(); + case TxSize.Tx8X8: + return fc.Tx8x8Prob[ctx].AsSpan(); + case TxSize.Tx16X16: + return fc.Tx16x16Prob[ctx].AsSpan(); + case TxSize.Tx32X32: + return fc.Tx32x32Prob[ctx].AsSpan(); default: Debug.Assert(false, "Invalid maxTxSize."); return ReadOnlySpan.Empty; @@ -72,9 +75,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { switch (maxTxSize) { - case TxSize.Tx8X8: return counts.Tx8x8[ctx].AsSpan(); - case TxSize.Tx16X16: return counts.Tx16x16[ctx].AsSpan(); - case TxSize.Tx32X32: return counts.Tx32x32[ctx].AsSpan(); + case TxSize.Tx8X8: + return counts.Tx8x8[ctx].AsSpan(); + case TxSize.Tx16X16: + return counts.Tx16x16[ctx].AsSpan(); + case TxSize.Tx32X32: + return counts.Tx32x32[ctx].AsSpan(); default: Debug.Assert(false, "Invalid maxTxSize."); return Span.Empty; @@ -129,13 +135,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } } - Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments); + Debug.Assert(segmentId is >= 0 and < Constants.MaxSegments); return segmentId; } private static void SetSegmentId(ref Vp9Common cm, int miOffset, int xMis, int yMis, int segmentId) { - Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments); + Debug.Assert(segmentId is >= 0 and < Constants.MaxSegments); for (int y = 0; y < yMis; y++) { @@ -412,7 +418,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { BlockSize bsize = mi.SbType; - switch (bsize) { case BlockSize.Block4X4: @@ -494,7 +499,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 ZeroPair(ref mv); break; } - default: return false; + default: + return false; } return ret; @@ -609,7 +615,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 bool earlyBreak = mode != PredictionMode.NearMv; // Blank the reference vector list - mvRefList.Slice(0, Constants.MaxMvRefCandidates).Fill(new Mv()); + mvRefList[..Constants.MaxMvRefCandidates].Clear(); i = 0; if (isSub8X8 != 0) @@ -760,7 +766,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 refmvCount = 1; } - Done: + Done: // Clamp vectors for (i = 0; i < refmvCount; ++i) { @@ -950,7 +956,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 int j = (idy * 2) + idx; bMode = ReadInterMode(ref cm, ref xd, ref r, interModeCtx); - if (bMode == PredictionMode.NearestMv || bMode == PredictionMode.NearMv) + if (bMode is PredictionMode.NearestMv or PredictionMode.NearMv) { for (refr = 0; refr < 1 + isCompound; ++refr) { @@ -1018,7 +1024,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 private static PredictionMode LeftBlockMode(Ptr curMi, Ptr leftMi, int b) { - if (b == 0 || b == 2) + if (b is 0 or 2) { if (leftMi.IsNull || leftMi.Value.IsInterBlock()) { @@ -1028,13 +1034,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 return leftMi.Value.GetYMode(b + 1); } - Debug.Assert(b == 1 || b == 3); + Debug.Assert(b is 1 or 3); return curMi.Value.Bmi[b - 1].Mode; } private static PredictionMode AboveBlockMode(Ptr curMi, Ptr aboveMi, int b) { - if (b == 0 || b == 1) + if (b is 0 or 1) { if (aboveMi.IsNull || aboveMi.Value.IsInterBlock()) { @@ -1044,7 +1050,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 return aboveMi.Value.GetYMode(b + 2); } - Debug.Assert(b == 2 || b == 3); + Debug.Assert(b is 2 or 3); return curMi.Value.Bmi[b - 2].Mode; } @@ -1154,4 +1160,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Decoder.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Decoder.cs index 009611b27..f788d57f4 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Decoder.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Decoder.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Types; using Ryujinx.Graphics.Video; @@ -29,49 +29,53 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 ReadOnlySpan mvsIn, Span mvsOut) { - Vp9Common cm = new(); + Vp9Common cm = new() + { + FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame, + IntraOnly = pictureInfo.IntraOnly, - cm.FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame; - cm.IntraOnly = pictureInfo.IntraOnly; + Width = output.Width, + Height = output.Height, + SubsamplingX = 1, + SubsamplingY = 1, - cm.Width = output.Width; - cm.Height = output.Height; - cm.SubsamplingX = 1; - cm.SubsamplingY = 1; + UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs, - cm.UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs; + RefFrameSignBias = pictureInfo.RefFrameSignBias, - cm.RefFrameSignBias = pictureInfo.RefFrameSignBias; + BaseQindex = pictureInfo.BaseQIndex, + YDcDeltaQ = pictureInfo.YDcDeltaQ, + UvAcDeltaQ = pictureInfo.UvAcDeltaQ, + UvDcDeltaQ = pictureInfo.UvDcDeltaQ, - cm.BaseQindex = pictureInfo.BaseQIndex; - cm.YDcDeltaQ = pictureInfo.YDcDeltaQ; - cm.UvAcDeltaQ = pictureInfo.UvAcDeltaQ; - cm.UvDcDeltaQ = pictureInfo.UvDcDeltaQ; + TxMode = (TxMode)pictureInfo.TransformMode, + + AllowHighPrecisionMv = pictureInfo.AllowHighPrecisionMv, + + InterpFilter = (byte)pictureInfo.InterpFilter, + + ReferenceMode = (ReferenceMode)pictureInfo.ReferenceMode, + + CompFixedRef = pictureInfo.CompFixedRef, + CompVarRef = pictureInfo.CompVarRef, + + BitDepth = BitDepth.Bits8, + + Log2TileCols = pictureInfo.Log2TileCols, + Log2TileRows = pictureInfo.Log2TileRows, + + Fc = new Ptr(ref pictureInfo.Entropy), + Counts = new Ptr(ref pictureInfo.BackwardUpdateCounts) + }; cm.Mb.Lossless = pictureInfo.Lossless; cm.Mb.Bd = 8; - cm.TxMode = (TxMode)pictureInfo.TransformMode; - - cm.AllowHighPrecisionMv = pictureInfo.AllowHighPrecisionMv; - - cm.InterpFilter = (byte)pictureInfo.InterpFilter; - if (cm.InterpFilter != Constants.Switchable) { cm.InterpFilter = LiteralToFilter[cm.InterpFilter]; } - cm.ReferenceMode = (ReferenceMode)pictureInfo.ReferenceMode; - - cm.CompFixedRef = pictureInfo.CompFixedRef; - cm.CompVarRef = pictureInfo.CompVarRef; - - cm.BitDepth = BitDepth.Bits8; - - cm.Log2TileCols = pictureInfo.Log2TileCols; - cm.Log2TileRows = pictureInfo.Log2TileRows; - cm.Seg.Enabled = pictureInfo.SegmentEnabled; cm.Seg.UpdateMap = pictureInfo.SegmentMapUpdate; cm.Seg.TemporalUpdate = pictureInfo.SegmentMapTemporalUpdate; @@ -85,9 +89,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 cm.Lf.RefDeltas = pictureInfo.RefDeltas; cm.Lf.ModeDeltas = pictureInfo.ModeDeltas; - cm.Fc = new Ptr(ref pictureInfo.Entropy); - cm.Counts = new Ptr(ref pictureInfo.BackwardUpdateCounts); - cm.FrameRefs[0].Buf = (Surface)pictureInfo.LastReference; cm.FrameRefs[1].Buf = (Surface)pictureInfo.GoldenReference; cm.FrameRefs[2].Buf = (Surface)pictureInfo.AltReference; @@ -164,4 +165,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 _allocator.Dispose(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Detokenize.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Detokenize.cs index 092d298dc..530eec441 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Detokenize.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Detokenize.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Dsp; using Ryujinx.Graphics.Nvdec.Vp9.Types; using Ryujinx.Graphics.Video; @@ -48,7 +48,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 ReadOnlySpan cat6Prob = xd.Bd == 12 ? Luts.Cat6ProbHigh12 : xd.Bd == 10 - ? Luts.Cat6ProbHigh12.Slice(2) + ? Luts.Cat6ProbHigh12[2..] : Luts.Cat6Prob; int cat6Bits = xd.Bd == 12 ? 18 : xd.Bd == 10 ? 16 : 14; // Keep value, range, and count as locals. The compiler produces better @@ -61,7 +61,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { int val = -1; band = bandTranslate[0]; - bandTranslate = bandTranslate.Slice(1); + bandTranslate = bandTranslate[1..]; ref Array3 prob = ref coefProbs[band][ctx]; if (!xd.Counts.IsNull) { @@ -98,7 +98,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 ctx = GetCoefContext(nb, tokenCache, c); band = bandTranslate[0]; - bandTranslate = bandTranslate.Slice(1); + bandTranslate = bandTranslate[1..]; prob = ref coefProbs[band][ctx]; } @@ -234,8 +234,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 ref MacroBlockDPlane pd = ref xd.Plane[plane]; ref Array2 dequant = ref pd.SegDequant[segId]; int eob; - Span a = pd.AboveContext.AsSpan().Slice(x); - Span l = pd.LeftContext.AsSpan().Slice(y); + Span a = pd.AboveContext.AsSpan()[x..]; + Span l = pd.LeftContext.AsSpan()[y..]; int ctx; int ctxShiftA = 0; int ctxShiftL = 0; @@ -320,4 +320,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 return eob; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Convolve.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Convolve.cs index 8cea09aec..839a9c400 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Convolve.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Convolve.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using System.Diagnostics; using System.Runtime.CompilerServices; @@ -944,4 +944,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Filter.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Filter.cs index 1dbbc8de5..a32221e09 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Filter.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Filter.cs @@ -9,4 +9,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp public const int SubpelShifts = 1 << SubpelBits; public const int SubpelTaps = 8; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/IntraPred.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/IntraPred.cs index df72e160d..926cc88e3 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/IntraPred.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/IntraPred.cs @@ -1,4 +1,4 @@ -using Ryujinx.Graphics.Nvdec.Vp9.Common; +using Ryujinx.Graphics.Nvdec.Vp9.Common; namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp { diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/InvTxfm.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/InvTxfm.cs index a36ea2dcf..7a1601395 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/InvTxfm.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/InvTxfm.cs @@ -1,4 +1,4 @@ -using Ryujinx.Graphics.Nvdec.Vp9.Common; +using Ryujinx.Graphics.Nvdec.Vp9.Common; using System; using System.Diagnostics; using System.Runtime.CompilerServices; @@ -114,8 +114,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp op[1] = WrapLow(b1); op[2] = WrapLow(c1); op[3] = WrapLow(d1); - ip = ip.Slice(4); - op = op.Slice(4); + ip = ip[4..]; + op = op[4..]; } Span ip2 = output; @@ -137,8 +137,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[stride * 2] = ClipPixelAdd(dest[stride * 2], WrapLow(c1)); dest[stride * 3] = ClipPixelAdd(dest[stride * 3], WrapLow(d1)); - ip2 = ip2.Slice(1); - dest = dest.Slice(1); + ip2 = ip2[1..]; + dest = dest[1..]; } } @@ -165,8 +165,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[stride * 1] = ClipPixelAdd(dest[stride * 1], e1); dest[stride * 2] = ClipPixelAdd(dest[stride * 2], e1); dest[stride * 3] = ClipPixelAdd(dest[stride * 3], e1); - ip2 = ip2.Slice(1); - dest = dest.Slice(1); + ip2 = ip2[1..]; + dest = dest[1..]; } } @@ -180,7 +180,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if ((x0 | x1 | x2 | x3) == 0) { - output.Slice(0, 4).Clear(); + output[..4].Clear(); return; } @@ -244,8 +244,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 4; ++i) { Idct4(input, outptr); - input = input.Slice(4); - outptr = outptr.Slice(4); + input = input[4..]; + outptr = outptr[4..]; } // Columns @@ -279,7 +279,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[1] = ClipPixelAdd(dest[1], a1); dest[2] = ClipPixelAdd(dest[2], a1); dest[3] = ClipPixelAdd(dest[3], a1); - dest = dest.Slice(stride); + dest = dest[stride..]; } } @@ -297,7 +297,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7) == 0) { - output.Slice(0, 8).Clear(); + output[..8].Clear(); return; } @@ -430,8 +430,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 8; ++i) { Idct8(input, outptr); - input = input.Slice(8); - outptr = outptr.Slice(8); + input = input[8..]; + outptr = outptr[8..]; } // Then transform columns @@ -466,8 +466,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 4; ++i) { Idct8(input, outptr); - input = input.Slice(8); - outptr = outptr.Slice(8); + input = input[8..]; + outptr = outptr[8..]; } // Then transform columns @@ -501,7 +501,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[i] = ClipPixelAdd(dest[i], a1); } - dest = dest.Slice(stride); + dest = dest[stride..]; } } @@ -528,7 +528,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15) == 0) { - output.Slice(0, 16).Clear(); + output[..16].Clear(); return; } @@ -854,8 +854,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 16; ++i) { Idct16(input, outptr); - input = input.Slice(16); - outptr = outptr.Slice(16); + input = input[16..]; + outptr = outptr[16..]; } // Then transform columns @@ -890,8 +890,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 8; ++i) { Idct16(input, outptr); - input = input.Slice(16); - outptr = outptr.Slice(16); + input = input[16..]; + outptr = outptr[16..]; } // Then transform columns @@ -926,8 +926,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 4; ++i) { Idct16(input, outptr); - input = input.Slice(16); - outptr = outptr.Slice(16); + input = input[16..]; + outptr = outptr[16..]; } // Then transform columns @@ -961,7 +961,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[i] = ClipPixelAdd(dest[i], a1); } - dest = dest.Slice(stride); + dest = dest[stride..]; } } @@ -1358,11 +1358,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp } else { - outptr.Slice(0, 32).Clear(); + outptr[..32].Clear(); } - input = input.Slice(32); - outptr = outptr.Slice(32); + input = input[32..]; + outptr = outptr[32..]; } // Columns @@ -1397,8 +1397,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 16; ++i) { Idct32(input, outptr); - input = input.Slice(32); - outptr = outptr.Slice(32); + input = input[32..]; + outptr = outptr[32..]; } // Columns @@ -1433,8 +1433,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 8; ++i) { Idct32(input, outptr); - input = input.Slice(32); - outptr = outptr.Slice(32); + input = input[32..]; + outptr = outptr[32..]; } // Columns @@ -1469,7 +1469,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[i] = ClipPixelAdd(dest[i], a1); } - dest = dest.Slice(stride); + dest = dest[stride..]; } } @@ -1501,8 +1501,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp op[1] = HighbdWrapLow(b1, bd); op[2] = HighbdWrapLow(c1, bd); op[3] = HighbdWrapLow(d1, bd); - ip = ip.Slice(4); - op = op.Slice(4); + ip = ip[4..]; + op = op[4..]; } ReadOnlySpan ip2 = output; @@ -1524,8 +1524,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[stride * 2] = HighbdClipPixelAdd(dest[stride * 2], HighbdWrapLow(c1, bd), bd); dest[stride * 3] = HighbdClipPixelAdd(dest[stride * 3], HighbdWrapLow(d1, bd), bd); - ip2 = ip2.Slice(1); - dest = dest.Slice(1); + ip2 = ip2[1..]; + dest = dest[1..]; } } @@ -1552,8 +1552,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[stride * 1] = HighbdClipPixelAdd(dest[stride * 1], e1, bd); dest[stride * 2] = HighbdClipPixelAdd(dest[stride * 2], e1, bd); dest[stride * 3] = HighbdClipPixelAdd(dest[stride * 3], e1, bd); - ip2 = ip2.Slice(1); - dest = dest.Slice(1); + ip2 = ip2[1..]; + dest = dest[1..]; } } @@ -1568,13 +1568,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if (DetectInvalidHighbdInput(input, 4) != 0) { Debug.Assert(false, "invalid highbd txfm input"); - output.Slice(0, 4).Clear(); + output[..4].Clear(); return; } if ((x0 | x1 | x2 | x3) == 0) { - output.Slice(0, 4).Clear(); + output[..4].Clear(); return; } @@ -1611,7 +1611,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if (DetectInvalidHighbdInput(input, 4) != 0) { Debug.Assert(false, "invalid highbd txfm input"); - output.Slice(0, 4).Clear(); + output[..4].Clear(); return; } @@ -1644,8 +1644,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 4; ++i) { HighbdIdct4(input, outptr, bd); - input = input.Slice(4); - outptr = outptr.Slice(4); + input = input[4..]; + outptr = outptr[4..]; } // Columns @@ -1679,7 +1679,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[1] = HighbdClipPixelAdd(dest[1], a1, bd); dest[2] = HighbdClipPixelAdd(dest[2], a1, bd); dest[3] = HighbdClipPixelAdd(dest[3], a1, bd); - dest = dest.Slice(stride); + dest = dest[stride..]; } } @@ -1698,13 +1698,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if (DetectInvalidHighbdInput(input, 8) != 0) { Debug.Assert(false, "invalid highbd txfm input"); - output.Slice(0, 8).Clear(); + output[..8].Clear(); return; } if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7) == 0) { - output.Slice(0, 8).Clear(); + output[..8].Clear(); return; } @@ -1777,7 +1777,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if (DetectInvalidHighbdInput(input, 8) != 0) { Debug.Assert(false, "invalid highbd txfm input"); - output.Slice(0, 8).Clear(); + output[..8].Clear(); return; } @@ -1835,8 +1835,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 8; ++i) { HighbdIdct8(input, outptr, bd); - input = input.Slice(8); - outptr = outptr.Slice(8); + input = input[8..]; + outptr = outptr[8..]; } // Then transform columns @@ -1871,8 +1871,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 4; ++i) { HighbdIdct8(input, outptr, bd); - input = input.Slice(8); - outptr = outptr.Slice(8); + input = input[8..]; + outptr = outptr[8..]; } // Then transform columns @@ -1906,7 +1906,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[i] = HighbdClipPixelAdd(dest[i], a1, bd); } - dest = dest.Slice(stride); + dest = dest[stride..]; } } @@ -1933,13 +1933,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if (DetectInvalidHighbdInput(input, 16) != 0) { Debug.Assert(false, "invalid highbd txfm input"); - output.Slice(0, 16).Clear(); + output[..16].Clear(); return; } if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15) == 0) { - output.Slice(0, 16).Clear(); + output[..16].Clear(); return; } @@ -2095,7 +2095,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if (DetectInvalidHighbdInput(input, 16) != 0) { Debug.Assert(false, "invalid highbd txfm input"); - output.Slice(0, 16).Clear(); + output[..16].Clear(); return; } @@ -2272,8 +2272,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 16; ++i) { HighbdIdct16(input, outptr, bd); - input = input.Slice(16); - outptr = outptr.Slice(16); + input = input[16..]; + outptr = outptr[16..]; } // Then transform columns @@ -2308,8 +2308,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 8; ++i) { HighbdIdct16(input, outptr, bd); - input = input.Slice(16); - outptr = outptr.Slice(16); + input = input[16..]; + outptr = outptr[16..]; } // Then transform columns @@ -2325,7 +2325,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int j = 0; j < 16; ++j) { destT[i] = HighbdClipPixelAdd(destT[i], BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd); - destT = destT.Slice(stride); + destT = destT[stride..]; } } } @@ -2345,8 +2345,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 4; ++i) { HighbdIdct16(input, outptr, bd); - input = input.Slice(16); - outptr = outptr.Slice(16); + input = input[16..]; + outptr = outptr[16..]; } // Then transform columns @@ -2380,7 +2380,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[i] = HighbdClipPixelAdd(dest[i], a1, bd); } - dest = dest.Slice(stride); + dest = dest[stride..]; } } @@ -2394,7 +2394,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if (DetectInvalidHighbdInput(input, 32) != 0) { Debug.Assert(false, "invalid highbd txfm input"); - output.Slice(0, 32).Clear(); + output[..32].Clear(); return; } @@ -2784,11 +2784,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp } else { - outptr.Slice(0, 32).Clear(); + outptr[..32].Clear(); } - input = input.Slice(32); - outptr = outptr.Slice(32); + input = input[32..]; + outptr = outptr[32..]; } // Columns @@ -2823,8 +2823,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 16; ++i) { HighbdIdct32(input, outptr, bd); - input = input.Slice(32); - outptr = outptr.Slice(32); + input = input[32..]; + outptr = outptr[32..]; } // Columns @@ -2840,7 +2840,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int j = 0; j < 32; ++j) { destT[i] = HighbdClipPixelAdd(destT[i], BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd); - destT = destT.Slice(stride); + destT = destT[stride..]; } } } @@ -2860,8 +2860,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 8; ++i) { HighbdIdct32(input, outptr, bd); - input = input.Slice(32); - outptr = outptr.Slice(32); + input = input[32..]; + outptr = outptr[32..]; } // Columns @@ -2896,8 +2896,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[i] = HighbdClipPixelAdd(dest[i], a1, bd); } - dest = dest.Slice(stride); + dest = dest[stride..]; } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterAuto.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterAuto.cs index fbd87e17f..ee33acc5f 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterAuto.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterAuto.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using System; using System.Runtime.Intrinsics.X86; @@ -226,4 +226,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterScalar.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterScalar.cs index 79c3f1235..dcb779442 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterScalar.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterScalar.cs @@ -1090,4 +1090,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp HighBdMbLpfVerticalEdgeW(s, pitch, blimit, limit, thresh, 16, bd); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterSse2.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterSse2.cs index 0d9f496ae..bf522636a 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterSse2.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterSse2.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using System; using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; @@ -133,8 +133,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp } Vector128 ff = Sse2.CompareEqual(zero, zero); - Vector128 q1P1, q0P0, p3P2, p2P1, p1P0, q3Q2, q2Q1, q1Q0, ps1Ps0, qs1Qs0; - Vector128 mask, hev; + Vector128 q1P1, q0P0, p3P2, p2P1, p1P0, q3Q2, q2Q1, q1Q0; p3P2 = Sse2.UnpackLow(Sse2.LoadScalarVector128((long*)(s.ToPointer() - (3 * pitch))), Sse2.LoadScalarVector128((long*)(s.ToPointer() - (4 * pitch)))).AsByte(); @@ -149,8 +148,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp q1Q0 = Sse2.UnpackHigh(q0P0.AsInt64(), q1P1.AsInt64()).AsByte(); q2Q1 = Sse2.UnpackLow(Sse2.ShiftRightLogical128BitLane(q1P1, 8).AsInt64(), q3Q2.AsInt64()).AsByte(); - FilterHevMask(q1P1, q0P0, p3P2, p2P1, p1P0, q3Q2, q2Q1, q1Q0, limitV, threshV, out hev, out mask); - Filter4(p1P0, q1Q0, hev, mask, ff, out ps1Ps0, out qs1Qs0); + FilterHevMask(q1P1, q0P0, p3P2, p2P1, p1P0, q3Q2, q2Q1, q1Q0, limitV, threshV, out Vector128 hev, out Vector128 mask); + Filter4(p1P0, q1Q0, hev, mask, ff, out Vector128 ps1Ps0, out Vector128 qs1Qs0); Sse.StoreHigh((float*)(s.ToPointer() - (2 * pitch)), ps1Ps0.AsSingle()); // *op1 Sse2.StoreScalar((long*)(s.ToPointer() - (1 * pitch)), ps1Ps0.AsInt64()); // *op0 @@ -178,8 +177,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp Vector128 ff = Sse2.CompareEqual(zero, zero); Vector128 x0, x1, x2, x3; - Vector128 q1P1, q0P0, p3P2, p2P1, p1P0, q3Q2, q2Q1, q1Q0, ps1Ps0, qs1Qs0; - Vector128 mask, hev; + Vector128 q1P1, q0P0, p3P2, p2P1, p1P0, q3Q2, q2Q1, q1Q0; // 00 10 01 11 02 12 03 13 04 14 05 15 06 16 07 17 q1Q0 = Sse2.UnpackLow( @@ -230,8 +228,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp p2P1 = Sse2.UnpackLow(q1P1.AsInt64(), p3P2.AsInt64()).AsByte(); q2Q1 = Sse2.UnpackLow(Sse2.ShiftRightLogical128BitLane(q1P1, 8).AsInt64(), q3Q2.AsInt64()).AsByte(); - FilterHevMask(q1P1, q0P0, p3P2, p2P1, p1P0, q3Q2, q2Q1, q1Q0, limitV, threshV, out hev, out mask); - Filter4(p1P0, q1Q0, hev, mask, ff, out ps1Ps0, out qs1Qs0); + FilterHevMask(q1P1, q0P0, p3P2, p2P1, p1P0, q3Q2, q2Q1, q1Q0, limitV, threshV, out Vector128 hev, out Vector128 mask); + Filter4(p1P0, q1Q0, hev, mask, ff, out Vector128 ps1Ps0, out Vector128 qs1Qs0); // Transpose 8x4 to 4x8 // qs1qs0: 20 21 22 23 24 25 26 27 30 31 32 33 34 34 36 37 @@ -1262,6 +1260,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp flat = Sse2.CompareEqual(flat, zero); flat = Sse2.And(flat, mask); } + { Vector128 four = Vector128.Create((short)4); ArrayPtr src = s; @@ -1834,4 +1833,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp Transpose8X16(tDst.Slice(8), tDst.Slice(8 + (8 * 16)), 16, s.Slice(-8 + (8 * pitch)), pitch); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Prob.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Prob.cs index df82dc7a9..dc89ecfd4 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Prob.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Prob.cs @@ -1,4 +1,4 @@ -using Ryujinx.Graphics.Nvdec.Vp9.Common; +using Ryujinx.Graphics.Nvdec.Vp9.Common; using System; using System.Diagnostics; @@ -68,4 +68,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp TreeMergeProbsImpl(0, tree, preProbs, counts, probs); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Reader.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Reader.cs index e6f34d266..6b570cc60 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Reader.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Reader.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Types; using System; using System.Buffers.Binary; @@ -63,7 +63,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp ulong bigEndianValues = BinaryPrimitives.ReadUInt64BigEndian(buffer); nv = bigEndianValues >> (BdValueSize - bits); count += bits; - buffer = buffer.Slice(bits >> 3); + buffer = buffer[(bits >> 3)..]; value = Value | (nv << (shift & 0x7)); } else @@ -82,7 +82,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp { count += 8; value |= (ulong)buffer[0] << shift; - buffer = buffer.Slice(1); + buffer = buffer[1..]; shift -= 8; } } @@ -96,7 +96,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp Count = count; } - public bool HasError() + public readonly bool HasError() { // Check if we have reached the end of the buffer. // @@ -112,7 +112,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp // // 1 if we have tried to decode bits after the end of stream was encountered. // 0 No error. - return Count > BdValueSize && Count < LotsOfBits; + return Count is > BdValueSize and < LotsOfBits; } public int Read(int prob) @@ -149,6 +149,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp value <<= shift; count -= shift; } + Value = value; Count = count; Range = range; @@ -200,14 +201,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if (value >= bigsplit) { - range = range - split; - value = value - bigsplit; + range -= split; + value -= bigsplit; { int shift = _norm[range]; range <<= shift; value <<= shift; count -= shift; } + return 1; } @@ -218,13 +220,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp value <<= shift; count -= shift; } + return 0; } public ArrayPtr FindEnd() { // Find the end of the coded buffer - while (Count > 8 && Count < BdValueSize) + while (Count is > 8 and < BdValueSize) { Count -= 8; _buffer = _buffer.Slice(-1); @@ -307,4 +310,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/TxfmCommon.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/TxfmCommon.cs index d84c0bb16..175f43704 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/TxfmCommon.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/TxfmCommon.cs @@ -51,4 +51,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp public const short SinPi39 = 13377; public const short SinPi49 = 15212; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Entropy.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Entropy.cs index 380879453..736b78fc6 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Entropy.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Entropy.cs @@ -1,4 +1,4 @@ -using Ryujinx.Graphics.Nvdec.Vp9.Types; +using Ryujinx.Graphics.Nvdec.Vp9.Types; using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -620,4 +620,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 internal const int CoefCountSatAfterKey = 24; internal const int CoefMaxUpdateFactorAfterKey = 128; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMode.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMode.cs index 586045976..624acbaa5 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMode.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMode.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Types; using Ryujinx.Graphics.Video; @@ -252,35 +252,35 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 private static readonly byte[] _defaultSingleRefP = [33, 16, 77, 74, 142, 142, 172, 170, 238, 247]; private static readonly byte[] _defaultTxProbs = [3, 136, 37, 5, 52, 13, 20, 152, 15, 101, 100, 66]; - static EntropyMode() - { - byte[][] kfPartitionProbs = - [ - // 8x8 . 4x4 - [158, 97, 94], // a/l both not split - [93, 24, 99], // a split, l not split - [85, 119, 44], // l split, a not split - [62, 59, 67], // a/l both split + //static EntropyMode() + //{ + // byte[][] kfPartitionProbs = + // [ + // // 8x8 . 4x4 + // [158, 97, 94], // a/l both not split + // [93, 24, 99], // a split, l not split + // [85, 119, 44], // l split, a not split + // [62, 59, 67], // a/l both split - // 16x16 . 8x8 - [149, 53, 53], // a/l both not split - [94, 20, 48], // a split, l not split - [83, 53, 24], // l split, a not split - [52, 18, 18], // a/l both split + // // 16x16 . 8x8 + // [149, 53, 53], // a/l both not split + // [94, 20, 48], // a split, l not split + // [83, 53, 24], // l split, a not split + // [52, 18, 18], // a/l both split - // 32x32 . 16x16 - [150, 40, 39], // a/l both not split - [78, 12, 26], // a split, l not split - [67, 33, 11], // l split, a not split - [24, 7, 5], // a/l both split + // // 32x32 . 16x16 + // [150, 40, 39], // a/l both not split + // [78, 12, 26], // a split, l not split + // [67, 33, 11], // l split, a not split + // [24, 7, 5], // a/l both split - // 64x64 . 32x32 - [174, 35, 49], // a/l both not split - [68, 11, 27], // a split, l not split - [57, 15, 9], // l split, a not split - [12, 3, 3] // a/l both split - ]; - } + // // 64x64 . 32x32 + // [174, 35, 49], // a/l both not split + // [68, 11, 27], // a split, l not split + // [57, 15, 9], // l split, a not split + // [12, 3, 3] // a/l both split + // ]; + //} private static readonly byte[] _defaultSkipProbs = [192, 128, 64]; @@ -296,7 +296,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 Entropy.CopyProbs(ref fc.CompInterProb, _defaultCompInterP); Entropy.CopyProbs(ref fc.CompRefProb, _defaultCompRefP); Entropy.CopyProbs(ref fc.SingleRefProb, _defaultSingleRefP); - Entropy.CopyProbs(ref fc.Tx32x32Prob, _defaultTxProbs.AsSpan().Slice(0, 6)); + Entropy.CopyProbs(ref fc.Tx32x32Prob, _defaultTxProbs.AsSpan()[..6]); Entropy.CopyProbs(ref fc.Tx16x16Prob, _defaultTxProbs.AsSpan().Slice(6, 4)); Entropy.CopyProbs(ref fc.Tx8x8Prob, _defaultTxProbs.AsSpan().Slice(10, 2)); Entropy.CopyProbs(ref fc.SkipProb, _defaultSkipProbs); @@ -387,4 +387,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 cm.FrameContextIdx = 0; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMv.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMv.cs index 4fa8e6d4c..511460a19 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMv.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMv.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Types; using Ryujinx.Graphics.Video; using System.Diagnostics; @@ -12,7 +12,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 /* Symbols for coding which components are zero jointly */ public const int Joints = 4; - public static readonly sbyte[] JointTree = [ -(sbyte)MvJointType.Zero, 2, -(sbyte)MvJointType.Hnzvz, 4, @@ -33,12 +32,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 private static bool JointVertical(MvJointType type) { - return type == MvJointType.Hzvnz || type == MvJointType.Hnzvnz; + return type is MvJointType.Hzvnz or MvJointType.Hnzvnz; } private static bool JointHorizontal(MvJointType type) { - return type == MvJointType.Hnzvz || type == MvJointType.Hnzvnz; + return type is MvJointType.Hnzvz or MvJointType.Hnzvnz; } private static readonly byte[] _logInBase2 = diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/FrameBuffers.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/FrameBuffers.cs index a5692c446..ac28735ec 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/FrameBuffers.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/FrameBuffers.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Types; diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Idct.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Idct.cs index f080fc825..2796a56e9 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Idct.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Idct.cs @@ -1,4 +1,4 @@ -using Ryujinx.Graphics.Nvdec.Vp9.Common; +using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Types; using System; using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.InvTxfm; @@ -11,7 +11,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 private delegate void HighbdTransform1D(ReadOnlySpan input, Span output, int bd); - private struct Transform2D + private readonly struct Transform2D { public readonly Transform1D Cols; // Vertical and horizontal public readonly Transform1D Rows; // Vertical and horizontal @@ -23,7 +23,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } } - private struct HighbdTransform2D + private readonly struct HighbdTransform2D { public readonly HighbdTransform1D Cols; // Vertical and horizontal public readonly HighbdTransform1D Rows; // Vertical and horizontal @@ -54,8 +54,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 for (int i = 0; i < 4; ++i) { _iht4[txType].Rows(input, outptr); - input = input.Slice(4); - outptr = outptr.Slice(4); + input = input[4..]; + outptr = outptr[4..]; } // Inverse transform column vectors @@ -95,8 +95,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 for (int i = 0; i < 8; ++i) { ht.Rows(input, outptr); - input = input.Slice(8); - outptr = outptr.Slice(8); + input = input[8..]; + outptr = outptr[8..]; } // Inverse transform column vectors @@ -136,8 +136,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 for (int i = 0; i < 16; ++i) { ht.Rows(input, outptr); - input = input.Slice(16); - outptr = outptr.Slice(16); + input = input[16..]; + outptr = outptr[16..]; } // Columns @@ -305,8 +305,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 for (int i = 0; i < 4; ++i) { _highbdIht4[txType].Rows(input, outptr, bd); - input = input.Slice(4); - outptr = outptr.Slice(4); + input = input[4..]; + outptr = outptr[4..]; } // Inverse transform column vectors. @@ -346,8 +346,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 for (int i = 0; i < 8; ++i) { ht.Rows(input, outptr, bd); - input = input.Slice(8); - outptr = output.Slice(8); + input = input[8..]; + outptr = output[8..]; } // Inverse transform column vectors. @@ -388,8 +388,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 for (int i = 0; i < 16; ++i) { ht.Rows(input, outptr, bd); - input = input.Slice(16); - outptr = output.Slice(16); + input = input[16..]; + outptr = output[16..]; } // Columns @@ -540,4 +540,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/InternalErrorException.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/InternalErrorException.cs index efcd9c23b..6d74e09f6 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/InternalErrorException.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/InternalErrorException.cs @@ -12,4 +12,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/InternalErrorInfo.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/InternalErrorInfo.cs index 9acfc211d..cfec81ed1 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/InternalErrorInfo.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/InternalErrorInfo.cs @@ -11,4 +11,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 throw new InternalErrorException(message); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/LoopFilter.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/LoopFilter.cs index 937a196dd..ada7ae400 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/LoopFilter.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/LoopFilter.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Dsp; using Ryujinx.Graphics.Nvdec.Vp9.Types; @@ -62,7 +62,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 _curSbCol.AsSpan().Fill(-1); } - public void SyncRead(int r, int c) + public readonly void SyncRead(int r, int c) { if (_curSbCol == null) { @@ -84,7 +84,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } } - public void SyncWrite(int r, int c, int sbCols) + public readonly void SyncWrite(int r, int c, int sbCols) { if (_curSbCol == null) { @@ -336,7 +336,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 private static Span GetLfm(ref Types.LoopFilter lf, int miRow, int miCol) { - return lf.Lfm.AsSpan().Slice((miCol >> 3) + ((miRow >> 3) * lf.LfmStride)); + return lf.Lfm.AsSpan()[((miCol >> 3) + ((miRow >> 3) * lf.LfmStride))..]; } // 8x8 blocks in a superblock. A "1" represents the first block in a 16x16 @@ -380,7 +380,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 for (int i = 0; i < bh; i++) { - MemoryMarshal.CreateSpan(ref lfm.LflY[index], 64 - index).Slice(0, bw).Fill((byte)filterLevel); + MemoryMarshal.CreateSpan(ref lfm.LflY[index], 64 - index)[..bw].Fill((byte)filterLevel); index += 8; } @@ -445,7 +445,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 const ushort LeftBorderUv = 0x1111; const ushort AboveBorderUv = 0x000f; - // The largest loopfilter we have is 16x16 so we use the 16x16 mask // for 32x32 transforms also. lfm.LeftY[(int)TxSize.Tx16X16] |= lfm.LeftY[(int)TxSize.Tx32X32]; @@ -775,7 +774,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } ss[0] = ss[0].Slice(8); - lfl = lfl.Slice(1); + lfl = lfl[1..]; mask16X16 >>= 1; mask8X8 >>= 1; mask4X4 >>= 1; @@ -903,7 +902,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } ss[0] = ss[0].Slice(8); - lfl = lfl.Slice(1); + lfl = lfl[1..]; mask16X16 >>= 1; mask8X8 >>= 1; mask4X4 >>= 1; @@ -1060,7 +1059,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } s = s.Slice(8 * count); - lfl = lfl.Slice(count); + lfl = lfl[count..]; mask16X16 >>= count; mask8X8 >>= count; mask4X4 >>= count; @@ -1222,7 +1221,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } s = s.Slice(8 * count); - lfl = lfl.Slice(count); + lfl = lfl[count..]; mask16X16 >>= count; mask8X8 >>= count; mask4X4 >>= count; @@ -1270,7 +1269,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } s = s.Slice(8); - lfl = lfl.Slice(1); + lfl = lfl[1..]; mask16X16 >>= 1; mask8X8 >>= 1; mask4X4 >>= 1; @@ -1315,7 +1314,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } s = s.Slice(8); - lfl = lfl.Slice(1); + lfl = lfl[1..]; mask16X16 >>= 1; mask8X8 >>= 1; mask4X4 >>= 1; @@ -1348,7 +1347,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 Span mask4X4Int = stackalloc int[Constants.MiBlockSize]; Span lfl = stackalloc byte[Constants.MiBlockSize * Constants.MiBlockSize]; - for (int r = 0; r < Constants.MiBlockSize && miRow + r < cm.MiRows; r += rowStep) { uint mask16X16C = 0; @@ -1478,7 +1476,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 mask4X4C & borderMask, (uint)mask4X4Int[r], cm.LfInfo.Lfthr.AsSpan(), - lfl.Slice(r << 3), + lfl[(r << 3)..], (int)cm.BitDepth); } else @@ -1491,7 +1489,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 mask4X4C & borderMask, (uint)mask4X4Int[r], cm.LfInfo.Lfthr.AsSpan(), - lfl.Slice(r << 3)); + lfl[(r << 3)..]); } dst.Buf = dst.Buf.Slice(8 * dst.Stride); @@ -1532,7 +1530,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 mask4X4R, mask4X4IntR, cm.LfInfo.Lfthr.AsSpan(), - lfl.Slice(r << 3), + lfl[(r << 3)..], (int)cm.BitDepth); } else @@ -1545,7 +1543,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 mask4X4R, mask4X4IntR, cm.LfInfo.Lfthr.AsSpan(), - lfl.Slice(r << 3)); + lfl[(r << 3)..]); } dst.Buf = dst.Buf.Slice(8 * dst.Stride); @@ -1579,7 +1577,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 (uint)mask4X4, (uint)mask4X4Int, cm.LfInfo.Lfthr.AsSpan(), - lfm.LflY.AsSpan().Slice(r << 3), + lfm.LflY.AsSpan()[(r << 3)..], (int)cm.BitDepth); } else @@ -1594,7 +1592,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 (uint)mask4X4, (uint)mask4X4Int, cm.LfInfo.Lfthr.AsSpan(), - lfm.LflY.AsSpan().Slice(r << 3)); + lfm.LflY.AsSpan()[(r << 3)..]); } dst.Buf = dst.Buf.Slice(16 * dst.Stride); @@ -1640,7 +1638,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 mask4X4R, (uint)mask4X4Int & 0xff, cm.LfInfo.Lfthr.AsSpan(), - lfm.LflY.AsSpan().Slice(r << 3), + lfm.LflY.AsSpan()[(r << 3)..], (int)cm.BitDepth); } else @@ -1653,7 +1651,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 mask4X4R, (uint)mask4X4Int & 0xff, cm.LfInfo.Lfthr.AsSpan(), - lfm.LflY.AsSpan().Slice(r << 3)); + lfm.LflY.AsSpan()[(r << 3)..]); } dst.Buf = dst.Buf.Slice(8 * dst.Stride); @@ -1700,7 +1698,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 mask4X4, mask4X4Int, cm.LfInfo.Lfthr.AsSpan(), - lflUv.Slice(r << 1), + lflUv[(r << 1)..], (int)cm.BitDepth); } else @@ -1715,7 +1713,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 mask4X4, mask4X4Int, cm.LfInfo.Lfthr.AsSpan(), - lflUv.Slice(r << 1)); + lflUv[(r << 1)..]); } dst.Buf = dst.Buf.Slice(16 * dst.Stride); @@ -1763,7 +1761,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 mask4X4R, mask4X4IntR, cm.LfInfo.Lfthr.AsSpan(), - lflUv.Slice(r << 1), + lflUv[(r << 1)..], (int)cm.BitDepth); } else @@ -1776,7 +1774,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 mask4X4R, mask4X4IntR, cm.LfInfo.Lfthr.AsSpan(), - lflUv.Slice(r << 1)); + lflUv[(r << 1)..]); } dst.Buf = dst.Buf.Slice(8 * dst.Stride); @@ -1831,7 +1829,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 ArrayPtr> mi = cm.MiGridVisible.Slice(miRow * cm.MiStride); Span lfm = GetLfm(ref cm.Lf, miRow, 0); - for (miCol = 0; miCol < cm.MiCols; miCol += Constants.MiBlockSize, lfm = lfm.Slice(1)) + for (miCol = 0; miCol < cm.MiCols; miCol += Constants.MiBlockSize, lfm = lfm[1..]) { int r = miRow >> Constants.MiBlockSizeLog2; int c = miCol >> Constants.MiBlockSizeLog2; @@ -1963,4 +1961,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 return new ArrayPtr((ushort*)s.ToPointer(), s.Length / 2); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Luts.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Luts.cs index d54dbeec5..acd771284 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Luts.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Luts.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Types; using System; @@ -270,11 +270,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 private static Array8 NewArray8Short(short e0, short e1, short e2, short e3, short e4, short e5, short e6, short e7) { - Array8 output = new() - { - [0] = e0, - [1] = e1, - [2] = e2, + Array8 output = new() + { + [0] = e0, + [1] = e1, + [2] = e2, [3] = e3, [4] = e4, [5] = e5, diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/PredCommon.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/PredCommon.cs index 30cab3b60..cf91eedeb 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/PredCommon.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/PredCommon.cs @@ -1,4 +1,4 @@ -using Ryujinx.Graphics.Nvdec.Vp9.Types; +using Ryujinx.Graphics.Nvdec.Vp9.Types; using System.Diagnostics; namespace Ryujinx.Graphics.Nvdec.Vp9 @@ -61,7 +61,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 ctx = 1; } - Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts); + Debug.Assert(ctx is >= 0 and < Constants.CompInterContexts); return ctx; } @@ -186,7 +186,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 predContext = 2; } - Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts); + Debug.Assert(predContext is >= 0 and < Constants.RefContexts); return predContext; } @@ -294,7 +294,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 predContext = 2; } - Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts); + Debug.Assert(predContext is >= 0 and < Constants.RefContexts); return predContext; } @@ -430,8 +430,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 predContext = 2; } - Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts); + Debug.Assert(predContext is >= 0 and < Constants.RefContexts); return predContext; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Prob.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Prob.cs index ca6fa351a..6967e63a6 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Prob.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Prob.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using System; using System.Diagnostics; @@ -91,4 +91,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 TreeMergeProbsImpl(0, tree, preProbs, counts, probs); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/QuantCommon.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/QuantCommon.cs index 3542c90c4..36e4f2704 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/QuantCommon.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/QuantCommon.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; namespace Ryujinx.Graphics.Nvdec.Vp9 @@ -117,9 +117,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { switch (bitDepth) { - case BitDepth.Bits8: return _dcQlookup[Math.Clamp(qindex + delta, 0, MaxQ)]; - case BitDepth.Bits10: return _dcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)]; - case BitDepth.Bits12: return _dcQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)]; + case BitDepth.Bits8: + return _dcQlookup[Math.Clamp(qindex + delta, 0, MaxQ)]; + case BitDepth.Bits10: + return _dcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)]; + case BitDepth.Bits12: + return _dcQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)]; default: Debug.Assert(false, "bitDepth should be Bits8, Bits10 or Bits12"); return -1; @@ -130,13 +133,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { switch (bitDepth) { - case BitDepth.Bits8: return _acQlookup[Math.Clamp(qindex + delta, 0, MaxQ)]; - case BitDepth.Bits10: return _acQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)]; - case BitDepth.Bits12: return _acQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)]; + case BitDepth.Bits8: + return _acQlookup[Math.Clamp(qindex + delta, 0, MaxQ)]; + case BitDepth.Bits10: + return _acQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)]; + case BitDepth.Bits12: + return _acQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)]; default: Debug.Assert(false, "bitDepth should be Bits8, Bits10 or Bits12"); return -1; } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/ReadBitBuffer.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/ReadBitBuffer.cs index a4e07a1c0..f3e908085 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/ReadBitBuffer.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/ReadBitBuffer.cs @@ -1,4 +1,4 @@ -using Ryujinx.Graphics.Nvdec.Vp9.Common; +using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Types; using System; @@ -16,7 +16,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 return data > max ? max : data; } - public ulong BytesRead() + public readonly ulong BytesRead() { return (BitOffset + 7) >> 3; } @@ -81,4 +81,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 return (BitstreamProfile)profile; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/ReconInter.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/ReconInter.cs index 35dbf1cab..e332fd208 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/ReconInter.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/ReconInter.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Types; using System; using System.Diagnostics; @@ -98,7 +98,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 int spelBottom = spelTop - SubpelShifts; Mv clampedMv = new() { - Row = (short)(srcMv.Row * (1 << (1 - ssY))), Col = (short)(srcMv.Col * (1 << (1 - ssX))) + Row = (short)(srcMv.Row * (1 << (1 - ssY))), + Col = (short)(srcMv.Col * (1 << (1 - ssX))) }; Debug.Assert(ssX <= 1); @@ -132,7 +133,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 res = mi.MvPredQ4(refr); break; default: - Debug.Assert(ssIdx <= 3 && ssIdx >= 0); + Debug.Assert(ssIdx is <= 3 and >= 0); break; } @@ -213,4 +214,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/ReconIntra.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/ReconIntra.cs index 877469787..e85c501c7 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/ReconIntra.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/ReconIntra.cs @@ -1,4 +1,4 @@ -using Ryujinx.Graphics.Nvdec.Vp9.Common; +using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Types; using System; using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.IntraPred; @@ -632,4 +632,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 plane); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/TileBuffer.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/TileBuffer.cs index 18b9d7f47..b6adb95ff 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/TileBuffer.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/TileBuffer.cs @@ -8,4 +8,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 public ArrayPtr Data; public int Size; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/TileWorkerData.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/TileWorkerData.cs index 8c62dca75..526195f87 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/TileWorkerData.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/TileWorkerData.cs @@ -28,4 +28,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 return (left * 2) + above + (bsl * Constants.PartitionPloffset); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BModeInfo.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BModeInfo.cs index a9d32d0b4..4ff82820e 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BModeInfo.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BModeInfo.cs @@ -7,4 +7,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public PredictionMode Mode; public Array2 Mv; // First, second inter predictor motion vectors } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BitstreamProfile.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BitstreamProfile.cs index 13293f460..e2ced8c95 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BitstreamProfile.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BitstreamProfile.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { public enum BitstreamProfile { @@ -8,4 +8,4 @@ Profile3, MaxProfiles } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BlockSize.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BlockSize.cs index cee162ab7..e52b05ec6 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BlockSize.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BlockSize.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { internal enum BlockSize { @@ -18,4 +18,4 @@ BlockSizes, BlockInvalid = BlockSizes } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Buf2D.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Buf2D.cs index 575189490..1313a2e1f 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Buf2D.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Buf2D.cs @@ -7,4 +7,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public ArrayPtr Buf; public int Stride; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BufferPool.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BufferPool.cs index bfe87d5a5..8af54d42a 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BufferPool.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BufferPool.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; namespace Ryujinx.Graphics.Nvdec.Vp9.Types { @@ -15,4 +15,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types // Frame buffers allocated internally by the codec. public InternalFrameBufferList IntFrameBuffers; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/FrameType.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/FrameType.cs index 8b0935e29..21f021c5b 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/FrameType.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/FrameType.cs @@ -5,4 +5,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types KeyFrame = 0, InterFrame = 1, } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilter.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilter.cs index 4207c54d7..2c75b780b 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilter.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilter.cs @@ -37,4 +37,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types ModeDeltas[1] = 0; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterInfoN.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterInfoN.cs index 2a88df3e1..be6243071 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterInfoN.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterInfoN.cs @@ -7,4 +7,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public Array64 Lfthr; public Array8>> Lvl; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterMask.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterMask.cs index 4aea49425..69a38b926 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterMask.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterMask.cs @@ -21,4 +21,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public ushort Int4X4Uv; public Array64 LflY; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterThresh.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterThresh.cs index 7fa3c6355..546213215 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterThresh.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterThresh.cs @@ -12,4 +12,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public Array16 HevThr; #pragma warning restore CS0649 } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MacroBlockD.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MacroBlockD.cs index bc6b7be32..47c218994 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MacroBlockD.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MacroBlockD.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Video; @@ -55,7 +55,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public Ptr ErrorInfo; - public int GetPredContextSegId() + public readonly int GetPredContextSegId() { sbyte aboveSip = !AboveMi.IsNull ? AboveMi.Value.SegIdPredicted : (sbyte)0; sbyte leftSip = !LeftMi.IsNull ? LeftMi.Value.SegIdPredicted : (sbyte)0; @@ -63,14 +63,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types return aboveSip + leftSip; } - public int GetSkipContext() + public readonly int GetSkipContext() { int aboveSkip = !AboveMi.IsNull ? AboveMi.Value.Skip : 0; int leftSkip = !LeftMi.IsNull ? LeftMi.Value.Skip : 0; return aboveSkip + leftSkip; } - public int GetPredContextSwitchableInterp() + public readonly int GetPredContextSwitchableInterp() { // Note: // The mode info data structure has a one element border above and to the @@ -104,7 +104,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types // 1 - intra/inter, inter/intra // 2 - intra/--, --/intra // 3 - intra/intra - public int GetIntraInterContext() + public readonly int GetIntraInterContext() { if (!AboveMi.IsNull && !LeftMi.IsNull) { @@ -127,7 +127,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types // The mode info data structure has a one element border above and to the // left of the entries corresponding to real blocks. // The prediction flags in these dummy entries are initialized to 0. - public int GetTxSizeContext() + public readonly int GetTxSizeContext() { int maxTxSize = (int)Luts.MaxTxSizeLookup[(int)Mi[0].Value.SbType]; int aboveCtx = !AboveMi.IsNull && AboveMi.Value.Skip == 0 ? (int)AboveMi.Value.TxSize : maxTxSize; @@ -190,4 +190,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MacroBlockDPlane.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MacroBlockDPlane.cs index d5b64f078..ebf044e64 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MacroBlockDPlane.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MacroBlockDPlane.cs @@ -19,4 +19,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types // Log2 of N4W, N4H public byte N4Wl, N4Hl; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ModeInfo.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ModeInfo.cs index 39f545a76..9fd961bb9 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ModeInfo.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ModeInfo.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using System.Diagnostics; namespace Ryujinx.Graphics.Nvdec.Vp9.Types @@ -32,7 +32,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types return SbType < BlockSize.Block8X8 ? Bmi[block].Mode : Mode; } - public TxSize GetUvTxSize(ref MacroBlockDPlane pd) + public readonly TxSize GetUvTxSize(ref MacroBlockDPlane pd) { Debug.Assert(SbType < BlockSize.Block8X8 || Luts.SsSizeLookup[(int)SbType][pd.SubsamplingX][pd.SubsamplingY] != BlockSize.BlockInvalid); @@ -104,4 +104,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types return mv; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MotionVectorContext.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MotionVectorContext.cs index 138b8a0ee..bad5af280 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MotionVectorContext.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MotionVectorContext.cs @@ -11,4 +11,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types BothIntra = 6, InvalidCase = 9, } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Mv.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Mv.cs index 6e0accfb3..8a70107b3 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Mv.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Mv.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Video; using System; using System.Diagnostics; @@ -44,7 +44,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types 9, 9, 9, 9, 9, 9, 9, 9, 9, 10 ]; - public bool UseHp() + public readonly bool UseHp() { const int KMvRefThresh = 64; // Threshold for use of high-precision 1/8 mv return Math.Abs(Row) < KMvRefThresh && Math.Abs(Col) < KMvRefThresh; @@ -52,12 +52,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public static bool JointVertical(MvJointType type) { - return type == MvJointType.Hzvnz || type == MvJointType.Hnzvnz; + return type is MvJointType.Hzvnz or MvJointType.Hnzvnz; } public static bool JointHorizontal(MvJointType type) { - return type == MvJointType.Hnzvz || type == MvJointType.Hnzvnz; + return type is MvJointType.Hnzvz or MvJointType.Hnzvnz; } private static int ClassBase(MvClassType c) @@ -110,7 +110,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types } } - public MvJointType GetJoint() + public readonly MvJointType GetJoint() { if (Row == 0) { @@ -120,7 +120,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types return Col == 0 ? MvJointType.Hzvnz : MvJointType.Hnzvnz; } - internal void Inc(Ptr counts) + internal readonly void Inc(Ptr counts) { if (!counts.IsNull) { @@ -173,10 +173,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types } } - public bool IsValid() + public readonly bool IsValid() { return Row is > Constants.MvLow and < Constants.MvUpp && Col is > Constants.MvLow and < Constants.MvUpp; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Mv32.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Mv32.cs index d3561fe58..5231ca6a6 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Mv32.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Mv32.cs @@ -5,4 +5,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public int Row; public int Col; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvClassType.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvClassType.cs index 0e233b2f2..d933e7117 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvClassType.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvClassType.cs @@ -14,4 +14,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types Class9, /* (512, 1024] integer pel */ Class10 /* (1024,2048] integer pel */ } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvJointType.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvJointType.cs index 499c50c68..a9dca4644 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvJointType.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvJointType.cs @@ -7,4 +7,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types Hzvnz, /* Hor zero, vert nonzero */ Hnzvnz /* Both components nonzero */ } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvRef.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvRef.cs index 06b082800..1d32a0927 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvRef.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvRef.cs @@ -7,4 +7,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public Array2 Mv; public Array2 RefFrame; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PartitionType.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PartitionType.cs index 8042071e4..c47557abf 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PartitionType.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PartitionType.cs @@ -9,4 +9,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types PartitionTypes, PartitionInvalid = PartitionTypes, } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PlaneType.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PlaneType.cs index ced1646e9..1b50010a2 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PlaneType.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PlaneType.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { internal enum PlaneType { @@ -6,4 +6,4 @@ Uv, PlaneTypes } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Position.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Position.cs index d055f225e..cee2fbe83 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Position.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Position.cs @@ -11,4 +11,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types Col = col; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PredictionMode.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PredictionMode.cs index a0f15905d..2d9750af9 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PredictionMode.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PredictionMode.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { internal enum PredictionMode { @@ -18,4 +18,4 @@ NewMv, MbModeCount } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/RefBuffer.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/RefBuffer.cs index 4b45f2c02..dc4444e6e 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/RefBuffer.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/RefBuffer.cs @@ -8,4 +8,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public Surface Buf; public ScaleFactors Sf; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/RefCntBuffer.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/RefCntBuffer.cs index 47febf38d..2f654b6f7 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/RefCntBuffer.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/RefCntBuffer.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { internal struct RefCntBuffer { @@ -9,4 +9,4 @@ public VpxCodecFrameBuffer RawFrameBuffer; public Surface Buf; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ReferenceMode.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ReferenceMode.cs index a678f8181..aee5fccc9 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ReferenceMode.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ReferenceMode.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { internal enum ReferenceMode { @@ -7,4 +7,4 @@ Select, ReferenceModes } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ScaleFactors.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ScaleFactors.cs index 212571311..e3f73d761 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ScaleFactors.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ScaleFactors.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using System.Runtime.CompilerServices; using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.Convolve; using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.Filter; @@ -123,18 +123,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public int XStepQ4; public int YStepQ4; - public int ScaleValueX(int val) + public readonly int ScaleValueX(int val) { return IsScaled() ? ScaledX(val) : val; } - public int ScaleValueY(int val) + public readonly int ScaleValueY(int val) { return IsScaled() ? ScaledY(val) : val; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public unsafe void InterPredict( + public readonly unsafe void InterPredict( int horiz, int vert, int avg, @@ -182,7 +182,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public unsafe void HighbdInterPredict( + public readonly unsafe void HighbdInterPredict( int horiz, int vert, int avg, @@ -231,12 +231,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types } } - private int ScaledX(int val) + private readonly int ScaledX(int val) { return (int)(((long)val * XScaleFp) >> RefScaleShift); } - private int ScaledY(int val) + private readonly int ScaledY(int val) { return (int)(((long)val * YScaleFp) >> RefScaleShift); } @@ -258,12 +258,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types return res; } - public bool IsValidScale() + public readonly bool IsValidScale() { return XScaleFp != RefInvalidScale && YScaleFp != RefInvalidScale; } - public bool IsScaled() + public readonly bool IsScaled() { return IsValidScale() && (XScaleFp != RefNoScale || YScaleFp != RefNoScale); } @@ -291,4 +291,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types YStepQ4 = ScaledY(16); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/SegLvlFeatures.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/SegLvlFeatures.cs index 21d57d1d7..d14cff2c8 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/SegLvlFeatures.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/SegLvlFeatures.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { internal enum SegLvlFeatures { @@ -8,4 +8,4 @@ Skip, // Optional Segment (0,0) + skip mode Max // Number of features supported } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Segmentation.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Segmentation.cs index 726476d96..c34545791 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Segmentation.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Segmentation.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Video; using System; using System.Diagnostics; @@ -161,4 +161,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Surface.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Surface.cs index 33741f85f..42ba0af3d 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Surface.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Surface.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Video; using System.Diagnostics; @@ -26,7 +26,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public readonly unsafe Plane UPlane => new((nint)UBuffer.ToPointer(), UBuffer.Length); public readonly unsafe Plane VPlane => new((nint)VBuffer.ToPointer(), VBuffer.Length); - public FrameField Field => FrameField.Progressive; + public readonly FrameField Field => FrameField.Progressive; public int Width { get; private set; } public int Height { get; private set; } @@ -43,10 +43,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public int FrameSize { get; private set; } public int Border { get; private set; } - public int YCropWidth => Width; - public int YCropHeight => Height; - public int UvCropWidth => UvWidth; - public int UvCropHeight => UvHeight; + public readonly int YCropWidth => Width; + public readonly int YCropHeight => Height; + public readonly int UvCropWidth => UvWidth; + public readonly int UvCropHeight => UvHeight; public ArrayPtr BufferAlloc; public int BufferAllocSz; @@ -119,7 +119,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types VpxGetFrameBufferCbFnT cb, Ptr cbPriv) { - int byteAlign = byteAlignment == 0 ? 1 : byteAlignment; // TODO: Is it safe to ignore the alignment? int alignedWidth = (width + 7) & ~7; int alignedHeight = (height + 7) & ~7; int yStride = (alignedWidth + (2 * border) + 31) & ~31; @@ -135,8 +134,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types ulong frameSize = (ulong)(1 + (useHighbitdepth ? 1 : 0)) * (yplaneSize + (2 * uvplaneSize)); - ArrayPtr buf = ArrayPtr.Null; - // frame_size is stored in buffer_alloc_sz, which is an int. If it won't // fit, fail early. if (frameSize > int.MaxValue) @@ -211,7 +208,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types SubsamplingX = ssX; SubsamplingY = ssY; - buf = BufferAlloc; + ArrayPtr buf = BufferAlloc; if (useHighbitdepth) { // Store uint16 addresses when using 16bit framebuffers @@ -231,7 +228,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types return 0; } - public void Dispose() + public readonly void Dispose() { Marshal.FreeHGlobal(_pointer); } diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TileInfo.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TileInfo.cs index 7d4350d3c..a32f55c72 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TileInfo.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TileInfo.cs @@ -83,4 +83,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types Debug.Assert(minLog2TileCols <= maxLog2TileCols); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxMode.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxMode.cs index d6a4fb843..47dad305c 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxMode.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxMode.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { public enum TxMode { @@ -9,4 +9,4 @@ TxModeSelect, // Transform specified for each block TxModes } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxSize.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxSize.cs index 72908a00c..cfc51317a 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxSize.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxSize.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { public enum TxSize { @@ -8,4 +8,4 @@ Tx32X32, // 32x32 transform TxSizes } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxType.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxType.cs index 60c5c9a44..95ef538f2 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxType.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxType.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { internal enum TxType { @@ -8,4 +8,4 @@ AdstAdst, // ADST in both directions TxTypes } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Vp9Common.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Vp9Common.cs index 5669e8574..3fc31127a 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Vp9Common.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Vp9Common.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Dsp; using Ryujinx.Graphics.Video; @@ -148,7 +148,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public ArrayPtr AboveSegContext; public ArrayPtr AboveContext; - public bool FrameIsIntraOnly() + public readonly bool FrameIsIntraOnly() { return FrameType == FrameType.KeyFrame || IntraOnly; } @@ -166,12 +166,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types return false; } - public ref Surface GetFrameNewBuffer() + public readonly ref Surface GetFrameNewBuffer() { return ref BufferPool.Value.FrameBufs[NewFbIdx].Buf; } - public int GetFreeFb() + public readonly int GetFreeFb() { ref Array12 frameBufs = ref BufferPool.Value.FrameBufs; @@ -233,7 +233,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types allocator.Allocate((tileCols * tileRows) + (maxThreads > 1 ? maxThreads : 0)); } - public void FreeTileWorkerData(MemoryAllocator allocator) + public readonly void FreeTileWorkerData(MemoryAllocator allocator) { allocator.Free(TileWorkerData); } @@ -357,7 +357,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types } } - private void SetPartitionProbs(ref MacroBlockD xd) + private readonly void SetPartitionProbs(ref MacroBlockD xd) { xd.PartitionProbs = FrameIsIntraOnly() ? new ArrayPtr>(ref Fc.Value.KfPartitionProb[0], 16) @@ -429,7 +429,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types { ref Vp9EntropyProbs fc = ref Fc.Value; - if (ReferenceMode == ReferenceMode.Select) { for (int i = 0; i < Constants.CompInterContexts; ++i) @@ -490,7 +489,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types } } - public void InitMvProbs() + public readonly void InitMvProbs() { Fc.Value.Joints[0] = 32; Fc.Value.Joints[1] = 64; @@ -684,11 +683,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public void SetupTileInfo(ref ReadBitBuffer rb) { - int minLog2TileCols = 0, maxLog2TileCols = 0, maxOnes; - TileInfo.GetTileNBits(MiCols, out minLog2TileCols, out maxLog2TileCols); + TileInfo.GetTileNBits(MiCols, out int minLog2TileCols, out int maxLog2TileCols); // columns - maxOnes = maxLog2TileCols - minLog2TileCols; + int maxOnes = maxLog2TileCols - minLog2TileCols; Log2TileCols = minLog2TileCols; while (maxOnes-- != 0 && rb.ReadBit() != 0) { @@ -725,7 +723,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types if (ColorSpace != VpxColorSpace.Srgb) { ColorRange = (VpxColorRange)rb.ReadBit(); - if (Profile == BitstreamProfile.Profile1 || Profile == BitstreamProfile.Profile3) + if (Profile is BitstreamProfile.Profile1 or BitstreamProfile.Profile3) { SubsamplingX = rb.ReadBit(); SubsamplingY = rb.ReadBit(); @@ -748,7 +746,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types else { ColorRange = VpxColorRange.Full; - if (Profile == BitstreamProfile.Profile1 || Profile == BitstreamProfile.Profile3) + if (Profile is BitstreamProfile.Profile1 or BitstreamProfile.Profile3) { // Note if colorspace is SRGB then 4:4:4 chroma sampling is assumed. // 4:2:2 or 4:4:0 chroma sampling is not allowed. @@ -988,7 +986,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types } } - public void DefaultCoefProbs() + public readonly void DefaultCoefProbs() { Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx4X4], Entropy.DefaultCoefProbs4X4); Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx8X8], Entropy.DefaultCoefProbs8X8); @@ -996,4 +994,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx32X32], Entropy.DefaultCoefProbs32X32); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Vp9Decoder.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Vp9Decoder.cs index 11c121cfe..4df8ef549 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Vp9Decoder.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Vp9Decoder.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Video; using System.Diagnostics; @@ -279,9 +279,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types ArrayPtr dataStart = data; CodecErr res; Array8 frameSizes = new(); - int frameCount = 0; - res = Decoder.ParseSuperframeIndex(data, (ulong)data.Length, ref frameSizes, out frameCount); + res = Decoder.ParseSuperframeIndex(data, (ulong)data.Length, ref frameSizes, out int frameCount); if (res != CodecErr.Ok) { return res; @@ -407,4 +406,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types return CodecErr.Ok; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxCodecFrameBuffer.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxCodecFrameBuffer.cs index 358de79dd..6883dfad9 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxCodecFrameBuffer.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxCodecFrameBuffer.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; namespace Ryujinx.Graphics.Nvdec.Vp9.Types { @@ -7,4 +7,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public ArrayPtr Data; public Ptr Priv; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorRange.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorRange.cs index 9f8c7c53d..4f32abb94 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorRange.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorRange.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { internal enum VpxColorRange { @@ -8,4 +8,4 @@ // YUV/RGB [0..255] Full } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorSpace.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorSpace.cs index a1706c0d0..fa69c16a5 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorSpace.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorSpace.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { internal enum VpxColorSpace { @@ -26,4 +26,4 @@ // sRGB Srgb } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.OpenGL/Debugger.cs b/src/Ryujinx.Graphics.OpenGL/Debugger.cs index c700b3b7c..8a94bcc87 100644 --- a/src/Ryujinx.Graphics.OpenGL/Debugger.cs +++ b/src/Ryujinx.Graphics.OpenGL/Debugger.cs @@ -84,6 +84,7 @@ namespace Ryujinx.Graphics.OpenGL { Logger.Debug?.Print(LogClass.Gpu, $"{type} {severity}: {msg}", "GLDEBUG"); } + break; } } diff --git a/src/Ryujinx.Graphics.OpenGL/FormatTable.cs b/src/Ryujinx.Graphics.OpenGL/FormatTable.cs index 4cf4dc760..bca79cb97 100644 --- a/src/Ryujinx.Graphics.OpenGL/FormatTable.cs +++ b/src/Ryujinx.Graphics.OpenGL/FormatTable.cs @@ -228,14 +228,14 @@ namespace Ryujinx.Graphics.OpenGL public static bool IsPackedDepthStencil(Format format) { - return format == Format.D24UnormS8Uint || - format == Format.D32FloatS8Uint || - format == Format.S8UintD24Unorm; + return format is Format.D24UnormS8Uint or + Format.D32FloatS8Uint or + Format.S8UintD24Unorm; } public static bool IsDepthOnly(Format format) { - return format == Format.D16Unorm || format == Format.D32Float || format == Format.X8UintD24Unorm; + return format is Format.D16Unorm or Format.D32Float or Format.X8UintD24Unorm; } } } diff --git a/src/Ryujinx.Graphics.OpenGL/HwCapabilities.cs b/src/Ryujinx.Graphics.OpenGL/HwCapabilities.cs index cf0b0645c..71186807e 100644 --- a/src/Ryujinx.Graphics.OpenGL/HwCapabilities.cs +++ b/src/Ryujinx.Graphics.OpenGL/HwCapabilities.cs @@ -43,13 +43,13 @@ namespace Ryujinx.Graphics.OpenGL private static readonly Lazy _gpuVendor = new(GetGpuVendor); - private static bool IsIntel => _gpuVendor.Value == GpuVendor.IntelWindows || _gpuVendor.Value == GpuVendor.IntelUnix; + private static bool IsIntel => _gpuVendor.Value is GpuVendor.IntelWindows or GpuVendor.IntelUnix; public static GpuVendor Vendor => _gpuVendor.Value; private static readonly Lazy _maxSupportedAnisotropy = new(GL.GetFloat((GetPName)All.MaxTextureMaxAnisotropy)); - public static bool UsePersistentBufferForFlush => _gpuVendor.Value == GpuVendor.AmdWindows || _gpuVendor.Value == GpuVendor.Nvidia; + public static bool UsePersistentBufferForFlush => _gpuVendor.Value is GpuVendor.AmdWindows or GpuVendor.Nvidia; public static bool SupportsAlphaToCoverageDitherControl => _supportsAlphaToCoverageDitherControl.Value; public static bool SupportsAstcCompression => _supportsAstcCompression.Value; @@ -73,7 +73,7 @@ namespace Ryujinx.Graphics.OpenGL public static bool SupportsTextureShadowLod => _supportsTextureShadowLod.Value; public static bool SupportsViewportSwizzle => _supportsViewportSwizzle.Value; - public static bool SupportsMismatchingViewFormat => _gpuVendor.Value != GpuVendor.AmdWindows && _gpuVendor.Value != GpuVendor.IntelWindows; + public static bool SupportsMismatchingViewFormat => _gpuVendor.Value is not GpuVendor.AmdWindows and not GpuVendor.IntelWindows; public static bool SupportsNonConstantTextureOffset => _gpuVendor.Value == GpuVendor.Nvidia; public static bool RequiresSyncFlush => _gpuVendor.Value == GpuVendor.AmdWindows || IsIntel; @@ -117,11 +117,11 @@ namespace Ryujinx.Graphics.OpenGL return renderer.Contains("mesa") ? GpuVendor.IntelUnix : GpuVendor.IntelWindows; } - else if (vendor == "ati technologies inc." || vendor == "advanced micro devices, inc.") + else if (vendor is "ati technologies inc." or "advanced micro devices, inc.") { return GpuVendor.AmdWindows; } - else if (vendor == "amd" || vendor == "x.org") + else if (vendor is "amd" or "x.org") { return GpuVendor.AmdUnix; } diff --git a/src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs b/src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs index e08da7013..3d1e47339 100644 --- a/src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs +++ b/src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs @@ -290,7 +290,7 @@ namespace Ryujinx.Graphics.OpenGL.Image private static FramebufferAttachment AttachmentForFormat(Format format) { - if (format == Format.D24UnormS8Uint || format == Format.D32FloatS8Uint) + if (format is Format.D24UnormS8Uint or Format.D32FloatS8Uint) { return FramebufferAttachment.DepthStencilAttachment; } diff --git a/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs b/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs index 84bb86a2d..fcd004dd6 100644 --- a/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs +++ b/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs @@ -358,7 +358,7 @@ namespace Ryujinx.Graphics.OpenGL.Image PixelFormat pixelFormat = format.PixelFormat; PixelType pixelType = format.PixelType; - if (target == TextureTarget.TextureCubeMap || target == TextureTarget.TextureCubeMapArray) + if (target is TextureTarget.TextureCubeMap or TextureTarget.TextureCubeMapArray) { target = TextureTarget.TextureCubeMapPositiveX + (layer % 6); } @@ -568,6 +568,7 @@ namespace Ryujinx.Graphics.OpenGL.Image format.PixelType, data); } + break; case Target.Texture1DArray: @@ -597,6 +598,7 @@ namespace Ryujinx.Graphics.OpenGL.Image format.PixelType, data); } + break; case Target.Texture2D: @@ -626,6 +628,7 @@ namespace Ryujinx.Graphics.OpenGL.Image format.PixelType, data); } + break; case Target.Texture2DArray: @@ -661,6 +664,7 @@ namespace Ryujinx.Graphics.OpenGL.Image format.PixelType, data); } + break; case Target.Cubemap: @@ -690,6 +694,7 @@ namespace Ryujinx.Graphics.OpenGL.Image format.PixelType, data); } + break; } } @@ -756,6 +761,7 @@ namespace Ryujinx.Graphics.OpenGL.Image format.PixelType, data); } + break; case Target.Texture1DArray: @@ -786,6 +792,7 @@ namespace Ryujinx.Graphics.OpenGL.Image format.PixelType, data); } + break; case Target.Texture2DArray: @@ -821,6 +828,7 @@ namespace Ryujinx.Graphics.OpenGL.Image format.PixelType, data); } + break; case Target.Cubemap: @@ -855,6 +863,7 @@ namespace Ryujinx.Graphics.OpenGL.Image data + faceOffset); } } + break; } diff --git a/src/Ryujinx.Graphics.OpenGL/Queries/BufferedQuery.cs b/src/Ryujinx.Graphics.OpenGL/Queries/BufferedQuery.cs index a5acd8dce..f39829923 100644 --- a/src/Ryujinx.Graphics.OpenGL/Queries/BufferedQuery.cs +++ b/src/Ryujinx.Graphics.OpenGL/Queries/BufferedQuery.cs @@ -31,6 +31,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries long defaultValue = DefaultValue; GL.BufferStorage(BufferTarget.QueryBuffer, sizeof(long), (nint)(&defaultValue), BufferStorageFlags.MapReadBit | BufferStorageFlags.MapWriteBit | BufferStorageFlags.MapPersistentBit); } + _bufferMap = GL.MapBufferRange(BufferTarget.QueryBuffer, nint.Zero, sizeof(long), BufferAccessMask.MapReadBit | BufferAccessMask.MapWriteBit | BufferAccessMask.MapPersistentBit); } diff --git a/src/Ryujinx.Graphics.OpenGL/Queries/CounterQueue.cs b/src/Ryujinx.Graphics.OpenGL/Queries/CounterQueue.cs index 88cdec983..0249440b4 100644 --- a/src/Ryujinx.Graphics.OpenGL/Queries/CounterQueue.cs +++ b/src/Ryujinx.Graphics.OpenGL/Queries/CounterQueue.cs @@ -172,6 +172,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries { return; // If not blocking, then return when we encounter an event that is not ready yet. } + _events.Dequeue(); } } diff --git a/src/Ryujinx.Graphics.OpenGL/ResourcePool.cs b/src/Ryujinx.Graphics.OpenGL/ResourcePool.cs index 352728813..ef6571fb9 100644 --- a/src/Ryujinx.Graphics.OpenGL/ResourcePool.cs +++ b/src/Ryujinx.Graphics.OpenGL/ResourcePool.cs @@ -108,6 +108,7 @@ namespace Ryujinx.Graphics.OpenGL texture.View.Dispose(); } } + _textures.Clear(); } } diff --git a/src/Ryujinx.Graphics.OpenGL/Sync.cs b/src/Ryujinx.Graphics.OpenGL/Sync.cs index 9fd7db9d1..a809a22f0 100644 --- a/src/Ryujinx.Graphics.OpenGL/Sync.cs +++ b/src/Ryujinx.Graphics.OpenGL/Sync.cs @@ -27,7 +27,6 @@ namespace Ryujinx.Graphics.OpenGL Handle = GL.FenceSync(SyncCondition.SyncGpuCommandsComplete, WaitSyncFlags.None), }; - if (HwCapabilities.RequiresSyncFlush) { // Force commands to flush up to the syncpoint. diff --git a/src/Ryujinx.Graphics.OpenGL/VertexArray.cs b/src/Ryujinx.Graphics.OpenGL/VertexArray.cs index bd8e9eafa..2480b6af2 100644 --- a/src/Ryujinx.Graphics.OpenGL/VertexArray.cs +++ b/src/Ryujinx.Graphics.OpenGL/VertexArray.cs @@ -104,8 +104,8 @@ namespace Ryujinx.Graphics.OpenGL int offset = attrib.Offset; int size = fmtInfo.Components; - bool isFloat = fmtInfo.PixelType == PixelType.Float || - fmtInfo.PixelType == PixelType.HalfFloat; + bool isFloat = fmtInfo.PixelType is PixelType.Float or + PixelType.HalfFloat; if (isFloat || fmtInfo.Normalized || fmtInfo.Scaled) { diff --git a/src/Ryujinx.Graphics.OpenGL/Window.cs b/src/Ryujinx.Graphics.OpenGL/Window.cs index 2813e03bc..bb4df0c06 100644 --- a/src/Ryujinx.Graphics.OpenGL/Window.cs +++ b/src/Ryujinx.Graphics.OpenGL/Window.cs @@ -340,6 +340,7 @@ namespace Ryujinx.Graphics.OpenGL _antiAliasing?.Dispose(); _antiAliasing = new SmaaPostProcessingEffect(_renderer, quality); } + break; } } @@ -371,6 +372,7 @@ namespace Ryujinx.Graphics.OpenGL _scalingFilter?.Dispose(); _scalingFilter = new FsrScalingFilter(_renderer); } + _isLinear = false; _scalingFilter.Level = _scalingFilterLevel; @@ -382,6 +384,7 @@ namespace Ryujinx.Graphics.OpenGL _scalingFilter?.Dispose(); _scalingFilter = new AreaScalingFilter(_renderer); } + _isLinear = false; RecreateUpscalingTexture(); diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs index 2677cba07..e0d7cdc4b 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs @@ -512,13 +512,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl if (context.Definitions.Stage == ShaderStage.Fragment && context.Definitions.DualSourceBlend) { IoDefinition firstOutput = outputs.ElementAtOrDefault(0); - IoDefinition secondOutput = outputs.ElementAtOrDefault(1); - if (firstOutput.Location + 1 == secondOutput.Location) - { - DeclareOutputDualSourceBlendAttribute(context, firstOutput.Location); - outputs = outputs.Skip(2); - } + DeclareOutputDualSourceBlendAttribute(context, firstOutput.Location); + outputs = outputs.Skip(2); } foreach (IoDefinition ioDefinition in outputs) @@ -633,9 +629,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl } else { - return stage == ShaderStage.TessellationControl || - stage == ShaderStage.TessellationEvaluation || - stage == ShaderStage.Geometry; + return stage is ShaderStage.TessellationControl or + ShaderStage.TessellationEvaluation or + ShaderStage.Geometry; } } diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs index 9e7f64b0e..939b57aa7 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs @@ -74,7 +74,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions { builder.Append(GenerateLoadOrStore(context, operation, isStore: false)); - AggregateType dstType = operation.Inst == Instruction.AtomicMaxS32 || operation.Inst == Instruction.AtomicMinS32 + AggregateType dstType = operation.Inst is Instruction.AtomicMaxS32 or Instruction.AtomicMinS32 ? AggregateType.S32 : AggregateType.U32; diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs index 634f9364a..32c930557 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs @@ -595,6 +595,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions varName = $"gl_out[{expr}].{varName}"; } } + break; default: diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstType.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstType.cs index 56985ae08..43ff12168 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstType.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstType.cs @@ -4,7 +4,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions { [Flags] - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum InstType { OpNullary = Op | 0, diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs index caa6ef642..8c45c0b67 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs @@ -79,9 +79,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions } else { - return stage == ShaderStage.TessellationControl || - stage == ShaderStage.TessellationEvaluation || - stage == ShaderStage.Geometry; + return stage is ShaderStage.TessellationControl or + ShaderStage.TessellationEvaluation or + ShaderStage.Geometry; } } diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/NumberFormatter.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/NumberFormatter.cs index 28e44c900..b32e28e04 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/NumberFormatter.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/NumberFormatter.cs @@ -83,7 +83,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl public static string FormatInt(int value) { - if (value <= MaxDecimal && value >= -MaxDecimal) + if (value is <= MaxDecimal and >= (-MaxDecimal)) { return value.ToString(CultureInfo.InvariantCulture); } @@ -93,7 +93,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl public static string FormatUint(uint value) { - if (value <= MaxDecimal && value >= 0) + if (value is <= MaxDecimal and >= 0) { return value.ToString(CultureInfo.InvariantCulture) + "u"; } diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs index a350b089c..6c20cb0c8 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs @@ -97,8 +97,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl } IoVariable ioVariable = (IoVariable)varId.Value; - bool isOutput = operation.StorageKind == StorageKind.Output || operation.StorageKind == StorageKind.OutputPerPatch; - bool isPerPatch = operation.StorageKind == StorageKind.InputPerPatch || operation.StorageKind == StorageKind.OutputPerPatch; + bool isOutput = operation.StorageKind is StorageKind.Output or StorageKind.OutputPerPatch; + bool isPerPatch = operation.StorageKind is StorageKind.InputPerPatch or StorageKind.OutputPerPatch; int location = 0; int component = 0; diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs index 39b27a3e1..27b5c21c0 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs @@ -1695,6 +1695,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv varType = context.Properties.SharedMemories[bindingId.Value].Type & AggregateType.ElementTypeMask; baseObj = context.SharedMemories[bindingId.Value]; } + break; case StorageKind.Input: diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/IoMap.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/IoMap.cs index 7b4e14ff0..1fd8a731a 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/IoMap.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/IoMap.cs @@ -104,9 +104,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv } else { - return stage == ShaderStage.TessellationControl || - stage == ShaderStage.TessellationEvaluation || - stage == ShaderStage.Geometry; + return stage is ShaderStage.TessellationControl or + ShaderStage.TessellationEvaluation or + ShaderStage.Geometry; } } diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs index db4de586a..e1561446b 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs @@ -89,8 +89,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv context.AddCapability(Capability.GeometryShaderPassthroughNV); } } - else if (parameters.Definitions.Stage == ShaderStage.TessellationControl || - parameters.Definitions.Stage == ShaderStage.TessellationEvaluation) + else if (parameters.Definitions.Stage is ShaderStage.TessellationControl or + ShaderStage.TessellationEvaluation) { context.AddCapability(Capability.Tessellation); } diff --git a/src/Ryujinx.Graphics.Shader/Decoders/Decoder.cs b/src/Ryujinx.Graphics.Shader/Decoders/Decoder.cs index 72e934a39..ac1f24218 100644 --- a/src/Ryujinx.Graphics.Shader/Decoders/Decoder.cs +++ b/src/Ryujinx.Graphics.Shader/Decoders/Decoder.cs @@ -392,7 +392,7 @@ namespace Ryujinx.Graphics.Shader.Decoders if (perPatch) { - if (attr >= AttributeConsts.UserAttributePerPatchBase && attr < AttributeConsts.UserAttributePerPatchEnd) + if (attr is >= AttributeConsts.UserAttributePerPatchBase and < AttributeConsts.UserAttributePerPatchEnd) { int userAttr = attr - AttributeConsts.UserAttributePerPatchBase; int index = userAttr / 16; @@ -407,7 +407,7 @@ namespace Ryujinx.Graphics.Shader.Decoders } } } - else if (attr >= AttributeConsts.UserAttributeBase && attr < AttributeConsts.UserAttributeEnd) + else if (attr is >= AttributeConsts.UserAttributeBase and < AttributeConsts.UserAttributeEnd) { int userAttr = attr - AttributeConsts.UserAttributeBase; int index = userAttr / 16; @@ -436,16 +436,18 @@ namespace Ryujinx.Graphics.Shader.Decoders switch (attr) { case AttributeConsts.Layer: - if (definitions.Stage != ShaderStage.Compute && definitions.Stage != ShaderStage.Fragment) + if (definitions.Stage is not ShaderStage.Compute and not ShaderStage.Fragment) { context.SetUsedFeature(FeatureFlags.RtLayer); } + break; case AttributeConsts.ViewportIndex: if (definitions.Stage != ShaderStage.Fragment) { context.SetUsedFeature(FeatureFlags.ViewportIndex); } + break; case AttributeConsts.ClipDistance0: case AttributeConsts.ClipDistance1: @@ -459,12 +461,14 @@ namespace Ryujinx.Graphics.Shader.Decoders { context.SetClipDistanceWritten((attr - AttributeConsts.ClipDistance0) / 4); } + break; case AttributeConsts.ViewportMask: if (definitions.Stage != ShaderStage.Fragment) { context.SetUsedFeature(FeatureFlags.ViewportMask); } + break; } } @@ -478,12 +482,14 @@ namespace Ryujinx.Graphics.Shader.Decoders { context.SetUsedFeature(FeatureFlags.FragCoordXY); } + break; case AttributeConsts.InstanceId: if (definitions.Stage == ShaderStage.Vertex) { context.SetUsedFeature(FeatureFlags.InstanceId); } + break; } } @@ -879,7 +885,7 @@ namespace Ryujinx.Graphics.Shader.Decoders public static bool IsPopBranch(InstName name) { - return name == InstName.Brk || name == InstName.Cont || name == InstName.Sync; + return name is InstName.Brk or InstName.Cont or InstName.Sync; } private static MergeType GetMergeTypeFromPush(InstName name) diff --git a/src/Ryujinx.Graphics.Shader/Instructions/AttributeMap.cs b/src/Ryujinx.Graphics.Shader/Instructions/AttributeMap.cs index 572cc513d..b89502e16 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/AttributeMap.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/AttributeMap.cs @@ -1,6 +1,7 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.Translation; using System.Collections.Generic; +using System.Collections.ObjectModel; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; namespace Ryujinx.Graphics.Shader.Instructions @@ -46,8 +47,8 @@ namespace Ryujinx.Graphics.Shader.Instructions } } - private static readonly IReadOnlyDictionary _attributes; - private static readonly IReadOnlyDictionary _attributesPerPatch; + private static readonly ReadOnlyDictionary _attributes; + private static readonly ReadOnlyDictionary _attributesPerPatch; static AttributeMap() { @@ -55,7 +56,7 @@ namespace Ryujinx.Graphics.Shader.Instructions _attributesPerPatch = CreatePerPatchMap(); } - private static IReadOnlyDictionary CreateMap() + private static ReadOnlyDictionary CreateMap() { Dictionary map = new(); @@ -79,10 +80,10 @@ namespace Ryujinx.Graphics.Shader.Instructions Add(map, 0x3a0, AggregateType.Array | AggregateType.S32, IoVariable.ViewportMask, StagesMask.Fragment, StagesMask.VertexTessellationGeometry); Add(map, 0x3fc, AggregateType.Bool, IoVariable.FrontFacing, StagesMask.Fragment, StagesMask.None); - return map; + return map.AsReadOnly(); } - private static IReadOnlyDictionary CreatePerPatchMap() + private static ReadOnlyDictionary CreatePerPatchMap() { Dictionary map = new(); @@ -90,7 +91,7 @@ namespace Ryujinx.Graphics.Shader.Instructions Add(map, 0x010, AggregateType.Vector2 | AggregateType.FP32, IoVariable.TessellationLevelInner, StagesMask.TessellationEvaluation, StagesMask.TessellationControl); Add(map, 0x018, AggregateType.Vector4 | AggregateType.FP32, IoVariable.UserDefined, StagesMask.TessellationEvaluation, StagesMask.TessellationControl, 31, 0x200); - return map; + return map.AsReadOnly(); } private static void Add( @@ -326,9 +327,9 @@ namespace Ryujinx.Graphics.Shader.Instructions return false; } - return stage == ShaderStage.TessellationControl || - stage == ShaderStage.TessellationEvaluation || - stage == ShaderStage.Geometry; + return stage is ShaderStage.TessellationControl or + ShaderStage.TessellationEvaluation or + ShaderStage.Geometry; } public static bool HasInvocationId(ShaderStage stage, bool isOutput) diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs index 0c2f90b7e..d77621db6 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs @@ -331,7 +331,8 @@ namespace Ryujinx.Graphics.Shader.Instructions { context.GetOp(); - context.TranslatorContext.GpuAccessor.Log("Shader instruction Votevtg is not implemented."); + // This instruction is proprietary and will not be implemented. Commenting it out to avoid false reports. + //context.TranslatorContext.GpuAccessor.Log("Shader instruction Votevtg is not implemented."); } public static void Vset(EmitterContext context) diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs index 89b7e9831..2b6647cd2 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs @@ -164,7 +164,7 @@ namespace Ryujinx.Graphics.Shader.Instructions { isFixedFunc = TryFixedFuncToUserAttributeIpa(context, op.Imm10, out res); - if (op.Imm10 >= AttributeConsts.UserAttributeBase && op.Imm10 < AttributeConsts.UserAttributeEnd) + if (op.Imm10 is >= AttributeConsts.UserAttributeBase and < AttributeConsts.UserAttributeEnd) { int index = (op.Imm10 - AttributeConsts.UserAttributeBase) >> 4; @@ -173,7 +173,7 @@ namespace Ryujinx.Graphics.Shader.Instructions res = context.FPMultiply(res, context.Load(StorageKind.Input, IoVariable.FragmentCoord, null, Const(3))); } } - else if (op.Imm10 == AttributeConsts.PositionX || op.Imm10 == AttributeConsts.PositionY) + else if (op.Imm10 is AttributeConsts.PositionX or AttributeConsts.PositionY) { // FragCoord X/Y must be divided by the render target scale, if resolution scaling is active, // because the shader code is not expecting scaled values. @@ -296,19 +296,19 @@ namespace Ryujinx.Graphics.Shader.Instructions private static bool HasPrimitiveVertex(int attr) { - return attr != AttributeConsts.PrimitiveId && - attr != AttributeConsts.TessCoordX && - attr != AttributeConsts.TessCoordY; + return attr is not AttributeConsts.PrimitiveId and + not AttributeConsts.TessCoordX and + not AttributeConsts.TessCoordY; } private static bool CanLoadOutput(int attr) { - return attr != AttributeConsts.TessCoordX && attr != AttributeConsts.TessCoordY; + return attr is not AttributeConsts.TessCoordX and not AttributeConsts.TessCoordY; } private static bool TryFixedFuncToUserAttributeIpa(EmitterContext context, int attr, out Operand selectedAttr) { - if (attr >= AttributeConsts.FrontColorDiffuseR && attr < AttributeConsts.BackColorDiffuseR) + if (attr is >= AttributeConsts.FrontColorDiffuseR and < AttributeConsts.BackColorDiffuseR) { // TODO: If two sided rendering is enabled, then this should return // FrontColor if the fragment is front facing, and back color otherwise. @@ -321,12 +321,12 @@ namespace Ryujinx.Graphics.Shader.Instructions selectedAttr = GenerateIpaLoad(context, FixedFuncToUserAttribute(context.TranslatorContext, attr, isOutput: false)); return true; } - else if (attr >= AttributeConsts.BackColorDiffuseR && attr < AttributeConsts.ClipDistance0) + else if (attr is >= AttributeConsts.BackColorDiffuseR and < AttributeConsts.ClipDistance0) { selectedAttr = ConstF(((attr >> 2) & 3) == 3 ? 1f : 0f); return true; } - else if (attr >= AttributeConsts.TexCoordBase && attr < AttributeConsts.TexCoordEnd) + else if (attr is >= AttributeConsts.TexCoordBase and < AttributeConsts.TexCoordEnd) { selectedAttr = GenerateIpaLoad(context, FixedFuncToUserAttribute(context.TranslatorContext, attr, isOutput: false)); return true; @@ -355,11 +355,11 @@ namespace Ryujinx.Graphics.Shader.Instructions { attr = FixedFuncToUserAttribute(translatorContext, attr, AttributeConsts.FogCoord, fixedStartAttr, isOutput); } - else if (attr >= AttributeConsts.FrontColorDiffuseR && attr < AttributeConsts.ClipDistance0) + else if (attr is >= AttributeConsts.FrontColorDiffuseR and < AttributeConsts.ClipDistance0) { attr = FixedFuncToUserAttribute(translatorContext, attr, AttributeConsts.FrontColorDiffuseR, fixedStartAttr + 1, isOutput); } - else if (attr >= AttributeConsts.TexCoordBase && attr < AttributeConsts.TexCoordEnd) + else if (attr is >= AttributeConsts.TexCoordBase and < AttributeConsts.TexCoordEnd) { attr = FixedFuncToUserAttribute(translatorContext, attr, AttributeConsts.TexCoordBase, fixedStartAttr + 5, isOutput); } diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs index 198c9077a..4b917c1eb 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs @@ -179,8 +179,8 @@ namespace Ryujinx.Graphics.Shader.Instructions Instruction fpType = srcType.ToInstFPType(); - bool isSignedInt = dstType == IDstFmt.S16 || dstType == IDstFmt.S32 || dstType == IDstFmt.S64; - bool isSmallInt = dstType == IDstFmt.U16 || dstType == IDstFmt.S16; + bool isSignedInt = dstType is IDstFmt.S16 or IDstFmt.S32 or IDstFmt.S64; + bool isSmallInt = dstType is IDstFmt.U16 or IDstFmt.S16; Operand srcB = context.FPAbsNeg(src, absolute, negate, fpType); @@ -242,15 +242,15 @@ namespace Ryujinx.Graphics.Shader.Instructions bool negate) { bool isSignedInt = - srcType == ISrcFmt.S8 || - srcType == ISrcFmt.S16 || - srcType == ISrcFmt.S32 || - srcType == ISrcFmt.S64; + srcType is ISrcFmt.S8 or + ISrcFmt.S16 or + ISrcFmt.S32 or + ISrcFmt.S64; bool isSmallInt = - srcType == ISrcFmt.U16 || - srcType == ISrcFmt.S16 || - srcType == ISrcFmt.U8 || - srcType == ISrcFmt.S8; + srcType is ISrcFmt.U16 or + ISrcFmt.S16 or + ISrcFmt.U8 or + ISrcFmt.S8; // TODO: Handle S/U64. @@ -258,7 +258,7 @@ namespace Ryujinx.Graphics.Shader.Instructions if (isSmallInt) { - int size = srcType == ISrcFmt.U16 || srcType == ISrcFmt.S16 ? 16 : 8; + int size = srcType is ISrcFmt.U16 or ISrcFmt.S16 ? 16 : 8; srcB = isSignedInt ? context.BitfieldExtractS32(srcB, Const((int)byteSelection * 8), Const(size)) @@ -302,22 +302,22 @@ namespace Ryujinx.Graphics.Shader.Instructions } bool srcIsSignedInt = - srcType == ISrcDstFmt.S8 || - srcType == ISrcDstFmt.S16 || - srcType == ISrcDstFmt.S32; + srcType is ISrcDstFmt.S8 or + ISrcDstFmt.S16 or + ISrcDstFmt.S32; bool dstIsSignedInt = - dstType == ISrcDstFmt.S8 || - dstType == ISrcDstFmt.S16 || - dstType == ISrcDstFmt.S32; + dstType is ISrcDstFmt.S8 or + ISrcDstFmt.S16 or + ISrcDstFmt.S32; bool srcIsSmallInt = - srcType == ISrcDstFmt.U16 || - srcType == ISrcDstFmt.S16 || - srcType == ISrcDstFmt.U8 || - srcType == ISrcDstFmt.S8; + srcType is ISrcDstFmt.U16 or + ISrcDstFmt.S16 or + ISrcDstFmt.U8 or + ISrcDstFmt.S8; if (srcIsSmallInt) { - int size = srcType == ISrcDstFmt.U16 || srcType == ISrcDstFmt.S16 ? 16 : 8; + int size = srcType is ISrcDstFmt.U16 or ISrcDstFmt.S16 ? 16 : 8; src = srcIsSignedInt ? context.BitfieldExtractS32(src, Const((int)byteSelection * 8), Const(size)) diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatComparison.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatComparison.cs index 314ab917c..e70afd74c 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatComparison.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatComparison.cs @@ -534,7 +534,7 @@ namespace Ryujinx.Graphics.Shader.Instructions { res = Const(IrConsts.False); } - else if (cond == FComp.Nan || cond == FComp.Num) + else if (cond is FComp.Nan or FComp.Num) { res = context.BitwiseOr(context.IsNan(srcA, fpType), context.IsNan(srcB, fpType)); diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs index 3fcb821d3..154ed24fc 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs @@ -73,7 +73,7 @@ namespace Ryujinx.Graphics.Shader.Instructions Operand slot = Const(op.CbufSlot); Operand srcA = GetSrcReg(context, op.SrcA); - if (op.AddressMode == AddressMode.Is || op.AddressMode == AddressMode.Isl) + if (op.AddressMode is AddressMode.Is or AddressMode.Isl) { slot = context.IAdd(slot, context.BitfieldExtractU32(srcA, Const(16), Const(16))); srcA = context.BitwiseAnd(srcA, Const(0xffff)); @@ -213,7 +213,7 @@ namespace Ryujinx.Graphics.Shader.Instructions switch (op) { case AtomOp.Add: - if (type == AtomSize.S32 || type == AtomSize.U32) + if (type is AtomSize.S32 or AtomSize.U32) { res = context.AtomicAdd(storageKind, e0, e1, value); } @@ -221,6 +221,7 @@ namespace Ryujinx.Graphics.Shader.Instructions { context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}."); } + break; case AtomOp.Min: if (type == AtomSize.S32) @@ -235,6 +236,7 @@ namespace Ryujinx.Graphics.Shader.Instructions { context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}."); } + break; case AtomOp.Max: if (type == AtomSize.S32) @@ -249,9 +251,10 @@ namespace Ryujinx.Graphics.Shader.Instructions { context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}."); } + break; case AtomOp.And: - if (type == AtomSize.S32 || type == AtomSize.U32) + if (type is AtomSize.S32 or AtomSize.U32) { res = context.AtomicAnd(storageKind, e0, e1, value); } @@ -259,9 +262,10 @@ namespace Ryujinx.Graphics.Shader.Instructions { context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}."); } + break; case AtomOp.Or: - if (type == AtomSize.S32 || type == AtomSize.U32) + if (type is AtomSize.S32 or AtomSize.U32) { res = context.AtomicOr(storageKind, e0, e1, value); } @@ -269,9 +273,10 @@ namespace Ryujinx.Graphics.Shader.Instructions { context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}."); } + break; case AtomOp.Xor: - if (type == AtomSize.S32 || type == AtomSize.U32) + if (type is AtomSize.S32 or AtomSize.U32) { res = context.AtomicXor(storageKind, e0, e1, value); } @@ -279,9 +284,10 @@ namespace Ryujinx.Graphics.Shader.Instructions { context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}."); } + break; case AtomOp.Exch: - if (type == AtomSize.S32 || type == AtomSize.U32) + if (type is AtomSize.S32 or AtomSize.U32) { res = context.AtomicSwap(storageKind, e0, e1, value); } @@ -289,6 +295,7 @@ namespace Ryujinx.Graphics.Shader.Instructions { context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}."); } + break; default: context.TranslatorContext.GpuAccessor.Log($"Invalid atomic operation: {op}."); diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs index 944039d65..df84c38f1 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs @@ -92,14 +92,14 @@ namespace Ryujinx.Graphics.Shader.Instructions break; case SReg.InvocationInfo: - if (context.TranslatorContext.Definitions.Stage != ShaderStage.Compute && context.TranslatorContext.Definitions.Stage != ShaderStage.Fragment) + if (context.TranslatorContext.Definitions.Stage is not ShaderStage.Compute and not ShaderStage.Fragment) { // Note: Lowest 8-bits seems to contain some primitive index, // but it seems to be NVIDIA implementation specific as it's only used // to calculate ISBE offsets, so we can just keep it as zero. - if (context.TranslatorContext.Definitions.Stage == ShaderStage.TessellationControl || - context.TranslatorContext.Definitions.Stage == ShaderStage.TessellationEvaluation) + if (context.TranslatorContext.Definitions.Stage is ShaderStage.TessellationControl or + ShaderStage.TessellationEvaluation) { src = context.ShiftLeft(context.Load(StorageKind.Input, IoVariable.PatchVertices), Const(16)); } @@ -112,6 +112,7 @@ namespace Ryujinx.Graphics.Shader.Instructions { src = Const(0); } + break; case SReg.TId: diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitShift.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitShift.cs index 7e2145c37..9c7899940 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitShift.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitShift.cs @@ -115,7 +115,7 @@ namespace Ryujinx.Graphics.Shader.Instructions bool left, bool writeCC) { - bool isLongShift = maxShift == MaxShift.U64 || maxShift == MaxShift.S64; + bool isLongShift = maxShift is MaxShift.U64 or MaxShift.S64; bool signedShift = maxShift == MaxShift.S64; int maxShiftConst = isLongShift ? 64 : 32; diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs index 946dcc02e..e9f930179 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs @@ -258,7 +258,7 @@ namespace Ryujinx.Graphics.Shader.Instructions } // TODO: FP and 64-bit formats. - TextureFormat format = size == SuatomSize.Sd32 || size == SuatomSize.Sd64 + TextureFormat format = size is SuatomSize.Sd32 or SuatomSize.Sd64 ? (isBindless ? TextureFormat.Unknown : ShaderProperties.GetTextureFormatAtomic(context.TranslatorContext.GpuAccessor, imm)) : GetTextureFormat(size); @@ -537,7 +537,7 @@ namespace Ryujinx.Graphics.Shader.Instructions } // TODO: FP and 64-bit formats. - TextureFormat format = size == SuatomSize.Sd32 || size == SuatomSize.Sd64 + TextureFormat format = size is SuatomSize.Sd32 or SuatomSize.Sd64 ? (isBindless ? TextureFormat.Unknown : ShaderProperties.GetTextureFormatAtomic(context.TranslatorContext.GpuAccessor, imm)) : GetTextureFormat(size); diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs index 7499f12d8..19b22e03b 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs @@ -284,7 +284,7 @@ namespace Ryujinx.Graphics.Shader.Instructions flags |= TextureFlags.Offset; } - if (lodMode == Lod.Lb || lodMode == Lod.Lba) + if (lodMode is Lod.Lb or Lod.Lba) { sourcesList.Add(lodValue); @@ -504,6 +504,7 @@ namespace Ryujinx.Graphics.Shader.Instructions sourcesList.Add(ConstF(0)); } + break; case TldsTarget.Texture1DLodLevel: @@ -694,10 +695,10 @@ namespace Ryujinx.Graphics.Shader.Instructions } bool isArray = - dimensions == TexDim.Array1d || - dimensions == TexDim.Array2d || - dimensions == TexDim.Array3d || - dimensions == TexDim.ArrayCube; + dimensions is TexDim.Array1d or + TexDim.Array2d or + TexDim.Array3d or + TexDim.ArrayCube; Operand arrayIndex = isArray ? Ra() : null; @@ -736,7 +737,7 @@ namespace Ryujinx.Graphics.Shader.Instructions Operand[] packedOffs = new Operand[2]; - bool hasAnyOffset = offset == TexOffset.Aoffi || offset == TexOffset.Ptp; + bool hasAnyOffset = offset is TexOffset.Aoffi or TexOffset.Ptp; packedOffs[0] = hasAnyOffset ? Rb() : null; packedOffs[1] = offset == TexOffset.Ptp ? Rb() : null; @@ -849,10 +850,10 @@ namespace Ryujinx.Graphics.Shader.Instructions int coordsCount = type.GetDimensions(); bool isArray = - dimensions == TexDim.Array1d || - dimensions == TexDim.Array2d || - dimensions == TexDim.Array3d || - dimensions == TexDim.ArrayCube; + dimensions is TexDim.Array1d or + TexDim.Array2d or + TexDim.Array3d or + TexDim.ArrayCube; Operand arrayIndex = isArray ? Ra() : null; @@ -993,10 +994,10 @@ namespace Ryujinx.Graphics.Shader.Instructions Operand packedParams = Ra(); bool isArray = - dimensions == TexDim.Array1d || - dimensions == TexDim.Array2d || - dimensions == TexDim.Array3d || - dimensions == TexDim.ArrayCube; + dimensions is TexDim.Array1d or + TexDim.Array2d or + TexDim.Array3d or + TexDim.ArrayCube; if (isArray) { @@ -1143,6 +1144,7 @@ namespace Ryujinx.Graphics.Shader.Instructions context.Copy(d, context.TextureQuerySize(type, flags, setAndBinding, compIndex, sources)); } } + break; case TexQuery.TexHeaderTextureType: @@ -1174,6 +1176,7 @@ namespace Ryujinx.Graphics.Shader.Instructions context.Copy(d, context.TextureQuerySamples(type, flags, setAndBinding, sources)); } } + break; default: diff --git a/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs b/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs index 273a38a5b..f63a8c4be 100644 --- a/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs +++ b/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs @@ -179,19 +179,19 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation public static bool IsTextureQuery(this Instruction inst) { inst &= Instruction.Mask; - return inst == Instruction.Lod || inst == Instruction.TextureQuerySamples || inst == Instruction.TextureQuerySize; + return inst is Instruction.Lod or Instruction.TextureQuerySamples or Instruction.TextureQuerySize; } public static bool IsImage(this Instruction inst) { inst &= Instruction.Mask; - return inst == Instruction.ImageAtomic || inst == Instruction.ImageLoad || inst == Instruction.ImageStore; + return inst is Instruction.ImageAtomic or Instruction.ImageLoad or Instruction.ImageStore; } public static bool IsImageStore(this Instruction inst) { inst &= Instruction.Mask; - return inst == Instruction.ImageAtomic || inst == Instruction.ImageStore; + return inst is Instruction.ImageAtomic or Instruction.ImageStore; } } } diff --git a/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/StorageKind.cs b/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/StorageKind.cs index 669c12816..2b39e85ea 100644 --- a/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/StorageKind.cs +++ b/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/StorageKind.cs @@ -24,22 +24,22 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation { public static bool IsInputOrOutput(this StorageKind storageKind) { - return storageKind == StorageKind.Input || - storageKind == StorageKind.InputPerPatch || - storageKind == StorageKind.Output || - storageKind == StorageKind.OutputPerPatch; + return storageKind is StorageKind.Input or + StorageKind.InputPerPatch or + StorageKind.Output or + StorageKind.OutputPerPatch; } public static bool IsOutput(this StorageKind storageKind) { - return storageKind == StorageKind.Output || - storageKind == StorageKind.OutputPerPatch; + return storageKind is StorageKind.Output or + StorageKind.OutputPerPatch; } public static bool IsPerPatch(this StorageKind storageKind) { - return storageKind == StorageKind.InputPerPatch || - storageKind == StorageKind.OutputPerPatch; + return storageKind is StorageKind.InputPerPatch or + StorageKind.OutputPerPatch; } } } diff --git a/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureFlags.cs b/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureFlags.cs index 51ff09cf8..61e6ecf5a 100644 --- a/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureFlags.cs +++ b/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureFlags.cs @@ -4,7 +4,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.Graphics.Shader.IntermediateRepresentation { [Flags] - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum TextureFlags { None = 0, diff --git a/src/Ryujinx.Graphics.Shader/ShaderStage.cs b/src/Ryujinx.Graphics.Shader/ShaderStage.cs index 2522b4fc1..faea5c357 100644 --- a/src/Ryujinx.Graphics.Shader/ShaderStage.cs +++ b/src/Ryujinx.Graphics.Shader/ShaderStage.cs @@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.Shader /// True if the shader stage supports render scale, false otherwise public static bool SupportsRenderScale(this ShaderStage stage) { - return stage == ShaderStage.Vertex || stage == ShaderStage.Fragment || stage == ShaderStage.Compute; + return stage is ShaderStage.Vertex or ShaderStage.Fragment or ShaderStage.Compute; } /// @@ -31,10 +31,10 @@ namespace Ryujinx.Graphics.Shader /// True if the shader stage is vertex, tessellation or geometry, false otherwise public static bool IsVtg(this ShaderStage stage) { - return stage == ShaderStage.Vertex || - stage == ShaderStage.TessellationControl || - stage == ShaderStage.TessellationEvaluation || - stage == ShaderStage.Geometry; + return stage is ShaderStage.Vertex or + ShaderStage.TessellationControl or + ShaderStage.TessellationEvaluation or + ShaderStage.Geometry; } } } diff --git a/src/Ryujinx.Graphics.Shader/StructuredIr/GotoElimination.cs b/src/Ryujinx.Graphics.Shader/StructuredIr/GotoElimination.cs index 687e5942d..e2e52586a 100644 --- a/src/Ryujinx.Graphics.Shader/StructuredIr/GotoElimination.cs +++ b/src/Ryujinx.Graphics.Shader/StructuredIr/GotoElimination.cs @@ -102,8 +102,8 @@ namespace Ryujinx.Graphics.Shader.StructuredIr return false; } - IAstNode block; - IAstNode other; + AstNode block; + AstNode other; int blockLvl, otherLvl; @@ -441,7 +441,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr return path.ToArray(); } - private static int Level(IAstNode node) + private static int Level(AstNode node) { int level = 0; diff --git a/src/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs b/src/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs index 72d0e9896..b2ddf6ab7 100644 --- a/src/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs +++ b/src/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs @@ -150,11 +150,11 @@ namespace Ryujinx.Graphics.Shader.StructuredIr { // TODO: Return correct type depending on source index, // that can improve the decompiler output. - if (inst == Instruction.ImageLoad || - inst == Instruction.ImageStore || - inst == Instruction.ImageAtomic || - inst == Instruction.Lod || - inst == Instruction.TextureSample) + if (inst is Instruction.ImageLoad or + Instruction.ImageStore or + Instruction.ImageAtomic or + Instruction.Lod or + Instruction.TextureSample) { return AggregateType.FP32; } diff --git a/src/Ryujinx.Graphics.Shader/StructuredIr/ShaderProperties.cs b/src/Ryujinx.Graphics.Shader/StructuredIr/ShaderProperties.cs index f56d7bff3..f0f22c056 100644 --- a/src/Ryujinx.Graphics.Shader/StructuredIr/ShaderProperties.cs +++ b/src/Ryujinx.Graphics.Shader/StructuredIr/ShaderProperties.cs @@ -87,7 +87,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr private static bool FormatSupportsAtomic(TextureFormat format) { - return format == TextureFormat.R32Sint || format == TextureFormat.R32Uint; + return format is TextureFormat.R32Sint or TextureFormat.R32Uint; } public static TextureFormat GetTextureFormatAtomic(IGpuAccessor gpuAccessor, int handle, int cbufSlot = -1) diff --git a/src/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs b/src/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs index 824aea195..63bd820dc 100644 --- a/src/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs +++ b/src/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs @@ -83,7 +83,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr Instruction inst = operation.Inst; StorageKind storageKind = operation.StorageKind; - if (inst == Instruction.Load || inst == Instruction.Store) + if (inst is Instruction.Load or Instruction.Store) { if (storageKind.IsInputOrOutput()) { diff --git a/src/Ryujinx.Graphics.Shader/TextureHandle.cs b/src/Ryujinx.Graphics.Shader/TextureHandle.cs index 3aaceac48..d2132172d 100644 --- a/src/Ryujinx.Graphics.Shader/TextureHandle.cs +++ b/src/Ryujinx.Graphics.Shader/TextureHandle.cs @@ -110,8 +110,8 @@ namespace Ryujinx.Graphics.Shader samplerHandle = samplerWordOffset; } - if (handleType == TextureHandleType.SeparateSamplerId || - handleType == TextureHandleType.SeparateConstantSamplerHandle) + if (handleType is TextureHandleType.SeparateSamplerId or + TextureHandleType.SeparateConstantSamplerHandle) { samplerHandle <<= 20; } diff --git a/src/Ryujinx.Graphics.Shader/Translation/AggregateType.cs b/src/Ryujinx.Graphics.Shader/Translation/AggregateType.cs index 108fcb94f..496fbc235 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/AggregateType.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/AggregateType.cs @@ -4,7 +4,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.Graphics.Shader.Translation { [Flags] - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum AggregateType { Invalid, diff --git a/src/Ryujinx.Graphics.Shader/Translation/ControlFlowGraph.cs b/src/Ryujinx.Graphics.Shader/Translation/ControlFlowGraph.cs index e14044256..1df45a478 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/ControlFlowGraph.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/ControlFlowGraph.cs @@ -110,9 +110,9 @@ namespace Ryujinx.Graphics.Shader.Translation currentBlock.Operations.AddLast(operation); } - needsNewBlock = operation.Inst == Instruction.Branch || - operation.Inst == Instruction.BranchIfTrue || - operation.Inst == Instruction.BranchIfFalse; + needsNewBlock = operation.Inst is Instruction.Branch or + Instruction.BranchIfTrue or + Instruction.BranchIfFalse; if (needsNewBlock) { diff --git a/src/Ryujinx.Graphics.Shader/Translation/HelperFunctionManager.cs b/src/Ryujinx.Graphics.Shader/Translation/HelperFunctionManager.cs index ef2f8759d..ec181bb09 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/HelperFunctionManager.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/HelperFunctionManager.cs @@ -470,6 +470,5 @@ namespace Ryujinx.Graphics.Shader.Translation return oldValue; } - } } diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs index 3941303b1..345e83c82 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs @@ -167,6 +167,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations operation.TurnIntoCopy(Cbuf(cbufSlot, cbufOffset)); } } + break; case Instruction.Maximum: diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs index 4805fb1ca..55628c88b 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs @@ -91,7 +91,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations return functionId; } - public bool TryGetFunctionId(Operation baseOp, bool isMultiTarget, IReadOnlyList targetCbs, out int functionId) + public bool TryGetFunctionId(Operation baseOp, bool isMultiTarget, List targetCbs, out int functionId) { foreach (Entry entry in _entries) { @@ -281,19 +281,19 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations private static bool IsGlobalMemory(StorageKind storageKind) { - return storageKind == StorageKind.GlobalMemory || - storageKind == StorageKind.GlobalMemoryS8 || - storageKind == StorageKind.GlobalMemoryS16 || - storageKind == StorageKind.GlobalMemoryU8 || - storageKind == StorageKind.GlobalMemoryU16; + return storageKind is StorageKind.GlobalMemory or + StorageKind.GlobalMemoryS8 or + StorageKind.GlobalMemoryS16 or + StorageKind.GlobalMemoryU8 or + StorageKind.GlobalMemoryU16; } private static bool IsSmallInt(StorageKind storageKind) { - return storageKind == StorageKind.GlobalMemoryS8 || - storageKind == StorageKind.GlobalMemoryS16 || - storageKind == StorageKind.GlobalMemoryU8 || - storageKind == StorageKind.GlobalMemoryU16; + return storageKind is StorageKind.GlobalMemoryS8 or + StorageKind.GlobalMemoryS16 or + StorageKind.GlobalMemoryU8 or + StorageKind.GlobalMemoryU16; } private static LinkedListNode ReplaceGlobalMemoryWithStorage( @@ -865,6 +865,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations return context.IMaximumS32(memValue, value); }); } + break; case Instruction.AtomicMaxU32: resultValue = context.AtomicMaxU32(StorageKind.StorageBuffer, binding, Const(0), wordOffset, value); @@ -881,6 +882,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations return context.IMinimumS32(memValue, value); }); } + break; case Instruction.AtomicMinU32: resultValue = context.AtomicMinU32(StorageKind.StorageBuffer, binding, Const(0), wordOffset, value); @@ -1100,7 +1102,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations { baseOffset = null; - if (operation.Inst == Instruction.Load || operation.Inst == Instruction.Store) + if (operation.Inst is Instruction.Load or Instruction.Store) { if (operation.StorageKind == StorageKind.SharedMemory) { diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs index 1be7c5c52..022532af8 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs @@ -9,6 +9,11 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations { public static void RunPass(TransformContext context) { + for (int blkIndex = 0; blkIndex < context.Blocks.Length; blkIndex++) + { + XmadOptimizer.RunPass(context.Blocks[blkIndex]); + } + RunOptimizationPasses(context.Blocks, context.ResourceManager); // TODO: Some of those are not optimizations and shouldn't be here. @@ -355,7 +360,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations operation.TurnIntoCopy(attrMulLhs); } - private static void RemoveNode(BasicBlock block, LinkedListNode llNode) + public static void RemoveNode(BasicBlock block, LinkedListNode llNode) { // Remove a node from the nodes list, and also remove itself // from all the use lists on the operands that this node uses. diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Simplification.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Simplification.cs index 097c8aa88..282c136e1 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Simplification.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Simplification.cs @@ -25,6 +25,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations { TryEliminateBinaryOpCommutative(operation, 0); } + break; case Instruction.BitwiseOr: diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Utils.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Utils.cs index 6ec90fa3c..449886e11 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Utils.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Utils.cs @@ -45,7 +45,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations return x == y || x.Type == OperandType.Constant || x.Type == OperandType.ConstantBuffer; } - private static bool AreAllSourcesEqual(INode node, INode otherNode) + private static bool AreAllSourcesEqual(Operation node, Operation otherNode) { if (node.SourcesCount != otherNode.SourcesCount) { @@ -96,7 +96,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations private static bool IsConditionalBranch(Instruction inst) { - return inst == Instruction.BranchIfFalse || inst == Instruction.BranchIfTrue; + return inst is Instruction.BranchIfFalse or Instruction.BranchIfTrue; } private static bool IsSameCondition(Operand currentCondition, Operand queryCondition) diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/XmadOptimizer.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/XmadOptimizer.cs new file mode 100644 index 000000000..91073164d --- /dev/null +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/XmadOptimizer.cs @@ -0,0 +1,342 @@ +using Ryujinx.Graphics.Shader.IntermediateRepresentation; +using System.Collections.Generic; + +namespace Ryujinx.Graphics.Shader.Translation.Optimizations +{ + static class XmadOptimizer + { + public static void RunPass(BasicBlock block) + { + for (LinkedListNode node = block.Operations.First; node != null; node = node.Next) + { + if (node.Value is not Operation operation) + { + continue; + } + + if (TryMatchXmadPattern(operation, out Operand x, out Operand y, out Operand addend)) + { + LinkedListNode nextNode; + + if (addend != null) + { + Operand temp = OperandHelper.Local(); + + nextNode = block.Operations.AddAfter(node, new Operation(Instruction.Multiply, temp, x, y)); + nextNode = block.Operations.AddAfter(nextNode, new Operation(Instruction.Add, operation.Dest, temp, addend)); + } + else + { + nextNode = block.Operations.AddAfter(node, new Operation(Instruction.Multiply, operation.Dest, x, y)); + } + + Optimizer.RemoveNode(block, node); + node = nextNode; + } + } + } + + private static bool TryMatchXmadPattern(Operation operation, out Operand x, out Operand y, out Operand addend) + { + return TryMatchXmad32x32Pattern(operation, out x, out y, out addend) || + TryMatchXmad32x16Pattern(operation, out x, out y, out addend); + } + + private static bool TryMatchXmad32x32Pattern(Operation operation, out Operand x, out Operand y, out Operand addend) + { + x = null; + y = null; + addend = null; + + if (operation.Inst != Instruction.Add) + { + return false; + } + + Operand src1 = operation.GetSource(0); + Operand src2 = operation.GetSource(1); + + if (src2.AsgOp is not Operation addOp || addOp.Inst != Instruction.Add) + { + return false; + } + + Operand lowTimesLowResult = GetCopySource(addOp.GetSource(0)); + + if (lowTimesLowResult.AsgOp is not Operation lowTimesLowOp) + { + return false; + } + + if (!TryMatchLowTimesLow(lowTimesLowOp, out x, out y, out addend)) + { + return false; + } + + Operand lowTimesHighResult = GetCopySource(GetShifted16Source(addOp.GetSource(1), Instruction.ShiftLeft)); + + if (lowTimesHighResult.AsgOp is not Operation lowTimesHighOp) + { + return false; + } + + if (!TryMatchLowTimesHigh(lowTimesHighOp, x, y)) + { + return false; + } + + if (src1.AsgOp is not Operation highTimesHighOp) + { + return false; + } + + if (!TryMatchHighTimesHigh(highTimesHighOp, x, lowTimesHighResult)) + { + return false; + } + + return true; + } + + private static bool TryMatchXmad32x16Pattern(Operation operation, out Operand x, out Operand y, out Operand addend) + { + x = null; + y = null; + addend = null; + + if (operation.Inst != Instruction.Add) + { + return false; + } + + Operand src1 = operation.GetSource(0); + Operand src2 = operation.GetSource(1); + + Operand lowTimesLowResult = GetCopySource(src2); + + if (lowTimesLowResult.AsgOp is not Operation lowTimesLowOp) + { + return false; + } + + if (!TryMatchLowTimesLow(lowTimesLowOp, out x, out y, out addend)) + { + return false; + } + + Operand highTimesLowResult = src1; + + if (highTimesLowResult.AsgOp is not Operation highTimesLowOp) + { + return false; + } + + if (!TryMatchHighTimesLow(highTimesLowOp, x, y)) + { + return false; + } + + return y.Type == OperandType.Constant && (ushort)y.Value == y.Value; + } + + private static bool TryMatchLowTimesLow(Operation operation, out Operand x, out Operand y, out Operand addend) + { + // x = x & 0xFFFF + // y = y & 0xFFFF + // lowTimesLow = x * y + + x = null; + y = null; + addend = null; + + if (operation.Inst == Instruction.Add) + { + if (operation.GetSource(0).AsgOp is not Operation mulOp) + { + return false; + } + + addend = operation.GetSource(1); + operation = mulOp; + } + + if (operation.Inst != Instruction.Multiply) + { + return false; + } + + Operand src1 = GetMasked16Source(operation.GetSource(0)); + Operand src2 = GetMasked16Source(operation.GetSource(1)); + + if (src1 == null || src2 == null) + { + return false; + } + + x = src1; + y = src2; + + return true; + } + + private static bool TryMatchLowTimesHigh(Operation operation, Operand x, Operand y) + { + // xLow = x & 0xFFFF + // yHigh = y >> 16 + // lowTimesHigh = xLow * yHigh + // result = (lowTimesHigh & 0xFFFF) | (y << 16) + + if (operation.Inst != Instruction.BitwiseOr) + { + return false; + } + + Operand mulResult = GetMasked16Source(operation.GetSource(0)); + + if (mulResult == null) + { + return false; + } + + mulResult = GetCopySource(mulResult); + + if (mulResult.AsgOp is not Operation mulOp || mulOp.Inst != Instruction.Multiply) + { + return false; + } + + if (GetMasked16Source(mulOp.GetSource(0)) != x) + { + return false; + } + + if (GetShifted16Source(mulOp.GetSource(1), Instruction.ShiftRightU32) != y) + { + return false; + } + + if (GetShifted16Source(operation.GetSource(1), Instruction.ShiftLeft) != y) + { + return false; + } + + return true; + } + + private static bool TryMatchHighTimesLow(Operation operation, Operand x, Operand y) + { + // xHigh = x >> 16 + // yLow = y & 0xFFFF + // highTimesLow = xHigh * yLow + // result = highTimesLow << 16 + + if (operation.Inst != Instruction.ShiftLeft || !IsConst(operation.GetSource(1), 16)) + { + return false; + } + + Operand mulResult = operation.GetSource(0); + + if (mulResult.AsgOp is not Operation mulOp || mulOp.Inst != Instruction.Multiply) + { + return false; + } + + if (GetShifted16Source(mulOp.GetSource(0), Instruction.ShiftRightU32) != x) + { + return false; + } + + Operand src2 = GetMasked16Source(mulOp.GetSource(1)); + + if (src2.Type != y.Type || src2.Value != y.Value) + { + return false; + } + + return true; + } + + private static bool TryMatchHighTimesHigh(Operation operation, Operand x, Operand lowTimesHighResult) + { + // xHigh = x >> 16 + // lowTimesHighResultHigh = lowTimesHighResult >> 16 + // highTimesHigh = xHigh * lowTimesHighResultHigh + // result = highTimesHigh << 16 + + if (operation.Inst != Instruction.ShiftLeft || !IsConst(operation.GetSource(1), 16)) + { + return false; + } + + Operand mulResult = operation.GetSource(0); + + if (mulResult.AsgOp is not Operation mulOp || mulOp.Inst != Instruction.Multiply) + { + return false; + } + + if (GetShifted16Source(mulOp.GetSource(0), Instruction.ShiftRightU32) != x) + { + return false; + } + + if (GetCopySource(GetShifted16Source(mulOp.GetSource(1), Instruction.ShiftRightU32)) != lowTimesHighResult) + { + return false; + } + + return true; + } + + private static Operand GetMasked16Source(Operand value) + { + if (value.AsgOp is not Operation maskOp) + { + return null; + } + + if (maskOp.Inst != Instruction.BitwiseAnd || !IsConst(maskOp.GetSource(1), ushort.MaxValue)) + { + return null; + } + + return maskOp.GetSource(0); + } + + private static Operand GetShifted16Source(Operand value, Instruction shiftInst) + { + if (value.AsgOp is not Operation shiftOp) + { + return null; + } + + if (shiftOp.Inst != shiftInst || !IsConst(shiftOp.GetSource(1), 16)) + { + return null; + } + + return shiftOp.GetSource(0); + } + + private static Operand GetCopySource(Operand value) + { + while (value.AsgOp is Operation operation && IsCopy(operation)) + { + value = operation.GetSource(0); + } + + return value; + } + + private static bool IsCopy(Operation operation) + { + return operation.Inst == Instruction.Copy || (operation.Inst == Instruction.Add && IsConst(operation.GetSource(1), 0)); + } + + private static bool IsConst(Operand operand, int value) + { + return operand.Type == OperandType.Constant && operand.Value == value; + } + } +} diff --git a/src/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs b/src/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs index 39f01b1ce..0fcdff691 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs @@ -33,10 +33,12 @@ namespace Ryujinx.Graphics.Shader.Translation { return X; } + if (Y != PixelImap.Unused) { return Y; } + if (Z != PixelImap.Unused) { return Z; diff --git a/src/Ryujinx.Graphics.Shader/Translation/Transforms/GeometryToCompute.cs b/src/Ryujinx.Graphics.Shader/Translation/Transforms/GeometryToCompute.cs index 0013cf0eb..573acc942 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Transforms/GeometryToCompute.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Transforms/GeometryToCompute.cs @@ -91,6 +91,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms context.GpuAccessor.Log($"Invalid output \"{(IoVariable)operation.GetSource(0).Value}\"."); } } + break; case Instruction.Store: if (operation.StorageKind == StorageKind.Output) @@ -110,6 +111,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms context.GpuAccessor.Log($"Invalid output \"{(IoVariable)operation.GetSource(0).Value}\"."); } } + break; } diff --git a/src/Ryujinx.Graphics.Shader/Translation/Transforms/VertexToCompute.cs b/src/Ryujinx.Graphics.Shader/Translation/Transforms/VertexToCompute.cs index ebff0d59c..2f85a33d1 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Transforms/VertexToCompute.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Transforms/VertexToCompute.cs @@ -97,6 +97,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms newNode = CopyMasked(context.ResourceManager, newNode, location, component, dest, temp); } } + break; case IoVariable.GlobalId: case IoVariable.SubgroupEqMask: diff --git a/src/Ryujinx.Graphics.Shader/Translation/Translator.cs b/src/Ryujinx.Graphics.Shader/Translation/Translator.cs index 7f276044a..2a1110632 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Translator.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Translator.cs @@ -181,13 +181,29 @@ namespace Ryujinx.Graphics.Shader.Translation private static void EmitOutputsInitialization(EmitterContext context, AttributeUsage attributeUsage, IGpuAccessor gpuAccessor, ShaderStage stage) { - // Compute has no output attributes, and fragment is the last stage, so we - // don't need to initialize outputs on those stages. - if (stage == ShaderStage.Compute || stage == ShaderStage.Fragment) + // Compute has no output attributes, so we + // don't need to initialize outputs on that stage. + if (stage == ShaderStage.Compute) { return; } + if (stage == ShaderStage.Fragment) + { + // Fragment is the last stage, so we don't need to + // initialize outputs unless we're using DSB, in which + // we need to make sure the ouput has a valid value. + if (gpuAccessor.QueryGraphicsState().DualSourceBlendEnable) + { + for (int i = 0; i < 4; i++) + { + context.Store(StorageKind.Output, IoVariable.FragmentOutputColor, null, Const(1), Const(i), ConstF(0)); + } + } + + return; + } + if (stage == ShaderStage.Vertex) { InitializeVertexOutputs(context); diff --git a/src/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs b/src/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs index a579433f9..dd1325f8a 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs @@ -385,7 +385,7 @@ namespace Ryujinx.Graphics.Shader.Translation { StructureType tfeDataStruct = new(new StructureField[] { - new StructureField(AggregateType.Array | AggregateType.U32, "data", 0) + new(AggregateType.Array | AggregateType.U32, "data", 0) }); for (int i = 0; i < ResourceReservations.TfeBuffersCount; i++) @@ -404,7 +404,7 @@ namespace Ryujinx.Graphics.Shader.Translation StructureType vertexOutputStruct = new(new StructureField[] { - new StructureField(AggregateType.Array | AggregateType.FP32, "data", 0) + new(AggregateType.Array | AggregateType.FP32, "data", 0) }); int vertexOutputSbBinding = resourceManager.Reservations.VertexOutputStorageBufferBinding; @@ -441,7 +441,7 @@ namespace Ryujinx.Graphics.Shader.Translation StructureType geometryIbOutputStruct = new(new StructureField[] { - new StructureField(AggregateType.Array | AggregateType.U32, "data", 0) + new(AggregateType.Array | AggregateType.U32, "data", 0) }); int geometryIbOutputSbBinding = resourceManager.Reservations.GeometryIndexOutputStorageBufferBinding; @@ -501,7 +501,7 @@ namespace Ryujinx.Graphics.Shader.Translation StructureType vertexInputStruct = new(new StructureField[] { - new StructureField(AggregateType.Array | AggregateType.FP32, "data", 0) + new(AggregateType.Array | AggregateType.FP32, "data", 0) }); int vertexDataSbBinding = reservations.VertexOutputStorageBufferBinding; diff --git a/src/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs b/src/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs index d6974596d..1053f6f18 100644 --- a/src/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs +++ b/src/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs @@ -480,6 +480,7 @@ namespace Ryujinx.Graphics.Texture.Astc { Debug.Assert(colorEndpointMode[i] < 16); } + Debug.Assert(bitStream.BitsLeft == texelParams.GetPackedBitSize()); // Decode both color data and texel weight data @@ -1032,7 +1033,6 @@ namespace Ryujinx.Graphics.Texture.Astc break; } - case 1: { Span val = ReadUintColorValues(2, colorValues, ref colorValuesPosition); @@ -1295,7 +1295,6 @@ namespace Ryujinx.Graphics.Texture.Astc break; } - case 4: { c = 22; @@ -1389,6 +1388,7 @@ namespace Ryujinx.Graphics.Texture.Astc default: throw new AstcDecoderException("Unsupported quint encoding for color values."); } + break; } } @@ -1574,7 +1574,7 @@ namespace Ryujinx.Graphics.Texture.Astc r |= (modeBits & 0xC) >> 1; } - Debug.Assert(2 <= r && r <= 7); + Debug.Assert(r is >= 2 and <= 7); // Determine width & height switch (layout) diff --git a/src/Ryujinx.Graphics.Texture/Astc/Bits.cs b/src/Ryujinx.Graphics.Texture/Astc/Bits.cs index bedc14f78..2cc29acc3 100644 --- a/src/Ryujinx.Graphics.Texture/Astc/Bits.cs +++ b/src/Ryujinx.Graphics.Texture/Astc/Bits.cs @@ -52,6 +52,7 @@ namespace Ryujinx.Graphics.Texture.Astc comp = numberBits - newShift; numberBits = newShift; } + retValue <<= numberBits; retValue |= tempValue >> comp; resLength += numberBits; diff --git a/src/Ryujinx.Graphics.Texture/Astc/IntegerEncoded.cs b/src/Ryujinx.Graphics.Texture/Astc/IntegerEncoded.cs index 4d3e8c5b5..61ab2f571 100644 --- a/src/Ryujinx.Graphics.Texture/Astc/IntegerEncoded.cs +++ b/src/Ryujinx.Graphics.Texture/Astc/IntegerEncoded.cs @@ -52,6 +52,7 @@ namespace Ryujinx.Graphics.Texture.Astc { totalBits += (numberVals * 7 + 2) / 3; } + return totalBits; } diff --git a/src/Ryujinx.Graphics.Texture/Encoders/BC7Encoder.cs b/src/Ryujinx.Graphics.Texture/Encoders/BC7Encoder.cs index e5462b046..4154ef83d 100644 --- a/src/Ryujinx.Graphics.Texture/Encoders/BC7Encoder.cs +++ b/src/Ryujinx.Graphics.Texture/Encoders/BC7Encoder.cs @@ -153,7 +153,7 @@ namespace Ryujinx.Graphics.Texture.Encoders int selectedPartition = 0; - if (selectedMode == 1 || selectedMode == 7) + if (selectedMode is 1 or 7) { int partitionSelectionLowestError = int.MaxValue; @@ -180,7 +180,7 @@ namespace Ryujinx.Graphics.Texture.Encoders for (int m = 0; m < 8; m++) { - for (int r = 0; r < (m == 4 || m == 5 ? 4 : 1); r++) + for (int r = 0; r < (m is 4 or 5 ? 4 : 1); r++) { for (int im = 0; im < (m == 4 ? 2 : 1); im++) { diff --git a/src/Ryujinx.Graphics.Texture/LayoutConverter.cs b/src/Ryujinx.Graphics.Texture/LayoutConverter.cs index 5426af205..143c36259 100644 --- a/src/Ryujinx.Graphics.Texture/LayoutConverter.cs +++ b/src/Ryujinx.Graphics.Texture/LayoutConverter.cs @@ -79,6 +79,7 @@ namespace Ryujinx.Graphics.Texture outPtr += outStrideGap; } } + return true; } @@ -229,8 +230,10 @@ namespace Ryujinx.Graphics.Texture } } } + outOffs += stride * h * d * layers; } + return true; } @@ -245,6 +248,7 @@ namespace Ryujinx.Graphics.Texture _ => throw new NotSupportedException($"Unable to convert ${bytesPerPixel} bpp pixel format."), }; } + return outputOwner; } @@ -350,6 +354,7 @@ namespace Ryujinx.Graphics.Texture inPtr += inStrideGap; } } + return true; } @@ -493,8 +498,10 @@ namespace Ryujinx.Graphics.Texture } } } + inOffs += stride * h * d * layers; } + return true; } diff --git a/src/Ryujinx.Graphics.Texture/OffsetCalculator.cs b/src/Ryujinx.Graphics.Texture/OffsetCalculator.cs index e519341e6..10399ff16 100644 --- a/src/Ryujinx.Graphics.Texture/OffsetCalculator.cs +++ b/src/Ryujinx.Graphics.Texture/OffsetCalculator.cs @@ -115,7 +115,6 @@ namespace Ryujinx.Graphics.Texture _stride == other._stride && _bytesPerPixel == other._bytesPerPixel; - return !other._isLinear && _layoutConverter.LayoutMatches(other._layoutConverter); } } diff --git a/src/Ryujinx.Graphics.Texture/Utils/BC67Utils.cs b/src/Ryujinx.Graphics.Texture/Utils/BC67Utils.cs index f548684a4..ebf5e6a70 100644 --- a/src/Ryujinx.Graphics.Texture/Utils/BC67Utils.cs +++ b/src/Ryujinx.Graphics.Texture/Utils/BC67Utils.cs @@ -1172,7 +1172,7 @@ namespace Ryujinx.Graphics.Texture.Utils [MethodImpl(MethodImplOptions.AggressiveInlining)] public static RgbaColor32 Interpolate(RgbaColor32 color1, RgbaColor32 color2, int weightIndex, int indexBitCount) { - Debug.Assert(indexBitCount >= 2 && indexBitCount <= 4); + Debug.Assert(indexBitCount is >= 2 and <= 4); int weight = (((weightIndex << 7) / ((1 << indexBitCount) - 1)) + 1) >> 1; @@ -1191,8 +1191,8 @@ namespace Ryujinx.Graphics.Texture.Utils int colorIndexBitCount, int alphaIndexBitCount) { - Debug.Assert(colorIndexBitCount >= 2 && colorIndexBitCount <= 4); - Debug.Assert(alphaIndexBitCount >= 2 && alphaIndexBitCount <= 4); + Debug.Assert(colorIndexBitCount is >= 2 and <= 4); + Debug.Assert(alphaIndexBitCount is >= 2 and <= 4); int colorWeight = BC67Tables.Weights[colorIndexBitCount - 2][colorWeightIndex]; int alphaWeight = BC67Tables.Weights[alphaIndexBitCount - 2][alphaWeightIndex]; diff --git a/src/Ryujinx.Graphics.Vic/Image/SurfaceReader.cs b/src/Ryujinx.Graphics.Vic/Image/SurfaceReader.cs index 83f00f345..2c6ff0511 100644 --- a/src/Ryujinx.Graphics.Vic/Image/SurfaceReader.cs +++ b/src/Ryujinx.Graphics.Vic/Image/SurfaceReader.cs @@ -397,6 +397,7 @@ namespace Ryujinx.Graphics.Vic.Image { Scaler.DeinterlaceBob(buffer.Data, w, stride, isTopField); } + break; default: Logger.Error?.Print(LogClass.Vic, $"Unsupported deinterlace mode \"{config.DeinterlaceMode}\"."); diff --git a/src/Ryujinx.Graphics.Vic/Types/FrameFormat.cs b/src/Ryujinx.Graphics.Vic/Types/FrameFormat.cs index b8f821631..d76fcd9e0 100644 --- a/src/Ryujinx.Graphics.Vic/Types/FrameFormat.cs +++ b/src/Ryujinx.Graphics.Vic/Types/FrameFormat.cs @@ -54,8 +54,8 @@ namespace Ryujinx.Graphics.Vic.Types public static bool IsInterlacedBottomFirst(this FrameFormat frameFormat) { - return frameFormat == FrameFormat.InterlacedBottomFieldFirst || - frameFormat == FrameFormat.SubPicInterlacedBottomFieldFirst; + return frameFormat is FrameFormat.InterlacedBottomFieldFirst or + FrameFormat.SubPicInterlacedBottomFieldFirst; } public static bool IsTopField(this FrameFormat frameFormat, bool isLuma) diff --git a/src/Ryujinx.Graphics.Video/Vp9PictureInfo.cs b/src/Ryujinx.Graphics.Video/Vp9PictureInfo.cs index 09f6e6664..b9604181a 100644 --- a/src/Ryujinx.Graphics.Video/Vp9PictureInfo.cs +++ b/src/Ryujinx.Graphics.Video/Vp9PictureInfo.cs @@ -38,4 +38,4 @@ namespace Ryujinx.Graphics.Video public Vp9EntropyProbs Entropy; public Vp9BackwardUpdates BackwardUpdateCounts; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Vulkan/BufferHolder.cs b/src/Ryujinx.Graphics.Vulkan/BufferHolder.cs index 3b2fce34a..1e54e8ece 100644 --- a/src/Ryujinx.Graphics.Vulkan/BufferHolder.cs +++ b/src/Ryujinx.Graphics.Vulkan/BufferHolder.cs @@ -289,7 +289,7 @@ namespace Ryujinx.Graphics.Vulkan if (_pendingData != null) { _mirrors.Clear(); - }; + } } public void ClearMirrors(CommandBufferScoped cbs, int offset, int size) @@ -309,7 +309,7 @@ namespace Ryujinx.Graphics.Vulkan { _gd.PipelineInternal.Rebind(_buffer, offset, size); } - }; + } } public void UseMirrors() diff --git a/src/Ryujinx.Graphics.Vulkan/BufferMirrorRangeList.cs b/src/Ryujinx.Graphics.Vulkan/BufferMirrorRangeList.cs index b643e55f1..3cffb08c9 100644 --- a/src/Ryujinx.Graphics.Vulkan/BufferMirrorRangeList.cs +++ b/src/Ryujinx.Graphics.Vulkan/BufferMirrorRangeList.cs @@ -172,7 +172,7 @@ namespace Ryujinx.Graphics.Vulkan { return null; } - + List result = null; int index = BinarySearch(list, offset, size); diff --git a/src/Ryujinx.Graphics.Vulkan/DescriptorSetTemplate.cs b/src/Ryujinx.Graphics.Vulkan/DescriptorSetTemplate.cs index 02d3ae88f..3b70a841a 100644 --- a/src/Ryujinx.Graphics.Vulkan/DescriptorSetTemplate.cs +++ b/src/Ryujinx.Graphics.Vulkan/DescriptorSetTemplate.cs @@ -194,12 +194,12 @@ namespace Ryujinx.Graphics.Vulkan private static bool IsBufferType(ResourceType type) { - return type == ResourceType.UniformBuffer || type == ResourceType.StorageBuffer; + return type is ResourceType.UniformBuffer or ResourceType.StorageBuffer; } private static bool IsBufferTextureType(ResourceType type) { - return type == ResourceType.BufferTexture || type == ResourceType.BufferImage; + return type is ResourceType.BufferTexture or ResourceType.BufferImage; } public unsafe void Dispose() diff --git a/src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs b/src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs index 406f33304..a0a238e38 100644 --- a/src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs +++ b/src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs @@ -235,7 +235,7 @@ namespace Ryujinx.Graphics.Vulkan // Check stage bindings - _uniformMirrored.Union(_uniformSet).SignalSet((int binding, int count) => + _uniformMirrored.Union(_uniformSet).SignalSet((binding, count) => { for (int i = 0; i < count; i++) { @@ -257,7 +257,7 @@ namespace Ryujinx.Graphics.Vulkan } }); - _storageMirrored.Union(_storageSet).SignalSet((int binding, int count) => + _storageMirrored.Union(_storageSet).SignalSet((binding, count) => { for (int i = 0; i < count; i++) { @@ -348,16 +348,16 @@ namespace Ryujinx.Graphics.Vulkan if (segment.IsArray) { - if (segment.Type == ResourceType.Texture || - segment.Type == ResourceType.Sampler || - segment.Type == ResourceType.TextureAndSampler || - segment.Type == ResourceType.BufferTexture) + if (segment.Type is ResourceType.Texture or + ResourceType.Sampler or + ResourceType.TextureAndSampler or + ResourceType.BufferTexture) { ref ArrayRef arrayRef = ref _textureArrayExtraRefs[setIndex - PipelineBase.DescriptorSetLayouts]; PipelineStageFlags stageFlags = arrayRef.Stage.ConvertToPipelineStageFlags(); arrayRef.Array?.QueueWriteToReadBarriers(cbs, stageFlags); } - else if (segment.Type == ResourceType.Image || segment.Type == ResourceType.BufferImage) + else if (segment.Type is ResourceType.Image or ResourceType.BufferImage) { ref ArrayRef arrayRef = ref _imageArrayExtraRefs[setIndex - PipelineBase.DescriptorSetLayouts]; PipelineStageFlags stageFlags = arrayRef.Stage.ConvertToPipelineStageFlags(); @@ -1072,7 +1072,7 @@ namespace Ryujinx.Graphics.Vulkan private void Initialize(CommandBufferScoped cbs, int setIndex, DescriptorSetCollection dsc) { // We don't support clearing texture descriptors currently. - if (setIndex != PipelineBase.UniformSetIndex && setIndex != PipelineBase.StorageSetIndex) + if (setIndex is not PipelineBase.UniformSetIndex and not PipelineBase.StorageSetIndex) { return; } @@ -1102,10 +1102,10 @@ namespace Ryujinx.Graphics.Vulkan { DescriptorSet[] sets = null; - if (segment.Type == ResourceType.Texture || - segment.Type == ResourceType.Sampler || - segment.Type == ResourceType.TextureAndSampler || - segment.Type == ResourceType.BufferTexture) + if (segment.Type is ResourceType.Texture or + ResourceType.Sampler or + ResourceType.TextureAndSampler or + ResourceType.BufferTexture) { sets = _textureArrayExtraRefs[setIndex - PipelineBase.DescriptorSetLayouts].Array.GetDescriptorSets( _device, @@ -1116,7 +1116,7 @@ namespace Ryujinx.Graphics.Vulkan _dummyTexture, _dummySampler); } - else if (segment.Type == ResourceType.Image || segment.Type == ResourceType.BufferImage) + else if (segment.Type is ResourceType.Image or ResourceType.BufferImage) { sets = _imageArrayExtraRefs[setIndex - PipelineBase.DescriptorSetLayouts].Array.GetDescriptorSets( _device, diff --git a/src/Ryujinx.Graphics.Vulkan/FenceHelper.cs b/src/Ryujinx.Graphics.Vulkan/FenceHelper.cs index 6649af7f5..9d682bab2 100644 --- a/src/Ryujinx.Graphics.Vulkan/FenceHelper.cs +++ b/src/Ryujinx.Graphics.Vulkan/FenceHelper.cs @@ -24,6 +24,7 @@ namespace Ryujinx.Graphics.Vulkan { // Keep waiting while the fence is not signaled. } + result.ThrowOnError(); } } diff --git a/src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs b/src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs index 18e5472db..0657638c9 100644 --- a/src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs +++ b/src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs @@ -222,14 +222,14 @@ namespace Ryujinx.Graphics.Vulkan public static bool IsD24S8(Format format) { - return format == Format.D24UnormS8Uint || format == Format.S8UintD24Unorm || format == Format.X8UintD24Unorm; + return format is Format.D24UnormS8Uint or Format.S8UintD24Unorm or Format.X8UintD24Unorm; } private static bool IsRGB16IntFloat(Format format) { - return format == Format.R16G16B16Float || - format == Format.R16G16B16Sint || - format == Format.R16G16B16Uint; + return format is Format.R16G16B16Float or + Format.R16G16B16Sint or + Format.R16G16B16Uint; } } } diff --git a/src/Ryujinx.Graphics.Vulkan/HelperShader.cs b/src/Ryujinx.Graphics.Vulkan/HelperShader.cs index 8c7c074f4..695046198 100644 --- a/src/Ryujinx.Graphics.Vulkan/HelperShader.cs +++ b/src/Ryujinx.Graphics.Vulkan/HelperShader.cs @@ -33,29 +33,29 @@ namespace Ryujinx.Graphics.Vulkan private readonly PipelineHelperShader _pipeline; private readonly ISampler _samplerLinear; private readonly ISampler _samplerNearest; - private readonly IProgram _programColorBlit; - private readonly IProgram _programColorBlitMs; - private readonly IProgram _programColorBlitClearAlpha; - private readonly IProgram _programColorClearF; - private readonly IProgram _programColorClearSI; - private readonly IProgram _programColorClearUI; - private readonly IProgram _programDepthStencilClear; - private readonly IProgram _programStrideChange; - private readonly IProgram _programConvertD32S8ToD24S8; - private readonly IProgram _programConvertIndexBuffer; - private readonly IProgram _programConvertIndirectData; - private readonly IProgram _programColorCopyShortening; - private readonly IProgram _programColorCopyToNonMs; - private readonly IProgram _programColorCopyWidening; - private readonly IProgram _programColorDrawToMs; - private readonly IProgram _programDepthBlit; - private readonly IProgram _programDepthBlitMs; - private readonly IProgram _programDepthDrawToMs; - private readonly IProgram _programDepthDrawToNonMs; - private readonly IProgram _programStencilBlit; - private readonly IProgram _programStencilBlitMs; - private readonly IProgram _programStencilDrawToMs; - private readonly IProgram _programStencilDrawToNonMs; + private readonly ShaderCollection _programColorBlit; + private readonly ShaderCollection _programColorBlitMs; + private readonly ShaderCollection _programColorBlitClearAlpha; + private readonly ShaderCollection _programColorClearF; + private readonly ShaderCollection _programColorClearSI; + private readonly ShaderCollection _programColorClearUI; + private readonly ShaderCollection _programDepthStencilClear; + private readonly ShaderCollection _programStrideChange; + private readonly ShaderCollection _programConvertD32S8ToD24S8; + private readonly ShaderCollection _programConvertIndexBuffer; + private readonly ShaderCollection _programConvertIndirectData; + private readonly ShaderCollection _programColorCopyShortening; + private readonly ShaderCollection _programColorCopyToNonMs; + private readonly ShaderCollection _programColorCopyWidening; + private readonly ShaderCollection _programColorDrawToMs; + private readonly ShaderCollection _programDepthBlit; + private readonly ShaderCollection _programDepthBlitMs; + private readonly ShaderCollection _programDepthDrawToMs; + private readonly ShaderCollection _programDepthDrawToNonMs; + private readonly ShaderCollection _programStencilBlit; + private readonly ShaderCollection _programStencilBlitMs; + private readonly ShaderCollection _programStencilDrawToMs; + private readonly ShaderCollection _programStencilDrawToNonMs; public HelperShader(VulkanRenderer gd, Device device) { @@ -874,57 +874,42 @@ namespace Ryujinx.Graphics.Vulkan public unsafe void ConvertIndexBuffer(VulkanRenderer gd, CommandBufferScoped cbs, - BufferHolder src, - BufferHolder dst, + BufferHolder srcIndexBuffer, + BufferHolder dstIndexBuffer, IndexBufferPattern pattern, int indexSize, int srcOffset, int indexCount) { // TODO: Support conversion with primitive restart enabled. - // TODO: Convert with a compute shader? + int primitiveCount = pattern.GetPrimitiveCount(indexCount); int convertedCount = pattern.GetConvertedCount(indexCount); int outputIndexSize = 4; + + Buffer dstBuffer = dstIndexBuffer.GetBuffer().Get(cbs, 0, convertedCount * outputIndexSize).Value; - Buffer srcBuffer = src.GetBuffer().Get(cbs, srcOffset, indexCount * indexSize).Value; - Buffer dstBuffer = dst.GetBuffer().Get(cbs, 0, convertedCount * outputIndexSize).Value; + const int ParamsBufferSize = 16 * sizeof(int); - gd.Api.CmdFillBuffer(cbs.CommandBuffer, dstBuffer, 0, Vk.WholeSize, 0); + Span shaderParams = stackalloc int[ParamsBufferSize / sizeof(int)]; - List bufferCopy = []; - int outputOffset = 0; + shaderParams[8] = pattern.PrimitiveVertices; + shaderParams[9] = pattern.PrimitiveVerticesOut; + shaderParams[10] = indexSize; + shaderParams[11] = outputIndexSize; + shaderParams[12] = pattern.BaseIndex; + shaderParams[13] = pattern.IndexStride; + shaderParams[14] = srcOffset; + shaderParams[15] = primitiveCount; - // Try to merge copies of adjacent indices to reduce copy count. - int sequenceStart = 0; - int sequenceLength = 0; + pattern.OffsetIndex.CopyTo(shaderParams[..pattern.OffsetIndex.Length]); - foreach (int index in pattern.GetIndexMapping(indexCount)) - { - if (sequenceLength > 0) - { - if (index == sequenceStart + sequenceLength && indexSize == outputIndexSize) - { - sequenceLength++; - continue; - } + using var patternScoped = gd.BufferManager.ReserveOrCreate(gd, cbs, ParamsBufferSize); + var patternBuffer = patternScoped.Holder; - // Commit the copy so far. - bufferCopy.Add(new BufferCopy((ulong)(srcOffset + sequenceStart * indexSize), (ulong)outputOffset, (ulong)(indexSize * sequenceLength))); - outputOffset += outputIndexSize * sequenceLength; - } + patternBuffer.SetDataUnchecked(patternScoped.Offset, shaderParams); - sequenceStart = index; - sequenceLength = 1; - } - - if (sequenceLength > 0) - { - // Commit final pending copy. - bufferCopy.Add(new BufferCopy((ulong)(srcOffset + sequenceStart * indexSize), (ulong)outputOffset, (ulong)(indexSize * sequenceLength))); - } - - BufferCopy[] bufferCopyArray = bufferCopy.ToArray(); + _pipeline.SetCommandBuffer(cbs); BufferHolder.InsertBufferBarrier( gd, @@ -937,10 +922,11 @@ namespace Ryujinx.Graphics.Vulkan 0, convertedCount * outputIndexSize); - fixed (BufferCopy* pBufferCopy = bufferCopyArray) - { - gd.Api.CmdCopyBuffer(cbs.CommandBuffer, srcBuffer, dstBuffer, (uint)bufferCopyArray.Length, pBufferCopy); - } + _pipeline.SetUniformBuffers([new BufferAssignment(0, new BufferRange(patternScoped.Handle, patternScoped.Offset, ParamsBufferSize))]); + _pipeline.SetStorageBuffers(1, new[] { srcIndexBuffer.GetBuffer(), dstIndexBuffer.GetBuffer() }); + + _pipeline.SetProgram(_programConvertIndexBuffer); + _pipeline.DispatchCompute(BitUtils.DivRoundUp(primitiveCount, 16), 1, 1); BufferHolder.InsertBufferBarrier( gd, @@ -952,6 +938,8 @@ namespace Ryujinx.Graphics.Vulkan PipelineStageFlags.AllCommandsBit, 0, convertedCount * outputIndexSize); + + _pipeline.Finish(gd, cbs); } public void CopyIncompatibleFormats( diff --git a/src/Ryujinx.Graphics.Vulkan/IndexBufferPattern.cs b/src/Ryujinx.Graphics.Vulkan/IndexBufferPattern.cs index 7b01dd4ca..9054b2e71 100644 --- a/src/Ryujinx.Graphics.Vulkan/IndexBufferPattern.cs +++ b/src/Ryujinx.Graphics.Vulkan/IndexBufferPattern.cs @@ -47,28 +47,6 @@ namespace Ryujinx.Graphics.Vulkan return primitiveCount * OffsetIndex.Length; } - public IEnumerable GetIndexMapping(int indexCount) - { - int primitiveCount = GetPrimitiveCount(indexCount); - int index = BaseIndex; - - for (int i = 0; i < primitiveCount; i++) - { - if (RepeatStart) - { - // Used for triangle fan - yield return 0; - } - - for (int j = RepeatStart ? 1 : 0; j < OffsetIndex.Length; j++) - { - yield return index + OffsetIndex[j]; - } - - index += IndexStride; - } - } - public BufferHandle GetRepeatingBuffer(int vertexCount, out int indexCount) { int primitiveCount = GetPrimitiveCount(vertexCount); diff --git a/src/Ryujinx.Graphics.Vulkan/MoltenVK/MVKInitialization.cs b/src/Ryujinx.Graphics.Vulkan/MoltenVK/MVKInitialization.cs index c3efcc8da..c1c59939e 100644 --- a/src/Ryujinx.Graphics.Vulkan/MoltenVK/MVKInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/MoltenVK/MVKInitialization.cs @@ -40,6 +40,7 @@ namespace Ryujinx.Graphics.Vulkan.MoltenVK path = path[..^VulkanLib.Length] + "libMoltenVK.dylib"; return [path]; } + return []; } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 191811593..eac47e60e 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1527,20 +1527,24 @@ namespace Ryujinx.Graphics.Vulkan private bool ChangeFeedbackLoop(FeedbackLoopAspects aspects) { - if (_feedbackLoop != aspects) + // AMD RDNA 3 GPUs only + if (Gd.IsAmdRdna3) { - if (Gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop) + if (_feedbackLoop != aspects) { - DynamicState.SetFeedbackLoop(aspects); - } - else - { - _newState.FeedbackLoopAspects = aspects; - } + if (Gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop) + { + DynamicState.SetFeedbackLoop(aspects); + } + else + { + _newState.FeedbackLoopAspects = aspects; + } - _feedbackLoop = aspects; + _feedbackLoop = aspects; - return true; + return true; + } } return false; diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index ad26ff7b3..3ed87206f 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -1,6 +1,7 @@ using Ryujinx.Common.Memory; using Silk.NET.Vulkan; using Silk.NET.Vulkan.Extensions.EXT; +using System; namespace Ryujinx.Graphics.Vulkan { @@ -27,6 +28,7 @@ namespace Ryujinx.Graphics.Vulkan public uint ViewportsCount; public Array16 Viewports; + [Flags] private enum DirtyFlags { None = 0, diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index eec3b8395..fa815d96c 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -433,11 +433,11 @@ namespace Ryujinx.Graphics.Vulkan } else { - topologySupportsRestart = Topology == PrimitiveTopology.LineStrip || - Topology == PrimitiveTopology.TriangleStrip || - Topology == PrimitiveTopology.TriangleFan || - Topology == PrimitiveTopology.LineStripWithAdjacency || - Topology == PrimitiveTopology.TriangleStripWithAdjacency; + topologySupportsRestart = Topology is PrimitiveTopology.LineStrip or + PrimitiveTopology.TriangleStrip or + PrimitiveTopology.TriangleFan or + PrimitiveTopology.LineStripWithAdjacency or + PrimitiveTopology.TriangleStripWithAdjacency; } primitiveRestartEnable &= topologySupportsRestart; diff --git a/src/Ryujinx.Graphics.Vulkan/Queries/BufferedQuery.cs b/src/Ryujinx.Graphics.Vulkan/Queries/BufferedQuery.cs index 5377c8a1e..4763007f4 100644 --- a/src/Ryujinx.Graphics.Vulkan/Queries/BufferedQuery.cs +++ b/src/Ryujinx.Graphics.Vulkan/Queries/BufferedQuery.cs @@ -105,6 +105,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries bool isOcclusion = _type == CounterType.SamplesPassed; _pipeline.BeginQuery(this, _queryPool, needsReset, isOcclusion, isOcclusion && resetSequence != null); } + _resetSequence = null; } @@ -211,6 +212,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries { _api.DestroyQueryPool(_device, _queryPool, null); } + _queryPool = default; } } diff --git a/src/Ryujinx.Graphics.Vulkan/Queries/CounterQueue.cs b/src/Ryujinx.Graphics.Vulkan/Queries/CounterQueue.cs index 24b0e7787..84e75bec0 100644 --- a/src/Ryujinx.Graphics.Vulkan/Queries/CounterQueue.cs +++ b/src/Ryujinx.Graphics.Vulkan/Queries/CounterQueue.cs @@ -198,6 +198,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries { return; // If not blocking, then return when we encounter an event that is not ready yet. } + _events.Dequeue(); } } diff --git a/src/Ryujinx.Graphics.Vulkan/SamplerHolder.cs b/src/Ryujinx.Graphics.Vulkan/SamplerHolder.cs index eae003686..600f0fafc 100644 --- a/src/Ryujinx.Graphics.Vulkan/SamplerHolder.cs +++ b/src/Ryujinx.Graphics.Vulkan/SamplerHolder.cs @@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Vulkan float minLod = info.MinLod; float maxLod = info.MaxLod; - if (info.MinFilter == MinFilter.Nearest || info.MinFilter == MinFilter.Linear) + if (info.MinFilter is MinFilter.Nearest or MinFilter.Linear) { minLod = 0; maxLod = 0.25f; diff --git a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs index 78cd15a39..c7bb1ba59 100644 --- a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs +++ b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs @@ -182,7 +182,7 @@ namespace Ryujinx.Graphics.Vulkan return false; } } - + //Prevent the sum of descriptors from exceeding MaxPushDescriptors int totalDescriptors = 0; foreach (ResourceDescriptor desc in layout.Sets.First().Descriptors) @@ -190,6 +190,7 @@ namespace Ryujinx.Graphics.Vulkan if (!reserved.Contains(desc.Binding)) totalDescriptors += desc.Count; } + if (totalDescriptors > gd.Capabilities.MaxPushDescriptors) return false; @@ -391,7 +392,7 @@ namespace Ryujinx.Graphics.Vulkan return templates; } - private PipelineStageFlags GetPipelineStages(ResourceStages stages) + private static PipelineStageFlags GetPipelineStages(ResourceStages stages) { PipelineStageFlags result = 0; @@ -428,7 +429,7 @@ namespace Ryujinx.Graphics.Vulkan return result; } - private (PipelineStageFlags Buffer, PipelineStageFlags Texture) BuildIncoherentStages(ReadOnlyCollection setUsages) + private static (PipelineStageFlags Buffer, PipelineStageFlags Texture) BuildIncoherentStages(ReadOnlyCollection setUsages) { PipelineStageFlags buffer = PipelineStageFlags.None; PipelineStageFlags texture = PipelineStageFlags.None; diff --git a/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs b/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs index 190ada27b..3dc605891 100644 --- a/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs +++ b/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs @@ -98,7 +98,7 @@ namespace Ryujinx.Graphics.Vulkan ImageCreateFlags flags = ImageCreateFlags.CreateMutableFormatBit | ImageCreateFlags.CreateExtendedUsageBit; // This flag causes mipmapped texture arrays to break on AMD GCN, so for that copy dependencies are forced for aliasing as cube. - bool isCube = info.Target == Target.Cubemap || info.Target == Target.CubemapArray; + bool isCube = info.Target is Target.Cubemap or Target.CubemapArray; bool cubeCompatible = gd.IsAmdGcn ? isCube : (info.Width == info.Height && layers >= 6); if (type == ImageType.Type2D && cubeCompatible) @@ -336,7 +336,7 @@ namespace Ryujinx.Graphics.Vulkan public static SampleCountFlags ConvertToSampleCountFlags(SampleCountFlags supportedSampleCounts, uint samples) { - if (samples == 0 || samples > (uint)SampleCountFlags.Count64Bit) + if (samples is 0 or > ((uint)SampleCountFlags.Count64Bit)) { return SampleCountFlags.Count1Bit; } diff --git a/src/Ryujinx.Graphics.Vulkan/TextureView.cs b/src/Ryujinx.Graphics.Vulkan/TextureView.cs index 7583b7e5c..1cbb7c6e1 100644 --- a/src/Ryujinx.Graphics.Vulkan/TextureView.cs +++ b/src/Ryujinx.Graphics.Vulkan/TextureView.cs @@ -78,9 +78,9 @@ namespace Ryujinx.Graphics.Vulkan ComponentSwizzle swizzleB = info.SwizzleB.Convert(); ComponentSwizzle swizzleA = info.SwizzleA.Convert(); - if (info.Format == Format.R5G5B5A1Unorm || - info.Format == Format.R5G5B5X1Unorm || - info.Format == Format.R5G6B5Unorm) + if (info.Format is Format.R5G5B5A1Unorm or + Format.R5G5B5X1Unorm or + Format.R5G6B5Unorm) { (swizzleB, swizzleR) = (swizzleR, swizzleB); } diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index e90606dcf..32c22dd2a 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -92,6 +92,7 @@ namespace Ryujinx.Graphics.Vulkan internal bool IsAmdWindows { get; private set; } internal bool IsIntelWindows { get; private set; } internal bool IsAmdGcn { get; private set; } + internal bool IsAmdRdna3 { get; private set; } internal bool IsNvidiaPreTuring { get; private set; } internal bool IsIntelArc { get; private set; } internal bool IsQualcommProprietary { get; private set; } @@ -359,11 +360,11 @@ namespace Ryujinx.Graphics.Vulkan IsAmdWindows = Vendor == Vendor.Amd && OperatingSystem.IsWindows(); IsIntelWindows = Vendor == Vendor.Intel && OperatingSystem.IsWindows(); IsTBDR = - Vendor == Vendor.Apple || - Vendor == Vendor.Qualcomm || - Vendor == Vendor.ARM || - Vendor == Vendor.Broadcom || - Vendor == Vendor.ImgTec; + Vendor is Vendor.Apple or + Vendor.Qualcomm or + Vendor.ARM or + Vendor.Broadcom or + Vendor.ImgTec; GpuVendor = VendorUtils.GetNameFromId(properties.VendorID); GpuDriver = hasDriverProperties && !OperatingSystem.IsMacOS() ? @@ -378,6 +379,10 @@ namespace Ryujinx.Graphics.Vulkan IsAmdGcn = !IsMoltenVk && Vendor == Vendor.Amd && Patterns.AmdGcn.IsMatch(GpuRenderer); + IsAmdRdna3 = Vendor == Vendor.Amd && (Patterns.AmdRdna3.IsMatch(GpuRenderer) + // ROG Ally (X) Device IDs + || properties.DeviceID is 0x15BF or 0x15C8); + if (Vendor == Vendor.Nvidia) { Match match = Patterns.NvidiaConsumerClass.Match(GpuRenderer); @@ -898,7 +903,7 @@ namespace Ryujinx.Graphics.Vulkan gpuInfoMessage = gpuInfoMessage.Prepend(GpuVendor); Logger.Notice.Print(LogClass.Gpu, gpuInfoMessage); - + Logger.Notice.Print(LogClass.Gpu, $"GPU Memory: {GetTotalGPUMemory() / (1024 * 1024)} MiB"); } diff --git a/src/Ryujinx.Graphics.Vulkan/Window.cs b/src/Ryujinx.Graphics.Vulkan/Window.cs index ab39cbd7d..b67b0dbfa 100644 --- a/src/Ryujinx.Graphics.Vulkan/Window.cs +++ b/src/Ryujinx.Graphics.Vulkan/Window.cs @@ -544,6 +544,7 @@ namespace Ryujinx.Graphics.Vulkan _effect?.Dispose(); _effect = new SmaaPostProcessingEffect(_gd, _device, quality); } + break; } } @@ -575,6 +576,7 @@ namespace Ryujinx.Graphics.Vulkan _scalingFilter?.Dispose(); _scalingFilter = new AreaScalingFilter(_gd, _device); } + break; } } diff --git a/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs b/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs index 4de100cf8..cdd062826 100644 --- a/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs +++ b/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs @@ -59,7 +59,7 @@ namespace Ryujinx.HLE.Generators generator.LeaveScope(); generator.LeaveScope(); - generator.AppendLine("#nullable disable"); + generator.AppendLine("#nullable disable"); context.AddSource($"IUserInterface.g.cs", generator.ToString()); } diff --git a/src/Ryujinx.HLE/FileSystem/ContentManager.cs b/src/Ryujinx.HLE/FileSystem/ContentManager.cs index 1c2a7351d..6ce19efee 100644 --- a/src/Ryujinx.HLE/FileSystem/ContentManager.cs +++ b/src/Ryujinx.HLE/FileSystem/ContentManager.cs @@ -111,10 +111,12 @@ namespace Ryujinx.HLE.FileSystem { continue; } + if (!ContentPath.TryGetRealPath(contentPathString, out string contentDirectory)) { continue; } + string registeredDirectory = Path.Combine(contentDirectory, "registered"); Directory.CreateDirectory(registeredDirectory); @@ -464,6 +466,7 @@ namespace Ryujinx.HLE.FileSystem { InstallFromZip(archive, temporaryDirectory); } + break; case ".xci": Xci xci = new(_virtualFileSystem.KeySet, file.AsStorage()); @@ -476,7 +479,7 @@ namespace Ryujinx.HLE.FileSystem FinishInstallation(temporaryDirectory, registeredDirectory); } - public void InstallKeys(string keysSource, string installDirectory) + public static void InstallKeys(string keysSource, string installDirectory) { if (Directory.Exists(keysSource)) { @@ -505,6 +508,7 @@ namespace Ryujinx.HLE.FileSystem { InstallKeysFromZip(archive, installDirectory); } + break; case ".keys": VerifyKeysFile(keysSource); @@ -515,13 +519,14 @@ namespace Ryujinx.HLE.FileSystem } } - private void InstallKeysFromZip(ZipArchive archive, string installDirectory) + private static void InstallKeysFromZip(ZipArchive archive, string installDirectory) { string temporaryDirectory = Path.Combine(installDirectory, "temp"); if (Directory.Exists(temporaryDirectory)) { Directory.Delete(temporaryDirectory, true); } + Directory.CreateDirectory(temporaryDirectory); foreach (ZipArchiveEntry entry in archive.Entries) { @@ -541,6 +546,7 @@ namespace Ryujinx.HLE.FileSystem } } } + Directory.Delete(temporaryDirectory, true); } @@ -567,7 +573,7 @@ namespace Ryujinx.HLE.FileSystem { Nca nca = new(_virtualFileSystem.KeySet, OpenPossibleFragmentedFile(filesystem, entry.FullPath, OpenMode.Read).AsStorage()); - SaveNca(nca, entry.Name.Remove(entry.Name.IndexOf('.')), temporaryDirectory); + SaveNca(nca, entry.Name[..entry.Name.IndexOf('.')], temporaryDirectory); } } @@ -641,7 +647,7 @@ namespace Ryujinx.HLE.FileSystem return file.Release(); } - private static Stream GetZipStream(ZipArchiveEntry entry) + private static MemoryStream GetZipStream(ZipArchiveEntry entry) { MemoryStream dest = MemoryStreamManager.Shared.GetStream(); @@ -1016,7 +1022,7 @@ namespace Ryujinx.HLE.FileSystem return null; } - public void VerifyKeysFile(string filePath) + public static void VerifyKeysFile(string filePath) { // Verify the keys file format refers to https://github.com/Thealexbarney/LibHac/blob/master/KEYS.md string genericPattern = @"^[a-z0-9_]+ = [a-z0-9]+$"; @@ -1028,7 +1034,7 @@ namespace Ryujinx.HLE.FileSystem string fileName = Path.GetFileName(filePath); string[] lines = File.ReadAllLines(filePath); - bool verified = false; + bool verified; switch (fileName) { case "prod.keys": @@ -1046,18 +1052,20 @@ namespace Ryujinx.HLE.FileSystem default: throw new FormatException($"Keys file name \"{fileName}\" not supported. Only \"prod.keys\", \"title.keys\", \"console.keys\", \"dev.keys\" are supported."); } + if (!verified) { throw new FormatException($"Invalid \"{filePath}\" file format."); } - } else + } + else { throw new FileNotFoundException($"Keys file not found at \"{filePath}\"."); } return; - - bool VerifyKeys(string[] lines, string regex) + + static bool VerifyKeys(string[] lines, string regex) { foreach (string line in lines) { @@ -1066,11 +1074,12 @@ namespace Ryujinx.HLE.FileSystem return false; } } + return true; } } - - public bool AreKeysAlredyPresent(string pathToCheck) + + public static bool AreKeysAlredyPresent(string pathToCheck) { string[] fileNames = ["prod.keys", "title.keys", "console.keys", "dev.keys"]; foreach (string file in fileNames) @@ -1080,6 +1089,7 @@ namespace Ryujinx.HLE.FileSystem return true; } } + return false; } } diff --git a/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs b/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs index 64b02a282..e6d76cec9 100644 --- a/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs +++ b/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs @@ -9,16 +9,16 @@ namespace Ryujinx.HLE.FileSystem public class EncryptedFileSystemCreator : IEncryptedFileSystemCreator { public Result Create(ref SharedRef outEncryptedFileSystem, - ref SharedRef baseFileSystem, IEncryptedFileSystemCreator.KeyId idIndex, + ref readonly SharedRef baseFileSystem, IEncryptedFileSystemCreator.KeyId idIndex, in EncryptionSeed encryptionSeed) { - if (idIndex < IEncryptedFileSystemCreator.KeyId.Save || idIndex > IEncryptedFileSystemCreator.KeyId.CustomStorage) + if (idIndex is < IEncryptedFileSystemCreator.KeyId.Save or > IEncryptedFileSystemCreator.KeyId.CustomStorage) { return ResultFs.InvalidArgument.Log(); } // TODO: Reenable when AesXtsFileSystem is fixed. - outEncryptedFileSystem = SharedRef.CreateMove(ref baseFileSystem); + outEncryptedFileSystem = SharedRef.CreateMove(ref baseFileSystem.Ref); return Result.Success; } diff --git a/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs b/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs index 067b7d4a8..4e0fdf554 100644 --- a/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs +++ b/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs @@ -392,7 +392,7 @@ namespace Ryujinx.HLE.FileSystem private static Result CreateSaveDataDirectory(HorizonClient hos, in SaveDataInfo info) { - if (info.SpaceId != SaveDataSpaceId.User && info.SpaceId != SaveDataSpaceId.System) + if (info.SpaceId is not SaveDataSpaceId.User and not SaveDataSpaceId.System) { return Result.Success; } diff --git a/src/Ryujinx.HLE/HOS/Applets/Browser/BrowserApplet.cs b/src/Ryujinx.HLE/HOS/Applets/Browser/BrowserApplet.cs index 488eca291..c8bbfc4b4 100644 --- a/src/Ryujinx.HLE/HOS/Applets/Browser/BrowserApplet.cs +++ b/src/Ryujinx.HLE/HOS/Applets/Browser/BrowserApplet.cs @@ -1,3 +1,4 @@ +using Microsoft.IO; using Ryujinx.Common; using Ryujinx.Common.Logging; using Ryujinx.Common.Memory; @@ -63,7 +64,7 @@ namespace Ryujinx.HLE.HOS.Applets.Browser private static byte[] BuildResponseOld(WebCommonReturnValue result) { - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter writer = new(stream); writer.WriteStruct(result); @@ -71,7 +72,7 @@ namespace Ryujinx.HLE.HOS.Applets.Browser } private byte[] BuildResponseNew(List outputArguments) { - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter writer = new(stream); writer.WriteStruct(new WebArgHeader { diff --git a/src/Ryujinx.HLE/HOS/Applets/Cabinet/CabinetApplet.cs b/src/Ryujinx.HLE/HOS/Applets/Cabinet/CabinetApplet.cs index 04843deb0..d8f665504 100644 --- a/src/Ryujinx.HLE/HOS/Applets/Cabinet/CabinetApplet.cs +++ b/src/Ryujinx.HLE/HOS/Applets/Cabinet/CabinetApplet.cs @@ -1,8 +1,8 @@ using Ryujinx.Common.Logging; using Ryujinx.Common.Memory; using Ryujinx.HLE.HOS.Services.Am.AppletAE; -using Ryujinx.HLE.HOS.Services.Hid.HidServer; using Ryujinx.HLE.HOS.Services.Hid; +using Ryujinx.HLE.HOS.Services.Hid.HidServer; using Ryujinx.HLE.HOS.Services.Nfc.Nfp; using Ryujinx.HLE.HOS.Services.Nfc.Nfp.NfpManager; using System; @@ -75,7 +75,7 @@ namespace Ryujinx.HLE.HOS.Applets.Cabinet return ResultCode.Success; } - private void StartFormatter(ref StartParamForAmiiboSettings startParam) + private static void StartFormatter(ref StartParamForAmiiboSettings startParam) { // Initialize RegisterInfo startParam.RegisterInfo = new RegisterInfo(); @@ -109,6 +109,7 @@ namespace Ryujinx.HLE.HOS.Applets.Cabinet } } } + VirtualAmiibo.UpdateNickName(amiiboId, newName); } @@ -154,9 +155,9 @@ namespace Ryujinx.HLE.HOS.Applets.Cabinet public unsafe struct ReturnValueForAmiiboSettings { public byte AmiiboSettingsReturnFlag; - private byte Padding1; - private byte Padding2; - private byte Padding3; + private readonly byte Padding1; + private readonly byte Padding2; + private readonly byte Padding3; public DeviceHandle DeviceHandle; public TagInfo TagInfo; public RegisterInfo RegisterInfo; diff --git a/src/Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs b/src/Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs index 3a7b29ab5..6b11f2cdd 100644 --- a/src/Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs +++ b/src/Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs @@ -1,3 +1,4 @@ +using Microsoft.IO; using Ryujinx.Common.Logging; using Ryujinx.Common.Memory; using Ryujinx.HLE.HOS.Services.Am.AppletAE; @@ -119,7 +120,7 @@ namespace Ryujinx.HLE.HOS.Applets private static byte[] BuildResponse(ControllerSupportResultInfo result) { - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter writer = new(stream); writer.Write(MemoryMarshal.AsBytes(MemoryMarshal.CreateReadOnlySpan(ref result, Unsafe.SizeOf()))); @@ -129,7 +130,7 @@ namespace Ryujinx.HLE.HOS.Applets private static byte[] BuildResponse() { - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter writer = new(stream); writer.Write((ulong)ResultCode.Success); diff --git a/src/Ryujinx.HLE/HOS/Applets/Dummy/DummyApplet.cs b/src/Ryujinx.HLE/HOS/Applets/Dummy/DummyApplet.cs index a581e1864..6fedff4dc 100644 --- a/src/Ryujinx.HLE/HOS/Applets/Dummy/DummyApplet.cs +++ b/src/Ryujinx.HLE/HOS/Applets/Dummy/DummyApplet.cs @@ -1,3 +1,4 @@ +using Microsoft.IO; using Ryujinx.Common.Memory; using Ryujinx.HLE.HOS.Services.Am.AppletAE; using System; @@ -9,14 +10,14 @@ namespace Ryujinx.HLE.HOS.Applets.Dummy { private readonly Horizon _system; private AppletSession _normalSession; - + public event EventHandler AppletStateChanged; - + public DummyApplet(Horizon system) { _system = system; } - + public ResultCode Start(AppletSession normalSession, AppletSession interactiveSession) { _normalSession = normalSession; @@ -25,10 +26,10 @@ namespace Ryujinx.HLE.HOS.Applets.Dummy _system.ReturnFocus(); return ResultCode.Success; } - + private static byte[] BuildResponse() { - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter writer = new(stream); writer.Write((ulong)ResultCode.Success); return stream.ToArray(); diff --git a/src/Ryujinx.HLE/HOS/Applets/Error/ErrorApplet.cs b/src/Ryujinx.HLE/HOS/Applets/Error/ErrorApplet.cs index 47bfadc4c..4c54b4666 100644 --- a/src/Ryujinx.HLE/HOS/Applets/Error/ErrorApplet.cs +++ b/src/Ryujinx.HLE/HOS/Applets/Error/ErrorApplet.cs @@ -159,7 +159,7 @@ namespace Ryujinx.HLE.HOS.Applets.Error string[] buttons = GetButtonsText(module, description, "DlgBtn"); (uint Module, uint Description) errorCodeTuple = (module, uint.Parse(description.ToString("0000"))); - + bool showDetails = _horizon.Device.UIHandler.DisplayErrorAppletDialog($"Error Code: {module}-{description:0000}", "\n" + message, buttons, errorCodeTuple); if (showDetails) { diff --git a/src/Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelectApplet.cs b/src/Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelectApplet.cs index cf99b0e7a..69bff74a5 100644 --- a/src/Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelectApplet.cs +++ b/src/Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelectApplet.cs @@ -1,3 +1,4 @@ +using Microsoft.IO; using Ryujinx.Common.Memory; using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.HOS.Services.Am.AppletAE; @@ -26,7 +27,7 @@ namespace Ryujinx.HLE.HOS.Applets { _normalSession = normalSession; _interactiveSession = interactiveSession; - + UserProfile selected = _system.Device.UIHandler.ShowPlayerSelectDialog(); if (selected == null) { @@ -40,6 +41,7 @@ namespace Ryujinx.HLE.HOS.Applets { _normalSession.Push(BuildResponse(selected)); } + AppletStateChanged?.Invoke(this, null); _system.ReturnFocus(); @@ -47,9 +49,9 @@ namespace Ryujinx.HLE.HOS.Applets return ResultCode.Success; } - private byte[] BuildResponse(UserProfile selectedUser) + private static byte[] BuildResponse(UserProfile selectedUser) { - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter writer = new(stream); writer.Write((ulong)PlayerSelectResult.Success); @@ -58,22 +60,22 @@ namespace Ryujinx.HLE.HOS.Applets return stream.ToArray(); } - - private byte[] BuildGuestResponse() + + private static byte[] BuildGuestResponse() { - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter writer = new(stream); - + writer.Write(new byte()); return stream.ToArray(); } - - private byte[] BuildResponse() + + private static byte[] BuildResponse() { - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter writer = new(stream); - + writer.Write((ulong)PlayerSelectResult.Failure); return stream.ToArray(); diff --git a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardApplet.cs b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardApplet.cs index 7e88db51d..58871a069 100644 --- a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardApplet.cs +++ b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardApplet.cs @@ -147,19 +147,19 @@ namespace Ryujinx.HLE.HOS.Applets private bool IsKeyboardActive() { - return _backgroundState >= InlineKeyboardState.Appearing && _backgroundState < InlineKeyboardState.Disappearing; + return _backgroundState is >= InlineKeyboardState.Appearing and < InlineKeyboardState.Disappearing; } private bool InputModeControllerEnabled() { - return _inputMode == KeyboardInputMode.ControllerAndKeyboard || - _inputMode == KeyboardInputMode.ControllerOnly; + return _inputMode is KeyboardInputMode.ControllerAndKeyboard or + KeyboardInputMode.ControllerOnly; } private bool InputModeTypingEnabled() { - return _inputMode == KeyboardInputMode.ControllerAndKeyboard || - _inputMode == KeyboardInputMode.KeyboardOnly; + return _inputMode is KeyboardInputMode.ControllerAndKeyboard or + KeyboardInputMode.KeyboardOnly; } private void AdvanceInputMode() @@ -365,6 +365,7 @@ namespace Ryujinx.HLE.HOS.Applets } } } + _interactiveSession.Push(InlineResponses.ReleasedUserWordInfo(_backgroundState)); break; case InlineKeyboardRequest.SetCustomizeDic: @@ -378,6 +379,7 @@ namespace Ryujinx.HLE.HOS.Applets { _keyboardBackgroundDic = reader.ReadStruct(); } + break; case InlineKeyboardRequest.SetCustomizedDictionaries: // Read the custom dictionaries data. @@ -390,6 +392,7 @@ namespace Ryujinx.HLE.HOS.Applets { _keyboardBackgroundDictSet = reader.ReadStruct(); } + break; case InlineKeyboardRequest.Calc: // The Calc request is used to communicate configuration changes and commands to the keyboard. diff --git a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs index 11f527285..5e048e55d 100644 --- a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs +++ b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs @@ -198,6 +198,7 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard { return; } + SKCanvas canvas = _surface.Canvas; canvas.Clear(SKColors.Transparent); @@ -376,7 +377,7 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard bool cursorVisible = false; - if (state.CursorBegin != state.CursorEnd) + if (state.CursorBegin != state.CursorEnd && state.CursorEnd <= state.InputText.Length) { Debug.Assert(state.InputText.Length > 0); diff --git a/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs b/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs index 08d929bf0..759780c42 100644 --- a/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs +++ b/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs @@ -110,6 +110,7 @@ namespace Ryujinx.HLE.HOS MemoryManagerHostMapped memoryManagerHostMapped = new(addressSpace, mode == MemoryManagerMode.HostMappedUnsafe, invalidAccessHandler); processContext = new ArmProcessContext(pid, cpuEngine, _gpu, memoryManagerHostMapped, addressSpace.AddressSpaceSize, for64Bit); } + break; default: diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs index 9413ed9ff..5424342fb 100644 --- a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs +++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs @@ -210,7 +210,6 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return true; } - // ::= # non-dependent type name, dependent type name, or dependent typename-specifier // ::= Ts # dependent elaborated type specifier using 'struct' or 'class' // ::= Tu # dependent elaborated type specifier using 'union' @@ -252,7 +251,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // ::= Do # non-throwing exception-specification (e.g., noexcept, throw()) // ::= DO E # computed (instantiation-dependent) noexcept // ::= Dw + E # dynamic exception specification with instantiation-dependent types - private BaseNode ParseFunctionType() + private FunctionType ParseFunctionType() { Cv cvQualifiers = ParseCvQualifiers(); @@ -347,7 +346,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // ::= A _ // ::= A [] _ - private BaseNode ParseArrayType() + private ArrayType ParseArrayType() { if (!ConsumeIf("A")) { @@ -570,6 +569,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler default: return null; } + break; case 'F': result = ParseFunctionType(); @@ -582,7 +582,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return null; case 'T': // might just be a class enum type - if (Peek(1) == 's' || Peek(1) == 'u' || Peek(1) == 'e') + if (Peek(1) is 's' or 'u' or 'e') { result = ParseClassEnumType(); break; @@ -604,6 +604,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler result = new NameTypeWithTemplateArguments(result, templateArguments); } + break; case 'P': _position++; @@ -680,6 +681,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler result = new NameTypeWithTemplateArguments(substitution, templateArgument); break; } + return substitution; } else @@ -691,6 +693,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler result = ParseClassEnumType(); break; } + if (result != null) { _substitutionList.Add(result); @@ -723,6 +726,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new SpecialName("guard variable for ", name); } + return null; } @@ -848,10 +852,12 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { qualifiers |= Cv.Restricted; } + if (ConsumeIf("V")) { qualifiers |= Cv.Volatile; } + if (ConsumeIf("K")) { qualifiers |= Cv.Const; @@ -860,7 +866,6 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return qualifiers; } - // ::= R # & ref-qualifier // ::= O # && ref-qualifier private SimpleReferenceType ParseRefQualifiers() @@ -874,6 +879,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { result = Reference.LValue; } + return new SimpleReferenceType(result, null); } @@ -945,7 +951,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler } // ::= - private BaseNode ParseSourceName() + private NameType ParseSourceName() { int length = ParsePositiveNumber(); if (Count() < length || length <= 0) @@ -1131,6 +1137,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _position += 2; return new NameType("operator[]"); } + return null; case 'l': switch (Peek(1)) @@ -1244,6 +1251,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _position += 2; return new NameType("operator?"); } + return null; case 'r': switch (Peek(1)) @@ -1269,6 +1277,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _position += 2; return new NameType("operator<=>"); } + return null; case 'v': // TODO: ::= v # vendor extended operator @@ -1311,6 +1320,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // TODO: ABI Tags // throw new Exception("ABI Tags not implemented"); } + return result; } @@ -1320,7 +1330,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // ::= D0 # deleting destructor // ::= D1 # complete object destructor // ::= D2 # base object destructor - private BaseNode ParseCtorDtorName(NameParserContext context, BaseNode prev) + private CtorDtorNameType ParseCtorDtorName(NameParserContext context, BaseNode prev) { if (prev.Type == NodeType.SpecialSubstitution && prev is SpecialSubstitution substitution) { @@ -1332,7 +1342,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler bool isInherited = ConsumeIf("I"); char ctorDtorType = Peek(); - if (ctorDtorType != '1' && ctorDtorType != '2' && ctorDtorType != '3') + if (ctorDtorType is not '1' and not '2' and not '3') { return null; } @@ -1355,7 +1365,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler if (ConsumeIf("D")) { char c = Peek(); - if (c != '0' && c != '1' && c != '2') + if (c is not '0' and not '1' and not '2') { return null; } @@ -1377,7 +1387,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // ::= fp _ # L == 0, second and later parameters // ::= fL p _ # L > 0, first parameter // ::= fL p _ # L > 0, second and later parameters - private BaseNode ParseFunctionParameter() + private FunctionParameter ParseFunctionParameter() { if (ConsumeIf("fp")) { @@ -1422,7 +1432,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // ::= fR // ::= fl // ::= fr - private BaseNode ParseFoldExpression() + private FoldExpression ParseFoldExpression() { if (!ConsumeIf("f")) { @@ -1430,8 +1440,8 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler } char foldKind = Peek(); - bool hasInitializer = foldKind == 'L' || foldKind == 'R'; - bool isLeftFold = foldKind == 'l' || foldKind == 'L'; + bool hasInitializer = foldKind is 'L' or 'R'; + bool isLeftFold = foldKind is 'l' or 'L'; if (!isLeftFold && !(foldKind == 'r' || foldKind == 'R')) { @@ -1568,10 +1578,9 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new FoldExpression(isLeftFold, operatorName, new PackedTemplateParameterExpansion(expression), initializer); } - // ::= cv # type (expression), conversion with one argument // ::= cv _ * E # type (expr-list), conversion with other than one argument - private BaseNode ParseConversionExpression() + private ConversionExpression ParseConversionExpression() { if (!ConsumeIf("cv")) { @@ -1616,7 +1625,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new ConversionExpression(type, new NodeArray(expressions)); } - private BaseNode ParseBinaryExpression(string name) + private BinaryExpression ParseBinaryExpression(string name) { BaseNode leftPart = ParseExpression(); if (leftPart == null) @@ -1633,7 +1642,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new BinaryExpression(leftPart, name, rightPart); } - private BaseNode ParsePrefixExpression(string name) + private PrefixExpression ParsePrefixExpression(string name) { BaseNode expression = ParseExpression(); if (expression == null) @@ -1644,7 +1653,6 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new PrefixExpression(name, expression); } - // ::= // ::= di # .name = expr // ::= dx # [expr] = expr @@ -1720,7 +1728,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // ::= [gs] na * _ # new[] (expr-list) type (init) // // ::= pi * E # parenthesized initialization - private BaseNode ParseNewExpression() + private NewExpression ParseNewExpression() { bool isGlobal = ConsumeIf("gs"); bool isArray = Peek(1) == 'a'; @@ -1771,7 +1779,6 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new NewExpression(new NodeArray(expressions), typeNode, new NodeArray(initializers), isGlobal, isArray); } - // ::= // ::= // ::= @@ -1872,6 +1879,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new EnclosedExpression("alignof (", expression, ")"); } + return null; case 'c': switch (Peek(1)) @@ -1910,6 +1918,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler names.Add(expression); } + return new CallExpression(callee, names); case 'm': _position += 2; @@ -1920,6 +1929,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler case 'v': return ParseConversionExpression(); } + return null; case 'd': BaseNode leftNode; @@ -2001,6 +2011,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _position += 2; return ParseBinaryExpression("/="); } + return null; case 'e': switch (Peek(1)) @@ -2015,6 +2026,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _position += 2; return ParseBinaryExpression("=="); } + return null; case 'g': switch (Peek(1)) @@ -2026,6 +2038,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _position += 2; return ParseBinaryExpression(">"); } + return null; case 'i': switch (Peek(1)) @@ -2059,8 +2072,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler bracedExpressions.Add(expression); } + return new InitListExpression(null, bracedExpressions); } + return null; case 'l': switch (Peek(1)) @@ -2078,6 +2093,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _position += 2; return ParseBinaryExpression("<"); } + return null; case 'm': switch (Peek(1)) @@ -2109,6 +2125,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new PostfixExpression(expression, "--"); } + return null; case 'n': switch (Peek(1)) @@ -2136,6 +2153,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new EnclosedExpression("noexcept (", expression, ")"); } + return null; case 'o': switch (Peek(1)) @@ -2152,6 +2170,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _position += 2; return ParseBinaryExpression("|="); } + return null; case 'p': switch (Peek(1)) @@ -2196,6 +2215,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new MemberExpression(leftNode, "->", rightNode); } + return null; case 'q': if (Peek(1) == 'u') @@ -2221,6 +2241,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new ConditionalExpression(condition, leftNode, rightNode); } + return null; case 'r': switch (Peek(1)) @@ -2253,6 +2274,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _position += 2; return ParseBinaryExpression(">>="); } + return null; case 's': switch (Peek(1)) @@ -2324,6 +2346,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new EnclosedExpression("sizeof...(", sizeofParamNode, ")"); } + return null; case 'P': _position += 2; @@ -2338,8 +2361,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler arguments.Add(argument); } + return new EnclosedExpression("sizeof...(", new NodeArray(arguments), ")"); } + return null; case 't': switch (Peek(1)) @@ -2379,6 +2404,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler bracedExpressions.Add(expression); } + return new InitListExpression(typeNode, bracedExpressions); case 'r': _position += 2; @@ -2393,6 +2419,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new ThrowExpression(expression); } + return null; } @@ -2404,7 +2431,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return null; } - private BaseNode ParseIntegerLiteral(string literalName) + private IntegerLiteral ParseIntegerLiteral(string literalName) { string number = ParseNumber(true); if (number == null || number.Length == 0 || !ConsumeIf("E")) @@ -2499,6 +2526,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return encoding; } } + return null; case 'T': return null; @@ -2521,7 +2549,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // ::= Dt E # decltype of an id-expression or class member access (C++0x) // ::= DT E # decltype of an expression (C++0x) - private BaseNode ParseDecltype() + private EnclosedExpression ParseDecltype() { if (!ConsumeIf("D") || (!ConsumeIf("t") && !ConsumeIf("T"))) { @@ -2579,6 +2607,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _forwardTemplateReferenceList.Add(forwardTemplateReference); return forwardTemplateReference; } + if (index >= _templateParamList.Count) { return null; @@ -2588,7 +2617,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler } // ::= I + E - private BaseNode ParseTemplateArguments(bool hasContext = false) + private TemplateArguments ParseTemplateArguments(bool hasContext = false) { if (!ConsumeIf("I")) { @@ -2605,7 +2634,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { if (hasContext) { - List templateParamListTemp = new(_templateParamList); + List templateParamListTemp = [.. _templateParamList]; BaseNode templateArgument = ParseTemplateArgument(); _templateParamList = templateParamListTemp; if (templateArgument == null) @@ -2618,6 +2647,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { templateArgument = new PackedTemplateParameter(((NodeArray)templateArgument).Nodes); } + _templateParamList.Add(templateArgument); } else @@ -2631,10 +2661,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler args.Add(templateArgument); } } + return new TemplateArguments(args); } - // ::= # type or template // ::= X E # expression // ::= # simple expressions @@ -2670,6 +2700,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler templateArguments.Add(templateArgument); } + return new NodeArray(templateArguments, NodeType.PackedTemplateArgument); // default: @@ -2685,7 +2716,6 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler public bool CtorDtorConversion; } - // ::= [ ] # T:: or T:: // ::= # decltype(p):: // ::= @@ -2713,6 +2743,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _substitutionList.Add(declType); return declType; } + return ParseSubstitution(); } @@ -2735,12 +2766,13 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new NameTypeWithTemplateArguments(sourceName, templateArguments); } + return sourceName; } // ::= # e.g., ~T or ~decltype(f()) // ::= # e.g., ~A<2*N> - private BaseNode ParseDestructorName() + private DtorName ParseDestructorName() { BaseNode node; if (char.IsDigit(Peek())) @@ -2751,6 +2783,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { node = ParseUnresolvedType(); } + if (node == null) { return null; @@ -2794,6 +2827,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new NameTypeWithTemplateArguments(operatorName, templateArguments); } + return operatorName; } @@ -2955,6 +2989,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new StdQualifiedName(unresolvedName); } + return ParseUnresolvedName(context); } @@ -2998,6 +3033,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler continue; } + char c = Peek(); // TODO: template args @@ -3098,10 +3134,12 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { return null; } + result = CreateNameNode(result, unqualifiedName, context); _substitutionList.Add(result); } + if (result == null || _substitutionList.Count == 0) { return null; @@ -3127,6 +3165,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { Consume(); } + ConsumeIf("_"); } } @@ -3134,7 +3173,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // ::= Z E [] // ::= Z E s [] // ::= Z Ed [ ] _ - private BaseNode ParseLocalName(NameParserContext context) + private LocalName ParseLocalName(NameParserContext context) { if (!ConsumeIf("Z")) { @@ -3329,6 +3368,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { return encoding; } + return null; } else @@ -3338,6 +3378,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { return type; } + return null; } } diff --git a/src/Ryujinx.HLE/HOS/Horizon.cs b/src/Ryujinx.HLE/HOS/Horizon.cs index 7af8711c7..5063b4329 100644 --- a/src/Ryujinx.HLE/HOS/Horizon.cs +++ b/src/Ryujinx.HLE/HOS/Horizon.cs @@ -345,6 +345,7 @@ namespace Ryujinx.HLE.HOS VirtualAmiibo.ApplicationBytes = []; VirtualAmiibo.InputBin = string.Empty; } + if (NfpDevices[nfpDeviceId].State == NfpDeviceState.SearchingForTag) { NfpDevices[nfpDeviceId].State = NfpDeviceState.TagFound; @@ -359,6 +360,7 @@ namespace Ryujinx.HLE.HOS { VirtualAmiibo.ApplicationBytes = []; } + byte[] encryptedData = File.ReadAllBytes(path); VirtualAmiiboFile newFile = AmiiboBinReader.ReadBinFile(encryptedData); if (SearchingForAmiibo(out int nfpDeviceId)) @@ -495,6 +497,7 @@ namespace Ryujinx.HLE.HOS TickSource.Resume(); } } + IsPaused = pause; } } diff --git a/src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs b/src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs index 6c1586cb9..edc3d819e 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs @@ -981,7 +981,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc { return KernelResult.OutOfResource; } - else if (recvListType == 1 || recvListType == 2) + else if (recvListType is 1 or 2) { ulong recvListBaseAddr; ulong recvListEndAddr; diff --git a/src/Ryujinx.HLE/HOS/Kernel/Memory/KCodeMemory.cs b/src/Ryujinx.HLE/HOS/Kernel/Memory/KCodeMemory.cs index e6d96d803..967aa6c0f 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Memory/KCodeMemory.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Memory/KCodeMemory.cs @@ -86,7 +86,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory return KernelResult.InvalidState; } - Debug.Assert(permission == KMemoryPermission.Read || permission == KMemoryPermission.ReadAndExecute); + Debug.Assert(permission is KMemoryPermission.Read or KMemoryPermission.ReadAndExecute); Result result = Owner.MemoryManager.MapPages(address, _pageList, MemoryState.CodeReadOnly, permission); diff --git a/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs b/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs index db190e6a9..ee1b4a7be 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs @@ -253,6 +253,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory AliasRegionExtraSize = addrSpaceEnd / 8; aliasRegion.Size += AliasRegionExtraSize; } + break; default: diff --git a/src/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs b/src/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs index bb12bd384..c4a9835cc 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs @@ -138,6 +138,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process { sb.AppendLine($"\tX[{i:d2}]:\t{GetReg(i)}"); } + sb.AppendLine($"\tFP:\t{GetReg(29)}"); sb.AppendLine($"\tLR:\t{GetReg(30)}"); sb.AppendLine($"\tSP:\t{GetReg(31)}"); @@ -235,6 +236,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process { info.SubName = Demangler.Parse(info.SubName); } + info.SubOffset = info.Offset - symbol.Value; } else diff --git a/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs b/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs index 32dca1512..478b4e864 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs @@ -128,7 +128,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process Pid = KernelContext.NewKipId(); - if (Pid == 0 || Pid >= KernelConstants.InitialProcessId) + if (Pid is 0 or >= KernelConstants.InitialProcessId) { throw new InvalidOperationException($"Invalid KIP Id {Pid}."); } @@ -231,7 +231,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process Pid = KernelContext.NewProcessId(); - if (Pid == ulong.MaxValue || Pid < KernelConstants.InitialProcessId) + if (Pid is ulong.MaxValue or < KernelConstants.InitialProcessId) { throw new InvalidOperationException($"Invalid Process Id {Pid}."); } @@ -309,7 +309,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process return KernelResult.InvalidCombination; } - if (requiredKernelVersionMajor != KernelVersionMajor && requiredKernelVersionMajor < 3) + if (requiredKernelVersionMajor is not KernelVersionMajor and < 3) { return KernelResult.InvalidCombination; } @@ -461,7 +461,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process Result result = Result.Success; - if (_fullTlsPages.TryGetValue(tlsPageAddr, out KTlsPageInfo pageInfo)) { // TLS page was full, free slot and move to free pages tree. @@ -509,7 +508,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process return result; } - private void GenerateRandomEntropy() + private static void GenerateRandomEntropy() { // TODO. } @@ -882,10 +881,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Process { if (State >= ProcessState.Started) { - if (State == ProcessState.Started || - State == ProcessState.Crashed || - State == ProcessState.Attached || - State == ProcessState.DebugSuspended) + if (State is ProcessState.Started or + ProcessState.Crashed or + ProcessState.Attached or + ProcessState.DebugSuspended) { SetState(ProcessState.Exiting); @@ -925,9 +924,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process { if (State >= ProcessState.Started) { - if (State == ProcessState.Started || - State == ProcessState.Attached || - State == ProcessState.DebugSuspended) + if (State is ProcessState.Started or + ProcessState.Attached or + ProcessState.DebugSuspended) { SetState(ProcessState.Exiting); @@ -1090,7 +1089,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process { KernelContext.CriticalSection.Enter(); - if (State != ProcessState.Exiting && State != ProcessState.Exited) + if (State is not ProcessState.Exiting and not ProcessState.Exited) { if (pause) { diff --git a/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationFlags.cs b/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationFlags.cs index 1b62a29d4..6ca54355e 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationFlags.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationFlags.cs @@ -4,7 +4,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.HLE.HOS.Kernel.Process { [Flags] - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum ProcessCreationFlags { Is64Bit = 1 << 0, diff --git a/src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs b/src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs index 9bcaf9538..c67220617 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs @@ -150,7 +150,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return handleTable.GenerateHandle(process, out handle); } - public Result StartProcess(int handle, int priority, int cpuCore, ulong mainThreadStackSize) + public static Result StartProcess(int handle, int priority, int cpuCore, ulong mainThreadStackSize) { KProcess process = KernelStatic.GetCurrentProcess().HandleTable.GetObject(handle); @@ -1071,7 +1071,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return result; } - public Result QueryMemory(out MemoryInfo info, out ulong pageInfo, ulong address) + public static Result QueryMemory(out MemoryInfo info, out ulong pageInfo, ulong address) { KProcess process = KernelStatic.GetCurrentProcess(); @@ -1199,7 +1199,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.InvalidMemState; } - if (permission > KMemoryPermission.ReadAndWrite || permission == KMemoryPermission.Write) + if (permission is > KMemoryPermission.ReadAndWrite or KMemoryPermission.Write) { return KernelResult.InvalidPermission; } @@ -1261,7 +1261,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.InvalidMemState; } - if (permission > KMemoryPermission.ReadAndWrite || permission == KMemoryPermission.Write) + if (permission is > KMemoryPermission.ReadAndWrite or KMemoryPermission.Write) { return KernelResult.InvalidPermission; } @@ -1485,7 +1485,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.InvalidMemRange; } - if (permission != KMemoryPermission.Read && permission != KMemoryPermission.ReadAndExecute) + if (permission is not KMemoryPermission.Read and not KMemoryPermission.ReadAndExecute) { return KernelResult.InvalidPermission; } @@ -1540,10 +1540,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.InvalidSize; } - if (permission != KMemoryPermission.None && - permission != KMemoryPermission.Read && - permission != KMemoryPermission.ReadAndWrite && - permission != KMemoryPermission.ReadAndExecute) + if (permission is not KMemoryPermission.None and + not KMemoryPermission.Read and + not KMemoryPermission.ReadAndWrite and + not KMemoryPermission.ReadAndExecute) { return KernelResult.InvalidPermission; } @@ -2009,6 +2009,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { value = process.MemoryManager.GetMmUsedPages() * KPageTableBase.PageSize; } + break; case InfoType.ProgramId: @@ -2040,12 +2041,14 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { value = 0; } + break; case InfoType.AliasRegionExtraSize: value = process.MemoryManager.AliasRegionExtraSize; break; } + break; } @@ -2093,6 +2096,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall value = (uint)resLimHandle; } + break; } @@ -2134,7 +2138,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall case InfoType.ThreadTickCount: { - if (subId < -1 || subId > 3) + if (subId is < (-1) or > 3) { return KernelResult.InvalidCombination; } @@ -2174,6 +2178,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall value = (ulong)KTimeManager.ConvertHostTicksToTicks(totalTimeRunning); } + break; } diff --git a/src/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs b/src/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs index b3fe5f1b6..172f67cca 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs @@ -6,7 +6,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { private readonly KernelContext _context; private int _recursionCount; - + // type is not Lock due to Monitor class usage public object Lock { get; } = new(); diff --git a/src/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs b/src/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs index 19f1b8be0..7471702c3 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs @@ -46,10 +46,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading _currentThread = null; - if (_srcCoresHighestPrioThreads == null) - { - _srcCoresHighestPrioThreads = new int[CpuCoresCount]; - } + _srcCoresHighestPrioThreads ??= new int[CpuCoresCount]; } private static int PreemptionPriorities(int index) diff --git a/src/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs b/src/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs index f1745eb44..b5a14ad5b 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs @@ -537,7 +537,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading ThreadSchedState lowNibble = SchedFlags & ThreadSchedState.LowMask; - if (lowNibble != ThreadSchedState.Paused && lowNibble != ThreadSchedState.Running) + if (lowNibble is not ThreadSchedState.Paused and not ThreadSchedState.Running) { KernelContext.CriticalSection.Leave(); diff --git a/src/Ryujinx.HLE/HOS/ModLoader.cs b/src/Ryujinx.HLE/HOS/ModLoader.cs index 2e8798009..4df929f35 100644 --- a/src/Ryujinx.HLE/HOS/ModLoader.cs +++ b/src/Ryujinx.HLE/HOS/ModLoader.cs @@ -500,6 +500,7 @@ namespace Ryujinx.HLE.HOS { AddFiles(fs, mod.Name, mod.Path.FullName, fileSet, builder); } + count++; } @@ -516,6 +517,7 @@ namespace Ryujinx.HLE.HOS { AddFiles(fs, mod.Name, mod.Path.FullName, fileSet, builder); } + count++; } @@ -547,7 +549,7 @@ namespace Ryujinx.HLE.HOS return newStorage; } - private static void AddFiles(IFileSystem fs, string modName, string rootPath, ISet fileSet, RomFsBuilder builder) + private static void AddFiles(IFileSystem fs, string modName, string rootPath, HashSet fileSet, RomFsBuilder builder) { foreach (DirectoryEntryEx entry in fs.EnumerateEntries() .AsParallel() @@ -644,16 +646,11 @@ namespace Ryujinx.HLE.HOS modLoadResult.Replaces[1 << i] = true; - using (FileStream stream = nsoFile.OpenRead()) - { - nsos[i] = new NsoExecutable(stream.AsStorage(), nsoName); - Logger.Info?.Print(LogClass.ModLoader, $"NSO '{nsoName}' replaced"); - using (MD5 md5 = MD5.Create()) - { - stream.Seek(0, SeekOrigin.Begin); - tempHash += BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLowerInvariant(); - } - } + using FileStream stream = nsoFile.OpenRead(); + nsos[i] = new NsoExecutable(stream.AsStorage(), nsoName); + Logger.Info?.Print(LogClass.ModLoader, $"NSO '{nsoName}' replaced"); + stream.Seek(0, SeekOrigin.Begin); + tempHash += Convert.ToHexStringLower(MD5.HashData(stream)); } modLoadResult.Stubs[1 << i] |= File.Exists(Path.Combine(mod.Path.FullName, nsoName + StubExtension)); @@ -687,10 +684,7 @@ namespace Ryujinx.HLE.HOS if (!string.IsNullOrEmpty(tempHash)) { - using (MD5 md5 = MD5.Create()) - { - modLoadResult.Hash += BitConverter.ToString(md5.ComputeHash(tempHash.ToBytes())).Replace("-", string.Empty).ToLowerInvariant(); - } + modLoadResult.Hash += Convert.ToHexStringLower(MD5.HashData(tempHash.ToBytes())); } return modLoadResult; @@ -791,7 +785,7 @@ namespace Ryujinx.HLE.HOS { string buildId = p switch { - NsoExecutable nso => Convert.ToHexString(nso.BuildId.ItemsRo.ToArray()).TrimEnd('0'), + NsoExecutable nso => Convert.ToHexString(nso.BuildId).TrimEnd('0'), NroExecutable nro => Convert.ToHexString(nro.Header.BuildId).TrimEnd('0'), _ => string.Empty, }; diff --git a/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountManager.cs b/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountManager.cs index 7364b2d40..7643c109d 100644 --- a/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountManager.cs @@ -56,6 +56,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc Logger.Warning?.Print(LogClass.Application, $"The command line specified profile named '{initialProfileName}' was not found"); } } + OpenUser(commandLineUserProfileOverride.IsNull ? _accountSaveDataManager.LastOpened : commandLineUserProfileOverride); } } diff --git a/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/ManagerServer.cs b/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/ManagerServer.cs index 2f0454a89..8c86788b1 100644 --- a/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/ManagerServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/ManagerServer.cs @@ -5,6 +5,7 @@ using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Services.Account.Acc.AsyncContext; using System; using System.Collections.Generic; +using System.Security.Claims; using System.Security.Cryptography; using System.Security.Principal; using System.Text; @@ -38,7 +39,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService RsaSecurityKey secKey = new(parameters); - SigningCredentials credentials = new(secKey, "RS256"); + SigningCredentials credentials = new(secKey, SecurityAlgorithms.RsaSha256); credentials.Key.KeyId = parameters.ToString(); @@ -49,11 +50,11 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService RandomNumberGenerator.Fill(deviceId); byte[] deviceAccountId = new byte[0x10]; - RandomNumberGenerator.Fill(deviceId); + RandomNumberGenerator.Fill(deviceAccountId); SecurityTokenDescriptor descriptor = new() { - Subject = new GenericIdentity(Convert.ToHexString(rawUserId).ToLower()), + Subject = new ClaimsIdentity([new Claim(JwtRegisteredClaimNames.Sub, Convert.ToHexString(rawUserId).ToLower())]), SigningCredentials = credentials, Audience = "ed9e2f05d286f7b8", Issuer = "https://e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com", diff --git a/src/Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserId.cs b/src/Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserId.cs index c9c78af9a..a6b1a47b6 100644 --- a/src/Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserId.cs +++ b/src/Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserId.cs @@ -51,14 +51,8 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc return High.ToString("x16") + Low.ToString("x16"); } - public Uid ToLibHacUid() - { - return new Uid((ulong)High, (ulong)Low); - } - - public UInt128 ToUInt128() - { - return new UInt128((ulong)High, (ulong)Low); - } + public Uid ToLibHacUid() => new((ulong)High, (ulong)Low); + public LibHac.Fs.UserId ToLibHac() => new((ulong)High, (ulong)Low); + public UInt128 ToUInt128() => new((ulong)High, (ulong)Low); } } diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs index 23ba99b04..f1ae81f8d 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs @@ -21,6 +21,21 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys return ResultCode.Success; } + [CommandCmif(3)] // 20.0.0+ + // CreateLibraryAppletEx(u32, u32, u64) -> object + 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)] // CreateStorage(u64) -> object public ResultCode CreateStorage(ServiceCtx context) diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/Storage/StorageHelper.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/Storage/StorageHelper.cs index 6c23720ee..d96877362 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/Storage/StorageHelper.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/Storage/StorageHelper.cs @@ -1,3 +1,4 @@ +using Microsoft.IO; using Ryujinx.Common.Memory; using Ryujinx.HLE.HOS.Services.Account.Acc; using System.IO; @@ -11,7 +12,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.Storage public static byte[] MakeLaunchParams(UserProfile userProfile) { // Size needs to be at least 0x88 bytes otherwise application errors. - using MemoryStream ms = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream ms = MemoryStreamManager.Shared.GetStream(); BinaryWriter writer = new(ms); ms.SetLength(0x88); diff --git a/src/Ryujinx.HLE/HOS/Services/Caps/CaptureManager.cs b/src/Ryujinx.HLE/HOS/Services/Caps/CaptureManager.cs index 2dd86b436..3caea0f6c 100644 --- a/src/Ryujinx.HLE/HOS/Services/Caps/CaptureManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Caps/CaptureManager.cs @@ -103,7 +103,7 @@ namespace Ryujinx.HLE.HOS.Services.Caps }; // NOTE: The hex hash is a HMAC-SHA256 (first 32 bytes) using a hardcoded secret key over the titleId, we can simulate it by hashing the titleId instead. - string hash = Convert.ToHexString(SHA256.HashData(BitConverter.GetBytes(titleId))).Remove(0x20); + string hash = Convert.ToHexString(SHA256.HashData(BitConverter.GetBytes(titleId)))[..0x20]; string folderPath = Path.Combine(_sdCardPath, "Nintendo", "Album", currentDateTime.Year.ToString("00"), currentDateTime.Month.ToString("00"), currentDateTime.Day.ToString("00")); string filePath = GenerateFilePath(folderPath, applicationAlbumEntry, currentDateTime, hash); diff --git a/src/Ryujinx.HLE/HOS/Services/Caps/IAlbumApplicationService.cs b/src/Ryujinx.HLE/HOS/Services/Caps/IAlbumApplicationService.cs index 5fbba310f..754a44025 100644 --- a/src/Ryujinx.HLE/HOS/Services/Caps/IAlbumApplicationService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Caps/IAlbumApplicationService.cs @@ -50,7 +50,7 @@ namespace Ryujinx.HLE.HOS.Services.Caps MemoryHelper.FillWithZeros(context.Memory, applicationAlbumFileEntryPosition, (int)applicationAlbumFileEntrySize); - if (contentType > ContentType.Unknown || contentType == ContentType.ExtraMovie) + if (contentType is > ContentType.Unknown or ContentType.ExtraMovie) { resultCode = ResultCode.InvalidContentType; } diff --git a/src/Ryujinx.HLE/HOS/Services/Caps/IScreenShotApplicationService.cs b/src/Ryujinx.HLE/HOS/Services/Caps/IScreenShotApplicationService.cs index 0dad46c14..0723b57cc 100644 --- a/src/Ryujinx.HLE/HOS/Services/Caps/IScreenShotApplicationService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Caps/IScreenShotApplicationService.cs @@ -60,7 +60,6 @@ namespace Ryujinx.HLE.HOS.Services.Caps ulong screenshotDataPosition = context.Request.SendBuff[1].Position; ulong screenshotDataSize = context.Request.SendBuff[1].Size; - // TODO: Parse the application data: At 0x00 it's UserData (Size of 0x400), at 0x404 it's a uint UserDataSize (Always empty for now). _ = context.Memory.GetSpan(applicationDataPosition, (int)applicationDataSize).ToArray(); @@ -89,7 +88,6 @@ namespace Ryujinx.HLE.HOS.Services.Caps ulong screenshotDataPosition = context.Request.SendBuff[1].Position; ulong screenshotDataSize = context.Request.SendBuff[1].Size; - // TODO: Parse the UserIdList. _ = context.Memory.GetSpan(userIdListPosition, (int)userIdListSize).ToArray(); diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs index 0ed56ea4e..168dfc37a 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs @@ -134,7 +134,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy ref readonly Path name = ref FileSystemProxyHelper.GetSfPath(context); using SharedRef dir = new(); - Result result = _fileSystem.Get.OpenDirectory(ref dir.Ref, name, mode); + Result result = _fileSystem.Get.OpenDirectory(ref dir.Ref, in name, mode); if (result.IsSuccess()) { diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs index 04dc6c688..a485ebe63 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs @@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { _baseStorage = SharedRef.CreateMove(ref baseStorage); } - + private const string Xc2JpTitleId = "0100f3400332c000"; private const string Xc2GlobalTitleId = "0100e95004038000"; private static bool IsXc2 => TitleIDs.CurrentApplication.Value.OrDefault() is Xc2GlobalTitleId or Xc2JpTitleId; @@ -41,7 +41,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy using WritableRegion region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true); Result result = _baseStorage.Get.Read((long)offset, new OutBuffer(region.Memory.Span), (long)size); - + if (context.Device.DirtyHacks.IsEnabled(DirtyHack.Xc2MenuSoftlockFix) && IsXc2) { // Add a load-bearing sleep to avoid XC2 softlock diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs b/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs index d353ce64f..08ede2b5b 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs @@ -753,17 +753,9 @@ namespace Ryujinx.HLE.HOS.Services.Fs public ResultCode OpenCloudBackupWorkStorageFileSystem(ServiceCtx context) { CloudBackupWorkStorageId storageId = (CloudBackupWorkStorageId)context.RequestData.ReadInt32(); - using SharedRef fileSystem = new(); - Result result = _baseFileSystemProxy.Get.OpenCloudBackupWorkStorageFileSystem(ref fileSystem.Ref, storageId); - if (result.IsFailure()) - { - return (ResultCode)result.Value; - } - - MakeObject(context, new FileSystemProxy.IFileSystem(ref fileSystem.Ref)); - - return ResultCode.Success; + Logger.Stub?.PrintStub(LogClass.ServiceFs, new { storageId }); + throw new NotImplementedException(); // reimplementing behavior from LibHac 0.19.0 } [CommandCmif(130)] @@ -1028,7 +1020,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs { ref readonly FspPath path = ref FileSystemProxyHelper.GetFspPath(context); - Result result = _baseFileSystemProxy.Get.GetRightsIdByPath(out RightsId rightsId, in path); + Result result = _baseFileSystemProxy.Get.GetRightsIdAndKeyGenerationByPath(out RightsId rightsId, out _, in path, ContentAttributes.None); if (result.IsFailure()) { return (ResultCode)result.Value; @@ -1044,7 +1036,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs { ref readonly FspPath path = ref FileSystemProxyHelper.GetFspPath(context); - Result result = _baseFileSystemProxy.Get.GetRightsIdAndKeyGenerationByPath(out RightsId rightsId, out byte keyGeneration, in path); + Result result = _baseFileSystemProxy.Get.GetRightsIdAndKeyGenerationByPath(out RightsId rightsId, out byte keyGeneration, in path, ContentAttributes.None); if (result.IsFailure()) { return (ResultCode)result.Value; @@ -1241,7 +1233,9 @@ namespace Ryujinx.HLE.HOS.Services.Fs BisPartitionId partitionId = (BisPartitionId)context.RequestData.ReadInt32(); ref readonly FspPath path = ref FileSystemProxyHelper.GetFspPath(context); - return (ResultCode)_baseFileSystemProxy.Get.SetBisRootForHost(partitionId, in path).Value; + Logger.Stub?.PrintStub(LogClass.ServiceFs, new { partitionId, path }); + + throw new NotImplementedException(); // reimplementing behavior from LibHac 0.19.0 } [CommandCmif(1001)] diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/HidServer/HidUtils.cs b/src/Ryujinx.HLE/HOS/Services/Hid/HidServer/HidUtils.cs index 8e2e854fb..d314d0567 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/HidServer/HidUtils.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/HidServer/HidUtils.cs @@ -42,9 +42,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid.HidServer public static bool IsValidNpadIdType(NpadIdType npadIdType) { - return (npadIdType >= NpadIdType.Player1 && npadIdType <= NpadIdType.Player8) || - npadIdType == NpadIdType.Handheld || - npadIdType == NpadIdType.Unknown; + return npadIdType is >= NpadIdType.Player1 and <= NpadIdType.Player8 or + NpadIdType.Handheld or + NpadIdType.Unknown; } } } diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs b/src/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs index 21288429f..0d2fcaa2a 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs @@ -130,7 +130,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid return ResultCode.Success; } - + [CommandCmif(26)] // ActivateDebugMouse(nn::applet::AppletResourceUserId) public ResultCode ActivateDebugMouse(ServiceCtx context) @@ -702,7 +702,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid return ResultCode.Success; } - + [CommandCmif(92)] // SetGestureOutputRanges(pid, ushort Unknown0) public ResultCode SetGestureOutputRanges(ServiceCtx context) @@ -1161,59 +1161,54 @@ namespace Ryujinx.HLE.HOS.Services.Hid NpadStyleIndex deviceType = (NpadStyleIndex)deviceHandle.DeviceType; NpadIdType npadIdType = (NpadIdType)deviceHandle.PlayerId; - if (deviceType < NpadStyleIndex.System || deviceType >= NpadStyleIndex.FullKey) + if (!HidUtils.IsValidNpadIdType(npadIdType)) { - if (!HidUtils.IsValidNpadIdType(npadIdType)) - { - return ResultCode.InvalidNpadIdType; - } - - if (deviceHandle.Position > 1) - { - return ResultCode.InvalidDeviceIndex; - } - - VibrationDeviceType vibrationDeviceType = VibrationDeviceType.None; - - if (Enum.IsDefined(deviceType)) - { - vibrationDeviceType = VibrationDeviceType.LinearResonantActuator; - } - else if ((uint)deviceType == 8) - { - vibrationDeviceType = VibrationDeviceType.GcErm; - } - - VibrationDevicePosition vibrationDevicePosition = VibrationDevicePosition.None; - - if (vibrationDeviceType == VibrationDeviceType.LinearResonantActuator) - { - if (deviceHandle.Position == 0) - { - vibrationDevicePosition = VibrationDevicePosition.Left; - } - else if (deviceHandle.Position == 1) - { - vibrationDevicePosition = VibrationDevicePosition.Right; - } - else - { - throw new InvalidOperationException($"{nameof(deviceHandle.Position)} contains an invalid value: {deviceHandle.Position}"); - } - } - - VibrationDeviceValue deviceInfo = new() - { - DeviceType = vibrationDeviceType, - Position = vibrationDevicePosition, - }; - - context.ResponseData.WriteStruct(deviceInfo); - - return ResultCode.Success; + return ResultCode.InvalidNpadIdType; } - return ResultCode.InvalidNpadDeviceType; + if (deviceHandle.Position > 1) + { + return ResultCode.InvalidDeviceIndex; + } + + VibrationDeviceType vibrationDeviceType = VibrationDeviceType.None; + + if (Enum.IsDefined(deviceType)) + { + vibrationDeviceType = VibrationDeviceType.LinearResonantActuator; + } + else if ((uint)deviceType == 8) + { + vibrationDeviceType = VibrationDeviceType.GcErm; + } + + VibrationDevicePosition vibrationDevicePosition = VibrationDevicePosition.None; + + if (vibrationDeviceType == VibrationDeviceType.LinearResonantActuator) + { + if (deviceHandle.Position == 0) + { + vibrationDevicePosition = VibrationDevicePosition.Left; + } + else if (deviceHandle.Position == 1) + { + vibrationDevicePosition = VibrationDevicePosition.Right; + } + else + { + throw new InvalidOperationException($"{nameof(deviceHandle.Position)} contains an invalid value: {deviceHandle.Position}"); + } + } + + VibrationDeviceValue deviceInfo = new() + { + DeviceType = vibrationDeviceType, + Position = vibrationDevicePosition, + }; + + context.ResponseData.WriteStruct(deviceInfo); + + return ResultCode.Success; } [CommandCmif(201)] diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/IHidbusServer.cs b/src/Ryujinx.HLE/HOS/Services/Hid/IHidbusServer.cs index d6531cc18..5082bddc2 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/IHidbusServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/IHidbusServer.cs @@ -10,9 +10,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid [CommandCmif(1)] // GetBusHandle(nn::hid::NpadIdType, nn::hidbus::BusType, nn::applet::AppletResourceUserId) -> (bool HasHandle, nn::hidbus::BusHandle) -#pragma warning disable CA1822 // Mark member as static public ResultCode GetBusHandle(ServiceCtx context) -#pragma warning restore CA1822 { NpadIdType npadIdType = (NpadIdType)context.RequestData.ReadInt32(); context.RequestData.BaseStream.Position += 4; // Padding diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/Irs/IIrSensorServer.cs b/src/Ryujinx.HLE/HOS/Services/Hid/Irs/IIrSensorServer.cs index 28caf4459..8a30ce066 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/Irs/IIrSensorServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/Irs/IIrSensorServer.cs @@ -172,9 +172,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Irs { NpadIdType npadIdType = (NpadIdType)context.RequestData.ReadUInt32(); - if (npadIdType > NpadIdType.Player8 && - npadIdType != NpadIdType.Unknown && - npadIdType != NpadIdType.Handheld) + if (npadIdType is > NpadIdType.Player8 and + not NpadIdType.Unknown and + not NpadIdType.Handheld) { return ResultCode.NpadIdOutOfRange; } diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs index 59d8f4489..7f3e564fb 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs @@ -45,7 +45,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory /// [FieldOffset(0x9A00)] public Array10 Npads; - + /// /// Debug mouse. /// diff --git a/src/Ryujinx.HLE/HOS/Services/IpcService.cs b/src/Ryujinx.HLE/HOS/Services/IpcService.cs index de58bb178..4c354ebc6 100644 --- a/src/Ryujinx.HLE/HOS/Services/IpcService.cs +++ b/src/Ryujinx.HLE/HOS/Services/IpcService.cs @@ -26,17 +26,17 @@ namespace Ryujinx.HLE.HOS.Services public IpcService(ServerBase server = null, bool registerTipc = false) { Stopwatch sw = Stopwatch.StartNew(); - + CmifCommands = GetType() .GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public) .SelectMany(methodInfo => methodInfo.GetCustomAttributes() .Select(command => (command.Id, methodInfo))) .ToDictionary(command => command.Id, command => command.methodInfo); - + sw.Stop(); - + Logger.Debug?.Print( - LogClass.Emulation, + LogClass.Emulation, $"{CmifCommands.Count} Cmif commands loaded in {sw.ElapsedTicks} ticks ({Stopwatch.Frequency} tps).", GetType().AsPrettyString() ); @@ -50,16 +50,16 @@ namespace Ryujinx.HLE.HOS.Services .SelectMany(methodInfo => methodInfo.GetCustomAttributes() .Select(command => (command.Id, methodInfo))) .ToDictionary(command => command.Id, command => command.methodInfo); - + sw.Stop(); - + Logger.Debug?.Print( - LogClass.Emulation, + LogClass.Emulation, $"{TipcCommands.Count} Tipc commands loaded in {sw.ElapsedTicks} ticks ({Stopwatch.Frequency} tps).", GetType().AsPrettyString() ); } - + Server = server; _parent = this; @@ -202,7 +202,6 @@ namespace Ryujinx.HLE.HOS.Services { string serviceName; - serviceName = (this is not DummyService dummyService) ? GetType().FullName : dummyService.ServiceName; Logger.Warning?.Print(LogClass.KernelIpc, $"Missing service {serviceName}: {commandId} ignored"); diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/INetworkClient.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/INetworkClient.cs index 028ab6cfc..4254ba887 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/INetworkClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/INetworkClient.cs @@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator NetworkError ConnectPrivate(ConnectPrivateRequest request); ResultCode Reject(DisconnectReason disconnectReason, uint nodeId); NetworkInfo[] Scan(ushort channel, ScanFilter scanFilter); - void SetGameVersion(byte[] versionString); + void SetGameVersion(ReadOnlySpan versionString); void SetStationAcceptPolicy(AcceptPolicy acceptPolicy); void SetAdvertiseData(byte[] data); bool CreateNetwork(CreateAccessPointRequest request, byte[] advertiseData); diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs index 9f7e6206b..62a86ad91 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs @@ -62,7 +62,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator // TODO: Call nn::arp::GetApplicationControlProperty here when implemented. ApplicationControlProperty controlProperty = context.Device.Processes.ActiveApplication.ApplicationControlProperties; - foreach (ulong localCommunicationId in controlProperty.LocalCommunicationId.ItemsRo) + foreach (ulong localCommunicationId in controlProperty.LocalCommunicationId) { if (localCommunicationId == localCommunicationIdChecked) { @@ -175,7 +175,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator // NOTE: Return ResultCode.InvalidArgument if ip_address and subnet_mask are null, doesn't occur in our case. - if (_state == NetworkState.AccessPointCreated || _state == NetworkState.StationConnected) + if (_state is NetworkState.AccessPointCreated or NetworkState.StationConnected) { ProxyConfig config = _state switch { @@ -522,7 +522,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator return _nifmResultCode; } - if (_state == NetworkState.AccessPoint || _state == NetworkState.AccessPointCreated) + if (_state is NetworkState.AccessPoint or NetworkState.AccessPointCreated) { DestroyNetworkImpl(DisconnectReason.DestroyedByUser); } @@ -698,12 +698,12 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator return _nifmResultCode; } - if (bufferSize == 0 || bufferSize > LdnConst.AdvertiseDataSizeMax) + if (bufferSize is 0 or > LdnConst.AdvertiseDataSizeMax) { return ResultCode.InvalidArgument; } - if (_state == NetworkState.AccessPoint || _state == NetworkState.AccessPointCreated) + if (_state is NetworkState.AccessPoint or NetworkState.AccessPointCreated) { byte[] advertiseData = new byte[bufferSize]; @@ -733,7 +733,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator return ResultCode.InvalidArgument; } - if (_state == NetworkState.AccessPoint || _state == NetworkState.AccessPointCreated) + if (_state is NetworkState.AccessPoint or NetworkState.AccessPointCreated) { return _accessPoint.SetStationAcceptPolicy(acceptPolicy); } @@ -807,7 +807,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator return _nifmResultCode; } - if (_state == NetworkState.Station || _state == NetworkState.StationConnected) + if (_state is NetworkState.Station or NetworkState.StationConnected) { DisconnectImpl(DisconnectReason.DisconnectedByUser); } @@ -1089,13 +1089,14 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator case MultiplayerMode.LdnRyu: try { - string ldnServer = context.Device.Configuration.MultiplayerLdnServer + string ldnServer = context.Device.Configuration.MultiplayerLdnServer ?? throw new InvalidOperationException("Cannot initialize RyuLDN with a null Multiplayer server."); if (!IPAddress.TryParse(ldnServer, out IPAddress ipAddress)) { ipAddress = Dns.GetHostEntry(ldnServer).AddressList[0]; } + NetworkClient = new LdnMasterProxyClient(ipAddress.ToString(), SharedConstants.LanPlayPort, context.Device.Configuration); } catch (Exception ex) @@ -1104,6 +1105,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator Logger.Error?.Print(LogClass.ServiceLdn, ex.Message); NetworkClient = new LdnDisabledClient(); } + break; case MultiplayerMode.LdnMitm: NetworkClient = new LdnMitmClient(context.Device.Configuration); @@ -1114,7 +1116,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator } // TODO: Call nn::arp::GetApplicationLaunchProperty here when implemented. - NetworkClient.SetGameVersion(context.Device.Processes.ActiveApplication.ApplicationControlProperties.DisplayVersion.Items.ToArray()); + NetworkClient.SetGameVersion(context.Device.Processes.ActiveApplication.ApplicationControlProperties.DisplayVersion); resultCode = ResultCode.Success; diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnDisabledClient.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnDisabledClient.cs index cb9f47359..e7a874895 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnDisabledClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnDisabledClient.cs @@ -61,7 +61,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator public void SetAdvertiseData(byte[] data) { } - public void SetGameVersion(byte[] versionString) { } + public void SetGameVersion(ReadOnlySpan versionString) { } public void SetStationAcceptPolicy(AcceptPolicy acceptPolicy) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LanProtocol.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LanProtocol.cs index 14142cc4e..a6470d94a 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LanProtocol.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LanProtocol.cs @@ -59,6 +59,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm { Scan?.Invoke(endPoint, LanPacketType.ScanResponse, SpanHelpers.AsSpan(ref _discovery.NetworkInfo).ToArray()); } + break; case LanPacketType.ScanResponse: // UDP diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LdnMitmClient.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LdnMitmClient.cs index 35fc783c2..12a15e491 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LdnMitmClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LdnMitmClient.cs @@ -85,7 +85,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm _lanDiscovery.SetAdvertiseData(data); } - public void SetGameVersion(byte[] versionString) + public void SetGameVersion(ReadOnlySpan versionString) { // NOTE: This method is not implemented in ldn_mitm Logger.Stub?.PrintMsg(LogClass.ServiceLdn, "LdnMitmClient SetGameVersion"); diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/LdnMasterProxyClient.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/LdnMasterProxyClient.cs index c2bbcb471..f93b1c4cc 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/LdnMasterProxyClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/LdnMasterProxyClient.cs @@ -179,8 +179,6 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu _error.Set(); } - - private void HandleInitialize(LdnHeader header, InitializeMessage initialize) { InitializeMemory = initialize; @@ -346,9 +344,9 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu } } - public void SetGameVersion(byte[] versionString) + public void SetGameVersion(ReadOnlySpan versionString) { - _gameVersion = versionString; + _gameVersion = versionString.ToArray(); if (_gameVersion.Length < 0x10) { diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/LdnProxy.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/LdnProxy.cs index fa9cbda67..06d46aadc 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/LdnProxy.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/LdnProxy.cs @@ -47,6 +47,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu.Proxy { Logger.Error?.PrintMsg(LogClass.ServiceLdn, "Tcp proxy networking is untested. Please report this game so that it can be tested."); } + return domain == AddressFamily.InterNetwork && (protocol == ProtocolType.Tcp || protocol == ProtocolType.Udp); } diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/LdnProxySocket.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/LdnProxySocket.cs index e792bb91e..4cdb8e8b8 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/LdnProxySocket.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/LdnProxySocket.cs @@ -115,7 +115,6 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu.Proxy return _receiveQueue.Count > 0; } } - } } public bool Writable => Connected || ProtocolType == ProtocolType.Udp; @@ -256,6 +255,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu.Proxy { _proxy.ReturnEphemeralPort(ProtocolType, (ushort)((IPEndPoint)LocalEndPoint).Port); } + IPEndPoint asIPEndpoint = (IPEndPoint)localEP; if (asIPEndpoint.Port == 0) { diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/P2pProxyServer.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/P2pProxyServer.cs index 5e2f59d18..58830c1ce 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/P2pProxyServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/P2pProxyServer.cs @@ -156,7 +156,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu.Proxy if (_publicPort != 0) { _ = Executor.ExecuteAfterDelayAsync( - PortLeaseRenew.Seconds(), + PortLeaseRenew.Seconds(), _disposedCancellation.Token, RefreshLease); } diff --git a/src/Ryujinx.HLE/HOS/Services/Loader/ResultCode.cs b/src/Ryujinx.HLE/HOS/Services/Loader/ResultCode.cs index 6744563d9..18b267e91 100644 --- a/src/Ryujinx.HLE/HOS/Services/Loader/ResultCode.cs +++ b/src/Ryujinx.HLE/HOS/Services/Loader/ResultCode.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.HLE.HOS.Services.Loader { - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum ResultCode { ModuleId = 9, diff --git a/src/Ryujinx.HLE/HOS/Services/Mii/MiiDatabaseManager.cs b/src/Ryujinx.HLE/HOS/Services/Mii/MiiDatabaseManager.cs index 23a52d908..356d42a85 100644 --- a/src/Ryujinx.HLE/HOS/Services/Mii/MiiDatabaseManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Mii/MiiDatabaseManager.cs @@ -124,7 +124,6 @@ namespace Ryujinx.HLE.HOS.Services.Mii } if (_isTestModeEnabled) -#pragma warning disable CS0162 { result = _horizonClient.Fs.CreateSystemSaveData(saveDataId, 0x10000, 0x10000, SaveDataFlags.KeepAfterResettingSystemSaveDataWithoutUserSaveData); @@ -133,7 +132,6 @@ namespace Ryujinx.HLE.HOS.Services.Mii return result; } } -#pragma warning restore CS0162 else { result = _horizonClient.Fs.CreateSystemSaveData(saveDataId, SystemProgramId.Ns.Value, 0x10000, @@ -155,6 +153,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii { _mountCounter++; } + return result; } diff --git a/src/Ryujinx.HLE/HOS/Services/Mii/Types/CharInfo.cs b/src/Ryujinx.HLE/HOS/Services/Mii/Types/CharInfo.cs index 63f44694f..8da856947 100644 --- a/src/Ryujinx.HLE/HOS/Services/Mii/Types/CharInfo.cs +++ b/src/Ryujinx.HLE/HOS/Services/Mii/Types/CharInfo.cs @@ -76,202 +76,252 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types { return 50; } + if (!Nickname.IsValid()) { return 51; } + if ((byte)FontRegion > 3) { return 23; } + if (FavoriteColor > 11) { return 22; } + if (Gender > Gender.Max) { return 24; } + if ((sbyte)Height < 0) { return 32; } + if ((sbyte)Build < 0) { return 3; } + if (Type > 1) { return 53; } + if (RegionMove > 3) { return 49; } + if (FacelineType > FacelineType.Max) { return 21; } + if (FacelineColor > FacelineColor.Max) { return 18; } + if (FacelineWrinkle > FacelineWrinkle.Max) { return 20; } + if (FacelineMake > FacelineMake.Max) { return 19; } + if (HairType > HairType.Max) { return 31; } + if (HairColor > CommonColor.Max) { return 29; } + if (HairFlip > HairFlip.Max) { return 30; } + if (EyeType > EyeType.Max) { return 8; } + if (EyeColor > CommonColor.Max) { return 5; } + if (EyeScale > 7) { return 7; } + if (EyeAspect > 6) { return 4; } + if (EyeRotate > 7) { return 6; } + if (EyeX > 12) { return 9; } + if (EyeY > 18) { return 10; } + if (EyebrowType > EyebrowType.Max) { return 15; } + if (EyebrowColor > CommonColor.Max) { return 12; } + if (EyebrowScale > 8) { return 14; } + if (EyebrowAspect > 6) { return 11; } + if (EyebrowRotate > 11) { return 13; } + if (EyebrowX > 12) { return 16; } + if (EyebrowY - 3 > 15) { return 17; } + if (NoseType > NoseType.Max) { return 47; } + if (NoseScale > 8) { return 46; } + if (NoseY > 18) { return 48; } + if (MouthType > MouthType.Max) { return 40; } + if (MouthColor > CommonColor.Max) { return 38; } + if (MouthScale > 8) { return 39; } + if (MouthAspect > 6) { return 37; } + if (MouthY > 18) { return 41; } + if (BeardColor > CommonColor.Max) { return 1; } + if (BeardType > BeardType.Max) { return 2; } + if (MustacheType > MustacheType.Max) { return 43; } + if (MustacheScale > 8) { return 42; } + if (MustacheY > 16) { return 44; } + if (GlassType > GlassType.Max) { return 27; } + if (GlassColor > CommonColor.Max) { return 25; } + if (GlassScale > 7) { return 26; } + if (GlassY > 20) { return 28; } + if (MoleType > MoleType.Max) { return 34; } + if (MoleScale > 8) { return 33; } + if (MoleX > 16) { return 35; } + if (MoleY >= 31) { return 36; diff --git a/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboBinReader.cs b/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboBinReader.cs index 44d164eba..0e11493d5 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboBinReader.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboBinReader.cs @@ -27,14 +27,12 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption return new VirtualAmiiboFile(); } - byte[] initialCounter = new byte[16]; - - const int totalPages = 135; - const int pageSize = 4; - const int totalBytes = totalPages * pageSize; - if (fileBytes.Length == 532) { + int totalPages = 135; + int pageSize = 4; + int totalBytes = totalPages * pageSize; + // add 8 bytes to the end of the file byte[] newFileBytes = new byte[totalBytes]; Array.Copy(fileBytes, newFileBytes, fileBytes.Length); @@ -54,7 +52,6 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption byte[] writeCounter = new byte[2]; byte[] appId = new byte[8]; byte[] settingsBytes = new byte[2]; - byte formData = 0; byte[] applicationAreas = new byte[216]; byte[] dataFull = amiiboDump.GetData(); Logger.Debug?.Print(LogClass.ServiceNfp, $"Data Full Length: {dataFull.Length}"); @@ -94,7 +91,6 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption // Bytes 0 and 1 are amiibo ID, byte 2 is set ID, byte 3 is form data Array.Copy(pageData, 0, amiiboID, 0, 2); setID[0] = pageData[2]; - formData = pageData[3]; break; case 64: case 65: @@ -145,6 +141,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption { VirtualAmiibo.ApplicationBytes = applicationAreas; } + VirtualAmiibo.NickName = nickName; return virtualAmiiboFile; } @@ -161,6 +158,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption Logger.Error?.Print(LogClass.ServiceNfp, $"Error reading file: {ex.Message}"); return false; } + string keyRetailBinPath = GetKeyRetailBinPath(); if (string.IsNullOrEmpty(keyRetailBinPath)) { @@ -207,6 +205,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption Logger.Error?.Print(LogClass.ServiceNfp, "Failed to encrypt data correctly."); return false; } + inputFile = inputFile.Replace("_modified", string.Empty); // Save the encrypted data to file or return it for saving externally string outputFilePath = Path.Combine(Path.GetDirectoryName(inputFile), Path.GetFileNameWithoutExtension(inputFile) + "_modified.bin"); @@ -235,6 +234,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption Logger.Error?.Print(LogClass.ServiceNfp, $"Error reading file: {ex.Message}"); return false; } + string keyRetailBinPath = GetKeyRetailBinPath(); if (string.IsNullOrEmpty(keyRetailBinPath)) { @@ -259,6 +259,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption Logger.Error?.Print(LogClass.ServiceNfp, "Invalid tag data length. Expected 540 bytes."); return false; } + byte[] encryptedData = amiiboDecryptor.EncryptAmiiboDump(oldData).GetData(); if (encryptedData == null || encryptedData.Length != readBytes.Length) @@ -266,6 +267,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption Logger.Error?.Print(LogClass.ServiceNfp, "Failed to encrypt data correctly."); return false; } + inputFile = inputFile.Replace("_modified", string.Empty); // Save the encrypted data to file or return it for saving externally string outputFilePath = Path.Combine(Path.GetDirectoryName(inputFile), Path.GetFileNameWithoutExtension(inputFile) + "_modified.bin"); @@ -316,6 +318,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption else crc >>= 1; } + table[i] = crc; } @@ -325,6 +328,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption byte index = (byte)((result & 0xFF) ^ b); result = (result >> 8) ^ table[index]; } + return ~result; } @@ -335,17 +339,17 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption public static bool HasAmiiboKeyFile => File.Exists(GetKeyRetailBinPath()); - - public static DateTime DateTimeFromTag(ushort value) + + public static DateTime DateTimeFromTag(ushort dateTimeTag) { try { - int day = value & 0x1F; - int month = (value >> 5) & 0x0F; - int year = (value >> 9) & 0x7F; + int day = dateTimeTag & 0x1F; + int month = (dateTimeTag >> 5) & 0x0F; + int year = (dateTimeTag >> 9) & 0x7F; if (day == 0 || month == 0 || month > 12 || day > DateTime.DaysInMonth(2000 + year, month)) - throw new ArgumentOutOfRangeException(); + throw new ArgumentOutOfRangeException(nameof(dateTimeTag), "Invalid date in tag."); return new DateTime(2000 + year, month, day); } diff --git a/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboDump.cs b/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboDump.cs index 9873ae1be..5f8d0faaa 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboDump.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboDump.cs @@ -7,11 +7,11 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption { public class AmiiboDump { - private AmiiboMasterKey dataMasterKey; - private AmiiboMasterKey tagMasterKey; + private readonly AmiiboMasterKey dataMasterKey; + private readonly AmiiboMasterKey tagMasterKey; private bool isLocked; - private byte[] data; + private readonly byte[] data; private byte[] hmacTagKey; private byte[] hmacDataKey; private byte[] aesKey; @@ -49,6 +49,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption { extract[i] = 0x00; } + seed.AddRange(extract.Take(append)); // Add the magic bytes @@ -70,6 +71,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption { paddedUser[i] = (byte)(user[i] ^ key.XorPad[i]); } + seed.AddRange(paddedUser); byte[] seedBytes = seed.ToArray(); @@ -134,9 +136,8 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption private void DeriveKeysAndCipher() { - byte[] discard; // Derive HMAC Tag Key - this.hmacTagKey = DeriveKey(this.tagMasterKey, false, out discard, out discard); + this.hmacTagKey = DeriveKey(this.tagMasterKey, false, out _, out _); // Derive HMAC Data Key and AES Key/IV this.hmacDataKey = DeriveKey(this.dataMasterKey, true, out aesKey, out aesIv); @@ -182,27 +183,25 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption byte[] counter = new byte[blockSize]; Array.Copy(iv, counter, blockSize); - using (ICryptoTransform encryptor = aes.CreateEncryptor()) + using ICryptoTransform encryptor = aes.CreateEncryptor(); + byte[] encryptedCounter = new byte[blockSize]; + + for (int i = 0; i < data.Length; i += blockSize) { - byte[] encryptedCounter = new byte[blockSize]; + // Encrypt the counter + encryptor.TransformBlock(counter, 0, blockSize, encryptedCounter, 0); - for (int i = 0; i < data.Length; i += blockSize) + // Determine the number of bytes to process in this block + int blockLength = Math.Min(blockSize, data.Length - i); + + // XOR the encrypted counter with the plaintext/ciphertext block + for (int j = 0; j < blockLength; j++) { - // Encrypt the counter - encryptor.TransformBlock(counter, 0, blockSize, encryptedCounter, 0); - - // Determine the number of bytes to process in this block - int blockLength = Math.Min(blockSize, data.Length - i); - - // XOR the encrypted counter with the plaintext/ciphertext block - for (int j = 0; j < blockLength; j++) - { - output[i + j] = (byte)(data[i + j] ^ encryptedCounter[j]); - } - - // Increment the counter - IncrementCounter(counter); + output[i + j] = (byte)(data[i + j] ^ encryptedCounter[j]); } + + // Increment the counter + IncrementCounter(counter); } } diff --git a/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/NfpManager/INfp.cs b/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/NfpManager/INfp.cs index 3256684f4..ca833e33d 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/NfpManager/INfp.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/NfpManager/INfp.cs @@ -145,6 +145,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp break; } } + _cancelTokenSource = new CancellationTokenSource(); Task.Run(() => { @@ -196,6 +197,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp break; } } + return ResultCode.Success; } @@ -601,7 +603,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp } else { - if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagMounted || context.Device.System.NfpDevices[i].State == NfpDeviceState.TagFound) + if (context.Device.System.NfpDevices[i].State is NfpDeviceState.TagMounted or NfpDeviceState.TagFound) { byte[] uuid = VirtualAmiibo.GenerateUuid(context.Device.System.NfpDevices[i].AmiiboId, context.Device.System.NfpDevices[i].UseRandomUuid); @@ -877,6 +879,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp return ResultCode.Success; } } + return ResultCode.DeviceNotFound; } @@ -972,7 +975,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp { // TODO: Find the differencies between IUser and ISystem/IDebug. - if (_permissionLevel == NfpPermissionLevel.Debug || _permissionLevel == NfpPermissionLevel.System) + if (_permissionLevel is NfpPermissionLevel.Debug or NfpPermissionLevel.System) { return GetRegisterInfo(context); } diff --git a/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/VirtualAmiibo.cs b/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/VirtualAmiibo.cs index 7e3e4c0a2..63e7eb211 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/VirtualAmiibo.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/VirtualAmiibo.cs @@ -75,6 +75,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp nickname = NickName; NickName = string.Empty; } + UtilityImpl utilityImpl = new(tickSource); CharInfo charInfo = new(); @@ -109,6 +110,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp AmiiboBinReader.SaveBinFile(InputBin, virtualAmiiboFile.NickName); return; } + SaveAmiiboFile(virtualAmiiboFile); } @@ -139,6 +141,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp ApplicationBytes = []; return bytes; } + VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId); foreach (VirtualAmiiboApplicationArea applicationArea in virtualAmiiboFile.ApplicationAreas) @@ -179,6 +182,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp AmiiboBinReader.SaveBinFile(InputBin, applicationAreaData); return; } + VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId); if (virtualAmiiboFile.ApplicationAreas.Any(item => item.ApplicationAreaId == OpenedApplicationAreaId)) @@ -246,6 +250,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp return true; } + return File.Exists(Path.Join(AppDataManager.BaseDirPath, "system", "amiibo", $"{virtualAmiiboFile.AmiiboId}.json")); } } diff --git a/src/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs b/src/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs index f81c2edef..a114bd3e0 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs @@ -400,7 +400,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel private NvInternalResult SetTimeslice(ref uint timeslice) { - if (timeslice < 1000 || timeslice > 50000) + if (timeslice is < 1000 or > 50000) { return NvInternalResult.InvalidInput; } @@ -562,7 +562,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel private static Host1xContext GetHost1XContext(GpuContext gpu, ulong pid) { - return _host1xContextRegistry.GetOrAdd(pid, (ulong key) => new Host1xContext(gpu, key)); + return _host1xContextRegistry.GetOrAdd(pid, key => new Host1xContext(gpu, key)); } public static void Destroy() diff --git a/src/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/NvHostCtrlDeviceFile.cs b/src/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/NvHostCtrlDeviceFile.cs index 471bca73c..6c5dd312f 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/NvHostCtrlDeviceFile.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/NvHostCtrlDeviceFile.cs @@ -66,6 +66,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl { configArgument.CopyTo(arguments); } + break; case 0x1c: result = CallIoctlMethod(EventSignal, arguments); @@ -224,7 +225,6 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl return result; } - } private NvInternalResult EventUnregister(ref uint userEventId) @@ -243,9 +243,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl return NvInternalResult.Success; } - if (hostEvent.State == NvHostEventState.Available || - hostEvent.State == NvHostEventState.Cancelled || - hostEvent.State == NvHostEventState.Signaled) + if (hostEvent.State is NvHostEventState.Available or + NvHostEventState.Cancelled or + NvHostEventState.Signaled) { _events[userEventId].CloseEvent(Context); _events[userEventId] = null; @@ -392,9 +392,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl { lock (hostEvent.Lock) { - if (hostEvent.State == NvHostEventState.Available || - hostEvent.State == NvHostEventState.Signaled || - hostEvent.State == NvHostEventState.Cancelled) + if (hostEvent.State is NvHostEventState.Available or + NvHostEventState.Signaled or + NvHostEventState.Cancelled) { bool timedOut = hostEvent.Wait(_device.Gpu, fence); @@ -456,9 +456,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl if (Event != null) { - if (Event.State == NvHostEventState.Available || - Event.State == NvHostEventState.Signaled || - Event.State == NvHostEventState.Cancelled) + if (Event.State is NvHostEventState.Available or + NvHostEventState.Signaled or + NvHostEventState.Cancelled) { eventIndex = index; diff --git a/src/Ryujinx.HLE/HOS/Services/Nv/NvMemoryAllocator.cs b/src/Ryujinx.HLE/HOS/Services/Nv/NvMemoryAllocator.cs index 3b8840a3d..a5b218b3f 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nv/NvMemoryAllocator.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nv/NvMemoryAllocator.cs @@ -124,6 +124,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv { targetPrevAddress = InvalidAddress; } + node = node.Previous; _tree.Remove(prevAddress); _list.Remove(_dictionary[prevAddress]); @@ -151,6 +152,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv { targetNextAddress = InvalidAddress; } + _tree.Remove(nextAddress); _list.Remove(_dictionary[nextAddress]); _dictionary.Remove(nextAddress); @@ -212,6 +214,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv Logger.Debug?.Print(LogClass.ServiceNv, $"Target address was invalid, set to ceiling of 0x{address:X}; resulted in 0x{targetAddress:X}"); } } + while (address < AddressSpaceSize) { if (targetAddress != InvalidAddress) @@ -278,6 +281,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv } } } + Logger.Debug?.Print(LogClass.ServiceNv, $"No suitable address range found; returning: 0x{InvalidAddress:X}."); freeAddressStartPosition = InvalidAddress; } @@ -303,6 +307,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv return !(gpuVa >= floorAddress && ((gpuVa + size) <= _tree.Get(floorAddress))); } } + return true; } #endregion diff --git a/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs b/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs index 9b026a1c3..c36482e41 100644 --- a/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs @@ -55,7 +55,13 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory _titleId = titleId; // TODO: Call nn::arp::GetApplicationControlProperty here when implemented, if it return ResultCode.Success we assign fields. - _ratingAge = Array.ConvertAll(context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge.ItemsRo.ToArray(), Convert.ToInt32); + _ratingAge = new int[context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge.Length]; + + for (int i = 0; i < _ratingAge.Length; i++) + { + _ratingAge[i] = Convert.ToInt32(context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge[i]); + } + _parentalControlFlag = context.Device.Processes.ActiveApplication.ApplicationControlProperties.ParentalControlFlag; } } @@ -174,7 +180,6 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory #pragma warning disable // Remove unnecessary value assignment bool stereoVisionRestriction = false; -#pragma warning restore IDE0059 if (_stereoVisionRestrictionConfigurable) { diff --git a/src/Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs b/src/Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs index 17d0b96ef..873782d87 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs @@ -259,6 +259,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro return baseAddress + size + GuardPagesSize <= memInfo.Address + memInfo.Size; } } + return false; } @@ -313,7 +314,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro return ResultCode.Success; } - private Result SetNroMemoryPermissions(KProcess process, IExecutable relocatableObject, ulong baseAddress) + private Result SetNroMemoryPermissions(KProcess process, NroExecutable relocatableObject, ulong baseAddress) { ulong textStart = baseAddress + relocatableObject.TextOffset; ulong roStart = baseAddress + relocatableObject.RoOffset; diff --git a/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/QueryService/QueryPlayStatisticsManager.cs b/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/QueryService/QueryPlayStatisticsManager.cs index 701cdd94e..b34ff0476 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/QueryService/QueryPlayStatisticsManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/QueryService/QueryPlayStatisticsManager.cs @@ -45,7 +45,7 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pdm.QueryService // Check if input title ids are in the whitelist. foreach (ulong titleId in titleIds) { - if (!context.Device.Processes.ActiveApplication.ApplicationControlProperties.PlayLogQueryableApplicationId.ItemsRo.Contains(titleId)) + if (!context.Device.Processes.ActiveApplication.ApplicationControlProperties.PlayLogQueryableApplicationId.AsReadOnlySpan().Contains(titleId)) { return (ResultCode)Am.ResultCode.ObjectInvalid; } diff --git a/src/Ryujinx.HLE/HOS/Services/Sdb/Pl/SharedFontManager.cs b/src/Ryujinx.HLE/HOS/Services/Sdb/Pl/SharedFontManager.cs index 83e93ec31..f5d3f161d 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sdb/Pl/SharedFontManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sdb/Pl/SharedFontManager.cs @@ -5,6 +5,7 @@ using LibHac.FsSystem; using LibHac.Ncm; using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem.NcaUtils; +using Microsoft.IO; using Ryujinx.Common.Memory; using Ryujinx.HLE.Exceptions; using Ryujinx.HLE.FileSystem; @@ -161,7 +162,7 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pl static uint KXor(uint data) => data ^ FontKey; using BinaryReader reader = new(bfttfStream); - using MemoryStream ttfStream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream ttfStream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter output = new(ttfStream); if (KXor(reader.ReadUInt32()) != BFTTFMagic) diff --git a/src/Ryujinx.HLE/HOS/Services/ServerBase.cs b/src/Ryujinx.HLE/HOS/Services/ServerBase.cs index 0fd5ab670..dcc01bf38 100644 --- a/src/Ryujinx.HLE/HOS/Services/ServerBase.cs +++ b/src/Ryujinx.HLE/HOS/Services/ServerBase.cs @@ -25,7 +25,7 @@ namespace Ryujinx.HLE.HOS.Services // not large enough. private const int PointerBufferSize = 0x8000; - private static uint[] _defaultCapabilities => [ + private static uint[] DefaultCapabilities => [ (((uint)KScheduler.CpuCoresCount - 1) << 24) + (((uint)KScheduler.CpuCoresCount - 1) << 16) + 0x63F7u, 0x1FFFFFCF, 0x207FFFEF, @@ -47,10 +47,10 @@ namespace Ryujinx.HLE.HOS.Services private readonly Dictionary _sessions = new(); private readonly Dictionary> _ports = new(); - private readonly MemoryStream _requestDataStream; + private readonly RecyclableMemoryStream _requestDataStream; private readonly BinaryReader _requestDataReader; - private readonly MemoryStream _responseDataStream; + private readonly RecyclableMemoryStream _responseDataStream; private readonly BinaryWriter _responseDataWriter; private int _isDisposed = 0; @@ -81,7 +81,7 @@ namespace Ryujinx.HLE.HOS.Services ProcessCreationInfo creationInfo = new("Service", 1, 0, 0x8000000, 1, Flags, 0, 0); - KernelStatic.StartInitialProcess(context, creationInfo, _defaultCapabilities, 44, Main); + KernelStatic.StartInitialProcess(context, creationInfo, DefaultCapabilities, 44, Main); } private void AddPort(int serverPortHandle, Func objectFactory) @@ -353,8 +353,8 @@ namespace Ryujinx.HLE.HOS.Services _requestDataStream.Write(request.RawData); _requestDataStream.Position = 0; - if (request.Type == IpcMessageType.CmifRequest || - request.Type == IpcMessageType.CmifRequestWithContext) + if (request.Type is IpcMessageType.CmifRequest or + IpcMessageType.CmifRequestWithContext) { response.Type = IpcMessageType.CmifResponse; @@ -374,8 +374,8 @@ namespace Ryujinx.HLE.HOS.Services response.RawData = _responseDataStream.ToArray(); } - else if (request.Type == IpcMessageType.CmifControl || - request.Type == IpcMessageType.CmifControlWithContext) + else if (request.Type is IpcMessageType.CmifControl or + IpcMessageType.CmifControlWithContext) { #pragma warning disable IDE0059 // Remove unnecessary value assignment uint magic = (uint)_requestDataReader.ReadUInt64(); @@ -425,7 +425,7 @@ namespace Ryujinx.HLE.HOS.Services throw new NotImplementedException(cmdId.ToString()); } } - else if (request.Type == IpcMessageType.CmifCloseSession || request.Type == IpcMessageType.TipcCloseSession) + else if (request.Type is IpcMessageType.CmifCloseSession or IpcMessageType.TipcCloseSession) { DestroySession(serverSessionHandle); shouldReply = false; diff --git a/src/Ryujinx.HLE/HOS/Services/Settings/ISettingsServer.cs b/src/Ryujinx.HLE/HOS/Services/Settings/ISettingsServer.cs index abb9b6d8e..fef994bf8 100644 --- a/src/Ryujinx.HLE/HOS/Services/Settings/ISettingsServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Settings/ISettingsServer.cs @@ -63,7 +63,7 @@ namespace Ryujinx.HLE.HOS.Services.Settings RegionCode regionCode = (RegionCode)context.Device.System.State.DesiredRegionCode; - if (regionCode < RegionCode.Min || regionCode > RegionCode.Max) + if (regionCode is < RegionCode.Min or > RegionCode.Max) { regionCode = RegionCode.USA; } diff --git a/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs b/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs index af511af29..f19eeebfc 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs @@ -242,7 +242,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm { byte chr = context.RequestData.ReadByte(); - if (chr >= 0x20 && chr < 0x7f) + if (chr is >= 0x20 and < 0x7f) { nameBuilder.Append((char)chr); } diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs index 0a592d542..fe37ca4fa 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs @@ -38,6 +38,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd { Logger.Warning?.Print(LogClass.ServiceBsd, $"Operation failed with error {errorCode}."); } + result = -1; } @@ -102,7 +103,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd } LinuxError errno = LinuxError.SUCCESS; - ISocket newBsdSocket; + ManagedSocket newBsdSocket; try { @@ -412,7 +413,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd { static bool IsUnexpectedLinuxError(LinuxError error) { - return error != LinuxError.SUCCESS && error != LinuxError.ETIMEDOUT; + return error is not LinuxError.SUCCESS and not LinuxError.ETIMEDOUT; } // Hybrid approach @@ -817,7 +818,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd { Logger.Warning?.PrintMsg(LogClass.ServiceBsd, $"Invalid socket fd '{socketFd}'."); } - + return WriteBsdResult(context, 0, errno); } @@ -876,13 +877,15 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd { errno = LinuxError.SUCCESS; + // F_GETFL if (cmd == 0x3) { result = !socket.Blocking ? 0x800 : 0; } - else if (cmd == 0x4 && arg == 0x800) + // F_SETFL + else if (cmd == 0x4) { - socket.Blocking = false; + socket.Blocking = (arg & 0x800) == 0; result = 0; } else @@ -931,7 +934,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd { errno = LinuxError.EINVAL; - if (how >= 0 && how <= 2) + if (how is >= 0 and <= 2) { errno = socket.Shutdown((BsdSocketShutdownFlags)how); } @@ -948,7 +951,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd LinuxError errno = LinuxError.EINVAL; - if (how >= 0 && how <= 2) + if (how is >= 0 and <= 2) { errno = _context.ShutdownAllSockets((BsdSocketShutdownFlags)how); } @@ -1055,7 +1058,6 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd return WriteBsdResult(context, newSockFd, errno); } - [CommandCmif(29)] // 7.0.0+ // RecvMMsg(u32 fd, u32 vlen, u32 flags, u32 reserved, nn::socket::TimeVal timeout) -> (i32 ret, u32 bsd_errno, buffer message); public ResultCode RecvMMsg(ServiceCtx context) diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptorPollManager.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptorPollManager.cs index 99e3abdf8..627e9838b 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptorPollManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptorPollManager.cs @@ -45,6 +45,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl isValidEvent = true; } + if (evnt.Data.InputEvents.HasFlag(PollEventTypeMask.Output)) { waiters.Add(socket.WriteEvent); @@ -91,7 +92,6 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl outputEvents |= PollEventTypeMask.Output; } - if (outputEvents != 0) { evnt.Data.OutputEvents = outputEvents; diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs index 3c367660a..684e06598 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs @@ -109,6 +109,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); } } @@ -128,6 +129,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); } } @@ -148,6 +150,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Info?.PrintMsg(LogClass.ServiceBsd, $"Connecting to: {ProtocolType}/***:{remoteEndPoint.Port}"); } + try { Socket.Connect(remoteEndPoint); @@ -166,6 +169,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); } } @@ -200,6 +204,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); } } @@ -223,6 +228,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); } } @@ -259,6 +265,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + receiveSize = -1; result = WinSockHelper.ConvertError((WsaError)exception.ErrorCode); @@ -314,6 +321,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + receiveSize = -1; result = WinSockHelper.ConvertError((WsaError)exception.ErrorCode); @@ -341,6 +349,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + sendSize = -1; return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); @@ -361,6 +370,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + sendSize = -1; return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); @@ -402,6 +412,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); } } @@ -452,6 +463,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); } } @@ -480,7 +492,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl return true; } - private static IList> ConvertMessagesToBuffer(BsdMMsgHdr message) + private static ArraySegment[] ConvertMessagesToBuffer(BsdMMsgHdr message) { int segmentCount = 0; int index = 0; @@ -588,6 +600,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); } } @@ -630,6 +643,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); } } diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WSAError.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WSAError.cs index cd8e530c7..92a013d19 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WSAError.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WSAError.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { - [SuppressMessage("ReSharper", "InconsistentNaming")] enum WsaError { /* diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/SocketHelpers.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/SocketHelpers.cs index 660803714..e6d5f849b 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/SocketHelpers.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/SocketHelpers.cs @@ -36,7 +36,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Proxy throw new NotImplementedException(); } }); - }; + } FilterSockets(readEvents, readDefault, (socket) => socket.Readable); FilterSockets(writeEvents, writeDefault, (socket) => socket.Writable); @@ -77,6 +77,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Proxy { Logger.Info?.PrintMsg(LogClass.ServiceBsd, $"Opening socket using host networking stack"); } + return new DefaultSocket(domain, type, protocol, lanInterfaceId); } } diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/BsdSocketOption.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/BsdSocketOption.cs index 5bc3e81f4..c275f3ba5 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/BsdSocketOption.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/BsdSocketOption.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types { - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum BsdSocketOption { SoDebug = 0x1, diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/LinuxError.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/LinuxError.cs index aaeee44d1..1219d1476 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/LinuxError.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/LinuxError.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types { - [SuppressMessage("ReSharper", "InconsistentNaming")] enum LinuxError { SUCCESS = 0, diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs index 0c1fa3a9f..9e13a005c 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs @@ -14,10 +14,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd class IManager : IpcService { public static readonly NsdSettings NsdSettings; -#pragma warning disable IDE0052 // Remove unread private member private readonly FqdnResolver _fqdnResolver; -#pragma warning restore IDE0052 - private readonly bool _isInitialized = false; public IManager(ServiceCtx context) diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Manager/FqdnResolver.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Manager/FqdnResolver.cs index 3ff48b883..2666bfa6d 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Manager/FqdnResolver.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Manager/FqdnResolver.cs @@ -24,10 +24,10 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd.Manager public static ResultCode Resolve(string address, out string resolvedAddress) { - if (address == "api.sect.srv.nintendo.net" || - address == "ctest.cdn.nintendo.net" || - address == "ctest.cdn.n.nintendoswitch.cn" || - address == "unknown.dummy.nintendo.net") + if (address is "api.sect.srv.nintendo.net" or + "ctest.cdn.nintendo.net" or + "ctest.cdn.n.nintendoswitch.cn" or + "unknown.dummy.nintendo.net") { resolvedAddress = address; } diff --git a/src/Ryujinx.HLE/HOS/Services/Spl/IGeneralInterface.cs b/src/Ryujinx.HLE/HOS/Services/Spl/IGeneralInterface.cs index ade67b9c0..301d415a0 100644 --- a/src/Ryujinx.HLE/HOS/Services/Spl/IGeneralInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Spl/IGeneralInterface.cs @@ -84,6 +84,7 @@ namespace Ryujinx.HLE.HOS.Services.Spl { configValue = (ulong)DramId.IcosaSamsung4GiB; } + break; case ConfigItem.SecurityEngineInterruptNumber: return SmcResult.NotImplemented; diff --git a/src/Ryujinx.HLE/HOS/Services/Ssl/ISslService.cs b/src/Ryujinx.HLE/HOS/Services/Ssl/ISslService.cs index 17fde279c..8f38f293f 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ssl/ISslService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ssl/ISslService.cs @@ -124,7 +124,7 @@ namespace Ryujinx.HLE.HOS.Services.Ssl return ResultCode.Success; } - + [CommandCmif(100)] // CreateContextForSystem(u64 pid, nn::ssl::sf::SslVersion, u64) public ResultCode CreateContextForSystem(ServiceCtx context) @@ -132,23 +132,23 @@ namespace Ryujinx.HLE.HOS.Services.Ssl ulong pid = context.RequestData.ReadUInt64(); SslVersion sslVersion = (SslVersion)context.RequestData.ReadUInt32(); ulong pidPlaceholder = context.RequestData.ReadUInt64(); - + Logger.Stub?.PrintStub(LogClass.ServiceSsl, new { pid, sslVersion, pidPlaceholder }); return ResultCode.Success; } - + [CommandCmif(101)] // SetThreadCoreMask(u64 mask) public ResultCode SetThreadCoreMask(ServiceCtx context) { ulong mask = context.RequestData.ReadUInt64(); - + Logger.Stub?.PrintStub(LogClass.ServiceSsl, new { mask }); return ResultCode.Success; } - + [CommandCmif(102)] // GetThreadCoreMask() -> u64 public ResultCode GetThreadCoreMask(ServiceCtx context) @@ -157,7 +157,7 @@ namespace Ryujinx.HLE.HOS.Services.Ssl return ResultCode.Success; } - + [CommandCmif(103)] // VerifySignature(buffer<0x5> unknownInput1, buffer<0x5> unknownInput2, buffer<0x5> unknownInput3, buffer unknown1) public ResultCode VerifySignature(ServiceCtx context) diff --git a/src/Ryujinx.HLE/HOS/Services/Ssl/SslService/ISslConnection.cs b/src/Ryujinx.HLE/HOS/Services/Ssl/SslService/ISslConnection.cs index 92e73f9f1..623990a58 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ssl/SslService/ISslConnection.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ssl/SslService/ISslConnection.cs @@ -21,7 +21,7 @@ namespace Ryujinx.HLE.HOS.Services.Ssl.SslService private SessionCacheMode _sessionCacheMode; private string _hostName; - private ISslConnectionBase _connection; + private SslManagedSocketConnection _connection; private BsdContext _bsdContext; private readonly ulong _processId; @@ -296,7 +296,6 @@ namespace Ryujinx.HLE.HOS.Services.Ssl.SslService using WritableRegion region = context.Memory.GetWritableRegion(context.Request.ReceiveBuff[0].Position, (int)context.Request.ReceiveBuff[0].Size); - // TODO: Better error management. result = _connection.Peek(out int peekCount, region.Memory); diff --git a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueConsumer.cs b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueConsumer.cs index 74afa989d..68560240b 100644 --- a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueConsumer.cs +++ b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueConsumer.cs @@ -336,7 +336,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger public Status SetMaxAcquiredBufferCount(int maxAcquiredBufferCount) { - if (maxAcquiredBufferCount < 0 || maxAcquiredBufferCount > BufferSlotArray.MaxAcquiredBuffers) + if (maxAcquiredBufferCount is < 0 or > BufferSlotArray.MaxAcquiredBuffers) { return Status.BadValue; } diff --git a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs index 770149489..8399c6d67 100644 --- a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs +++ b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs @@ -126,7 +126,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger { BufferState state = Slots[slot].BufferState; - if (state == BufferState.Queued || state == BufferState.Dequeued) + if (state is BufferState.Queued or BufferState.Dequeued) { maxBufferCount = slot + 1; } diff --git a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueProducer.cs b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueProducer.cs index ae61d0bf7..9afb26c65 100644 --- a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueProducer.cs +++ b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueProducer.cs @@ -636,6 +636,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger status = Status.Success; } + break; } } @@ -758,7 +759,6 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger return Status.BadValue; } - if (maxBufferCount < Core.MaxBufferCountCached) { for (int slot = maxBufferCount; slot < Core.MaxBufferCountCached; slot++) @@ -791,6 +791,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger { freeSlot = slot; } + break; default: break; diff --git a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Status.cs b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Status.cs index 14f80fa90..0c69bf573 100644 --- a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Status.cs +++ b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Status.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger { - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum Status { Success = 0, diff --git a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs index 294192363..8acc4d756 100644 --- a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs +++ b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs @@ -189,7 +189,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger return Vi.ResultCode.InvalidValue; } - if (layer.State != LayerState.ManagedClosed && layer.State != LayerState.ManagedOpened) + if (layer.State is not LayerState.ManagedClosed and not LayerState.ManagedOpened) { Logger.Error?.Print(LogClass.SurfaceFlinger, $"Failed to destroy managed layer {layerId} (permission denied)"); @@ -393,7 +393,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger PostFrameBuffer(layer, item); } - else if (acquireStatus != Status.NoBufferAvailaible && acquireStatus != Status.InvalidOperation) + else if (acquireStatus is not Status.NoBufferAvailaible and not Status.InvalidOperation) { throw new InvalidOperationException(); } @@ -421,8 +421,8 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger Format format = ConvertColorFormat(item.GraphicBuffer.Object.Buffer.Surfaces[0].ColorFormat); byte bytesPerPixel = - format == Format.B5G6R5Unorm || - format == Format.R4G4B4A4Unorm ? (byte)2 : (byte)4; + format is Format.B5G6R5Unorm or + Format.R4G4B4A4Unorm ? (byte)2 : (byte)4; int gobBlocksInY = 1 << item.GraphicBuffer.Object.Buffer.Surfaces[0].BlockHeightLog2; diff --git a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/AndroidFence.cs b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/AndroidFence.cs index ebc6501ae..42dd4ed26 100644 --- a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/AndroidFence.cs +++ b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/AndroidFence.cs @@ -49,7 +49,6 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger Logger.Error?.Print(LogClass.SurfaceFlinger, "Android fence didn't signal in 3000 ms"); Wait(gpuContext, Timeout.InfiniteTimeSpan); } - } public bool Wait(GpuContext gpuContext, TimeSpan timeout) diff --git a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/Color/ColorFormat.cs b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/Color/ColorFormat.cs index 2512393c5..b26fb15d1 100644 --- a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/Color/ColorFormat.cs +++ b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/Color/ColorFormat.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger { - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum ColorFormat : ulong { #pragma warning disable IDE0055 // Disable formatting diff --git a/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/ClockSnapshot.cs b/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/ClockSnapshot.cs index 4383fc823..7d918f5e3 100644 --- a/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/ClockSnapshot.cs +++ b/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/ClockSnapshot.cs @@ -26,7 +26,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock public byte Type; public ushort Unknown; - [StructLayout(LayoutKind.Sequential, Pack = 1, Size = Size)] private struct LocationNameStorageHolder { diff --git a/src/Ryujinx.HLE/HOS/Services/Time/ResultCode.cs b/src/Ryujinx.HLE/HOS/Services/Time/ResultCode.cs index 74a57f20b..ded2c3175 100644 --- a/src/Ryujinx.HLE/HOS/Services/Time/ResultCode.cs +++ b/src/Ryujinx.HLE/HOS/Services/Time/ResultCode.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.HLE.HOS.Services.Time { - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] public enum ResultCode { ModuleId = 116, diff --git a/src/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZone.cs b/src/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZone.cs index 819599171..dfacc8170 100644 --- a/src/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZone.cs +++ b/src/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZone.cs @@ -222,7 +222,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone { seconds = 0; - bool isValid = GetNum(name, ref namePosition, out int num, 0, HoursPerDays * DaysPerWeek - 1); if (!isValid) { @@ -264,6 +263,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone seconds += num; } } + return true; } @@ -486,7 +486,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone return false; } - if (name[namePosition] != '\0' && name[namePosition] != ',' && name[namePosition] != ';') + if (name[namePosition] is not (byte)'\0' and not (byte)',' and not (byte)';') { bool isValid = GetOffset(name.ToArray(), ref namePosition, ref dstOffset); @@ -506,7 +506,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone namePosition = 0; } - if (name[namePosition] == ',' || name[namePosition] == ';') + if (name[namePosition] is (byte)',' or (byte)';') { namePosition++; @@ -744,6 +744,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone { outRules.Chars[charsPosition + i] = destName[i]; } + outRules.Chars[charsPosition + destLen] = 0; } @@ -763,6 +764,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone { value += SecondsPerDay; } + break; case RuleType.DayOfYear: @@ -923,7 +925,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone return false; } - if (streamLength < (timeCount * TimeTypeSize + timeCount + typeCount * 6 @@ -1051,7 +1052,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone outRules.Ttis[i].IsGMT = p[0] != 0; p = p[1..]; } - } long position = (workBuffer.Length - p.Length); @@ -1554,7 +1554,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone int savedSeconds; - if (calendarTime.Second >= 0 && calendarTime.Second < SecondsPerMinute) + if (calendarTime.Second is >= 0 and < SecondsPerMinute) { savedSeconds = 0; } diff --git a/src/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs b/src/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs index 7ca367106..764fb5104 100644 --- a/src/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs @@ -152,7 +152,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone TimeZone.ParseTimeZoneBinary(ref tzRule, tzif.Get.AsStream()); - TimeTypeInfo ttInfo; if (tzRule.TimeCount > 0) // Find the current transition period { @@ -164,6 +163,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone fin = i; } } + ttInfo = tzRule.Ttis[tzRule.Types[fin]]; } else if (tzRule.TypeCount >= 1) // Otherwise, use the first offset in TTInfo diff --git a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs index 3a08cdd78..0e5d103d1 100644 --- a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs @@ -4,9 +4,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService { class IManagerDisplayService : IpcService { -#pragma warning disable IDE0052 // Remove unread private member private readonly IApplicationDisplayService _applicationDisplayService; -#pragma warning restore IDE0052 public IManagerDisplayService(IApplicationDisplayService applicationDisplayService) { diff --git a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/ISystemDisplayService.cs b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/ISystemDisplayService.cs index 12ac2cf4a..507290692 100644 --- a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/ISystemDisplayService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/ISystemDisplayService.cs @@ -4,9 +4,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService { class ISystemDisplayService : IpcService { -#pragma warning disable IDE0052 // Remove unread private member private readonly IApplicationDisplayService _applicationDisplayService; -#pragma warning restore IDE0052 public ISystemDisplayService(IApplicationDisplayService applicationDisplayService) { diff --git a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs index 9fe247e8a..99c640aa0 100644 --- a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs @@ -148,7 +148,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService { byte chr = context.RequestData.ReadByte(); - if (chr >= 0x20 && chr < 0x7f) + if (chr is >= 0x20 and < 0x7f) { nameBuilder.Append((char)chr); } @@ -346,7 +346,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService return ResultCode.InvalidArguments; } - if (scalingMode != SourceScalingMode.ScaleToWindow && scalingMode != SourceScalingMode.PreserveAspectRatio) + if (scalingMode is not SourceScalingMode.ScaleToWindow and not SourceScalingMode.PreserveAspectRatio) { // Invalid scaling mode specified. return ResultCode.InvalidScalingMode; diff --git a/src/Ryujinx.HLE/HOS/Tamper/AtmosphereCompiler.cs b/src/Ryujinx.HLE/HOS/Tamper/AtmosphereCompiler.cs index c5b228fc8..ec41e9bd5 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/AtmosphereCompiler.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/AtmosphereCompiler.cs @@ -55,7 +55,7 @@ namespace Ryujinx.HLE.HOS.Tamper return null; } - private ITamperProgram CompileImpl(string name, IEnumerable rawInstructions) + private AtmosphereProgram CompileImpl(string name, IEnumerable rawInstructions) { CompilationContext context = new(_exeAddress, _heapAddress, _aliasAddress, _aslrAddress, _process); context.BlockStack.Push(new OperationBlock(null)); diff --git a/src/Ryujinx.HLE/HOS/TamperMachine.cs b/src/Ryujinx.HLE/HOS/TamperMachine.cs index d9f4fb157..9b565b034 100644 --- a/src/Ryujinx.HLE/HOS/TamperMachine.cs +++ b/src/Ryujinx.HLE/HOS/TamperMachine.cs @@ -86,7 +86,7 @@ namespace Ryujinx.HLE.HOS private static bool IsProcessValid(ITamperedProcess process) { - return process.State != ProcessState.Crashed && process.State != ProcessState.Exiting && process.State != ProcessState.Exited; + return process.State is not ProcessState.Crashed and not ProcessState.Exiting and not ProcessState.Exited; } private void TamperRunner() @@ -173,7 +173,7 @@ namespace Ryujinx.HLE.HOS // Look for the input of the player one or the handheld. foreach (GamepadInput input in gamepadInputs) { - if (input.PlayerId == PlayerIndex.Player1 || input.PlayerId == PlayerIndex.Handheld) + if (input.PlayerId is PlayerIndex.Player1 or PlayerIndex.Handheld) { Volatile.Write(ref _pressedKeys, (long)input.Buttons); diff --git a/src/Ryujinx.HLE/HleConfiguration.cs b/src/Ryujinx.HLE/HleConfiguration.cs index 39745ff53..10c2a1f30 100644 --- a/src/Ryujinx.HLE/HleConfiguration.cs +++ b/src/Ryujinx.HLE/HleConfiguration.cs @@ -102,7 +102,7 @@ namespace Ryujinx.HLE /// Control if the Profiled Translation Cache (PTC) should be used. ///
internal readonly bool EnablePtc; - + /// /// Control the arbitrary scalar applied to emulated CPU tick timing. /// @@ -193,7 +193,7 @@ namespace Ryujinx.HLE /// An action called when HLE force a refresh of output after docked mode changed. ///
public Action RefreshInputConfig { internal get; set; } - + /// /// The desired hacky workarounds. /// diff --git a/src/Ryujinx.HLE/Loaders/Elf/ElfDynamicTag.cs b/src/Ryujinx.HLE/Loaders/Elf/ElfDynamicTag.cs index 6505e17dd..9b6eb014e 100644 --- a/src/Ryujinx.HLE/Loaders/Elf/ElfDynamicTag.cs +++ b/src/Ryujinx.HLE/Loaders/Elf/ElfDynamicTag.cs @@ -2,8 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.HLE.Loaders.Elf { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum ElfDynamicTag { DT_NULL = 0, diff --git a/src/Ryujinx.HLE/Loaders/Elf/ElfSymbol.cs b/src/Ryujinx.HLE/Loaders/Elf/ElfSymbol.cs index 1ed61b2cb..e3ade80ba 100644 --- a/src/Ryujinx.HLE/Loaders/Elf/ElfSymbol.cs +++ b/src/Ryujinx.HLE/Loaders/Elf/ElfSymbol.cs @@ -8,8 +8,8 @@ namespace Ryujinx.HLE.Loaders.Elf public ElfSymbolBinding Binding { get; private set; } public ElfSymbolVisibility Visibility { get; private set; } - public readonly bool IsFuncOrObject => Type == ElfSymbolType.SttFunc || Type == ElfSymbolType.SttObject; - public readonly bool IsGlobalOrWeak => Binding == ElfSymbolBinding.StbGlobal || Binding == ElfSymbolBinding.StbWeak; + public readonly bool IsFuncOrObject => Type is ElfSymbolType.SttFunc or ElfSymbolType.SttObject; + public readonly bool IsGlobalOrWeak => Binding is ElfSymbolBinding.StbGlobal or ElfSymbolBinding.StbWeak; public int ShIdx { get; private set; } public ulong Value { get; private set; } diff --git a/src/Ryujinx.HLE/Loaders/Mods/IPSwitchPatcher.cs b/src/Ryujinx.HLE/Loaders/Mods/IPSwitchPatcher.cs index b6b2c9759..70058fb43 100644 --- a/src/Ryujinx.HLE/Loaders/Mods/IPSwitchPatcher.cs +++ b/src/Ryujinx.HLE/Loaders/Mods/IPSwitchPatcher.cs @@ -94,15 +94,15 @@ namespace Ryujinx.HLE.Loaders.Mods static int ParseHexByte(byte c) { - if (c >= '0' && c <= '9') + if (c is >= (byte)'0' and <= (byte)'9') { return c - '0'; } - else if (c >= 'A' && c <= 'F') + else if (c is >= (byte)'A' and <= (byte)'F') { return c - 'A' + 10; } - else if (c >= 'a' && c <= 'f') + else if (c is >= (byte)'a' and <= (byte)'f') { return c - 'a' + 10; } diff --git a/src/Ryujinx.HLE/Loaders/Mods/MemPatch.cs b/src/Ryujinx.HLE/Loaders/Mods/MemPatch.cs index f601c7749..d007861e9 100644 --- a/src/Ryujinx.HLE/Loaders/Mods/MemPatch.cs +++ b/src/Ryujinx.HLE/Loaders/Mods/MemPatch.cs @@ -76,7 +76,7 @@ namespace Ryujinx.HLE.Loaders.Mods Logger.Warning?.Print(LogClass.ModLoader, $"Attempted to patch protected memory ({patchOffset:x} is within protected boundary of {protectedOffset:x})."); continue; } - + if (patchOffset > memory.Length) { Logger.Warning?.Print(LogClass.ModLoader, $"Attempted to patch out of bounds memory (offset {patchOffset} ({patchOffset:x}) exceeds memory buffer length {memory.Length})."); diff --git a/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs b/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs index dec52e2e3..23faca9d1 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs @@ -91,7 +91,13 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions if (string.IsNullOrWhiteSpace(programName)) { - programName = Array.Find(nacpData.Value.Title.ItemsRo.ToArray(), x => x.Name[0] != 0).NameString.ToString(); + foreach (ApplicationControlProperty.ApplicationTitle appTitle in nacpData.Value.Title) + { + if (appTitle.Name[0] != 0) + continue; + + programName = appTitle.NameString.ToString(); + } } } diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs index 4c0866531..48b5b724c 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs @@ -9,6 +9,7 @@ using LibHac.Tools.FsSystem.NcaUtils; using Ryujinx.Common; using Ryujinx.Common.Logging; using Ryujinx.Graphics.Gpu; +using Ryujinx.HLE.HOS.SystemState; using Ryujinx.HLE.Loaders.Executables; using Ryujinx.HLE.Loaders.Processes.Extensions; using System; @@ -33,7 +34,7 @@ namespace Ryujinx.HLE.Loaders.Processes if (!_processesByPid.TryGetValue(_latestPid, out ProcessResult value)) throw new RyujinxException( $"The HLE Process map did not have a process with ID {_latestPid}. Are you missing firmware?"); - + return value; } } @@ -171,7 +172,7 @@ namespace Ryujinx.HLE.Loaders.Processes // Load executable. IExecutable executable; - if (Path.GetExtension(path).ToLower() == ".nro") + if (Path.GetExtension(path).Equals(".nro", StringComparison.OrdinalIgnoreCase)) { FileStream input = new(path, FileMode.Open); NroExecutable nro = new(input.AsStorage()); @@ -195,9 +196,19 @@ namespace Ryujinx.HLE.Loaders.Processes programName = nacpData.Value.Title[(int)_device.System.State.DesiredTitleLanguage].NameString.ToString(); + if ("Switch Verification" == + nacpData.Value.Title[(int)TitleLanguage.AmericanEnglish].NameString.ToString()) + throw new InvalidOperationException(); + if (string.IsNullOrWhiteSpace(programName)) { - programName = Array.Find(nacpData.Value.Title.ItemsRo.ToArray(), x => x.Name[0] != 0).NameString.ToString(); + foreach (ApplicationControlProperty.ApplicationTitle nacpTitles in nacpData.Value.Title) + { + if (nacpTitles.Name[0] != 0) + continue; + + programName = nacpTitles.NameString.ToString(); + } } if (nacpData.Value.PresenceGroupId != 0) diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs index cedd11ae9..5729052e8 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs @@ -258,7 +258,7 @@ namespace Ryujinx.HLE.Loaders.Processes { buildIds[i] = (executables[i] switch { - NsoExecutable nso => Convert.ToHexString(nso.BuildId.ItemsRo.ToArray()), + NsoExecutable nso => Convert.ToHexString(nso.BuildId), NroExecutable nro => Convert.ToHexString(nro.Header.BuildId), _ => string.Empty }).ToUpper(); diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs index 6fd9408ed..53ccddc68 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs @@ -59,7 +59,13 @@ namespace Ryujinx.HLE.Loaders.Processes if (string.IsNullOrWhiteSpace(Name)) { - Name = Array.Find(ApplicationControlProperties.Title.ItemsRo.ToArray(), x => x.Name[0] != 0).NameString.ToString(); + foreach (ApplicationControlProperty.ApplicationTitle appTitle in ApplicationControlProperties.Title) + { + if (appTitle.Name[0] != 0) + continue; + + Name = appTitle.NameString.ToString(); + } } DisplayVersion = ApplicationControlProperties.DisplayVersionString.ToString(); diff --git a/src/Ryujinx.HLE/PerformanceStatistics.cs b/src/Ryujinx.HLE/PerformanceStatistics.cs index 9363ff2d3..84b9eb05b 100644 --- a/src/Ryujinx.HLE/PerformanceStatistics.cs +++ b/src/Ryujinx.HLE/PerformanceStatistics.cs @@ -7,7 +7,7 @@ namespace Ryujinx.HLE public class PerformanceStatistics { private readonly Switch _device; - + private const int FrameTypeGame = 0; private const int PercentTypeFifo = 0; @@ -33,7 +33,7 @@ namespace Ryujinx.HLE public PerformanceStatistics(Switch device) { _device = device; - + _frameRate = new double[1]; _accumulatedFrameTime = new double[1]; _previousFrameTime = new double[1]; @@ -165,7 +165,7 @@ namespace Ryujinx.HLE { return 1000 / _frameRate[FrameTypeGame]; } - + public string FormatFifoPercent() { double fifoPercent = GetFifoPercent(); diff --git a/src/Ryujinx.HLE/Ryujinx.HLE.csproj b/src/Ryujinx.HLE/Ryujinx.HLE.csproj index f551f1a18..5139d9276 100644 --- a/src/Ryujinx.HLE/Ryujinx.HLE.csproj +++ b/src/Ryujinx.HLE/Ryujinx.HLE.csproj @@ -23,7 +23,7 @@ - + diff --git a/src/Ryujinx.HLE/StructHelpers.cs b/src/Ryujinx.HLE/StructHelpers.cs index a9a00c2d7..dc9c6d727 100644 --- a/src/Ryujinx.HLE/StructHelpers.cs +++ b/src/Ryujinx.HLE/StructHelpers.cs @@ -1,4 +1,4 @@ -using LibHac.Common; +using LibHac.Common; using LibHac.Ns; using System; using System.Text; @@ -11,13 +11,13 @@ namespace Ryujinx.HLE { // https://switchbrew.org/wiki/NACP const int OffsetOfDisplayVersion = 0x3060; - + // https://switchbrew.org/wiki/NACP#ApplicationTitle const int TotalApplicationTitles = 0x10; const int SizeOfApplicationTitle = 0x300; const int OffsetOfApplicationPublisherStrings = 0x200; - - + + BlitStruct nacpData = new(1); // name and publisher buffer @@ -27,7 +27,7 @@ namespace Ryujinx.HLE Encoding.ASCII.GetBytes(name).AsSpan().CopyTo(nacpData.ByteSpan[(i * SizeOfApplicationTitle)..]); "Ryujinx"u8.CopyTo(nacpData.ByteSpan[(i * SizeOfApplicationTitle + OffsetOfApplicationPublisherStrings)..]); } - + // version buffer Encoding.ASCII.GetBytes(version).AsSpan().CopyTo(nacpData.ByteSpan[OffsetOfDisplayVersion..]); diff --git a/src/Ryujinx.HLE/Switch.cs b/src/Ryujinx.HLE/Switch.cs index e52b3df15..bdcbe82c7 100644 --- a/src/Ryujinx.HLE/Switch.cs +++ b/src/Ryujinx.HLE/Switch.cs @@ -20,7 +20,7 @@ namespace Ryujinx.HLE public class Switch : IDisposable { public static Switch Shared { get; private set; } - + public HleConfiguration Configuration { get; } public IHardwareDeviceDriver AudioDeviceDriver { get; } public MemoryBlock Memory { get; } @@ -35,7 +35,7 @@ namespace Ryujinx.HLE get => System?.TickSource?.TickScalar ?? ITickSource.RealityTickScalar; set => System.TickSource.TickScalar = value; } - + public ProcessLoader Processes { get; } public PerformanceStatistics Statistics { get; } public Hid Hid { get; } diff --git a/src/Ryujinx.HLE/UI/IHostUIHandler.cs b/src/Ryujinx.HLE/UI/IHostUIHandler.cs index 3748eef39..b5c5cb168 100644 --- a/src/Ryujinx.HLE/UI/IHostUIHandler.cs +++ b/src/Ryujinx.HLE/UI/IHostUIHandler.cs @@ -62,8 +62,8 @@ namespace Ryujinx.HLE.UI /// Gets fonts and colors used by the host. ///
IHostUITheme HostUITheme { get; } - - + + /// /// Displays the player select dialog and returns the selected profile. /// diff --git a/src/Ryujinx.HLE/Utilities/PartitionFileSystemUtils.cs b/src/Ryujinx.HLE/Utilities/PartitionFileSystemUtils.cs index 671bcaa06..e65fac438 100644 --- a/src/Ryujinx.HLE/Utilities/PartitionFileSystemUtils.cs +++ b/src/Ryujinx.HLE/Utilities/PartitionFileSystemUtils.cs @@ -16,7 +16,7 @@ namespace Ryujinx.HLE.Utilities IFileSystem partitionFileSystem; - if (Path.GetExtension(path).ToLower() == ".xci") + if (Path.GetExtension(path).Equals(".xci", System.StringComparison.OrdinalIgnoreCase)) { partitionFileSystem = new Xci(fileSystem.KeySet, file.AsStorage()).OpenPartition(XciPartitionType.Secure); } diff --git a/src/Ryujinx.Horizon.Common/ResultNames.cs b/src/Ryujinx.Horizon.Common/ResultNames.cs index 25d04b308..15e372c35 100644 --- a/src/Ryujinx.Horizon.Common/ResultNames.cs +++ b/src/Ryujinx.Horizon.Common/ResultNames.cs @@ -1,11 +1,12 @@ using System.Collections.Generic; +using System.Collections.ObjectModel; namespace Ryujinx.Horizon.Common { static class ResultNames { // Reference: https://github.com/Thealexbarney/LibHac/blob/master/build/CodeGen/results.csv - private static readonly IReadOnlyDictionary _names = new Dictionary() + private static readonly ReadOnlyDictionary _names = new Dictionary() { { 0x0, "Success" }, { 0xE01, "OutOfSessions" }, @@ -1691,7 +1692,7 @@ namespace Ryujinx.Horizon.Common { 0x823AC, "InvalidPackage1SectionSize" }, { 0x825AC, "InvalidPackage1MarikoBodySize" }, { 0x827AC, "InvalidPackage1Pk11Size" }, - }; + }.AsReadOnly(); public static bool TryGet(int errorCode, out string name) { diff --git a/src/Ryujinx.Horizon.Generators/Hipc/HipcGenerator.cs b/src/Ryujinx.Horizon.Generators/Hipc/HipcGenerator.cs index b68e05681..2786c45aa 100644 --- a/src/Ryujinx.Horizon.Generators/Hipc/HipcGenerator.cs +++ b/src/Ryujinx.Horizon.Generators/Hipc/HipcGenerator.cs @@ -102,7 +102,7 @@ namespace Ryujinx.Horizon.Generators.Hipc private static string GetNamespaceName(SyntaxNode syntaxNode) { - while (syntaxNode != null && !(syntaxNode is NamespaceDeclarationSyntax)) + while (syntaxNode is not null and not NamespaceDeclarationSyntax) { syntaxNode = syntaxNode.Parent; } @@ -162,7 +162,7 @@ namespace Ryujinx.Horizon.Generators.Hipc arg = $"new CommandArg({bufferFlags})"; } } - else if (argType == CommandArgType.InArgument || argType == CommandArgType.OutArgument) + else if (argType is CommandArgType.InArgument or CommandArgType.OutArgument) { string alignment = GetTypeAlignmentExpression(compilation, parameter.Type); @@ -353,6 +353,7 @@ namespace Ryujinx.Horizon.Generators.Hipc value = $"CommandSerialization.GetRef<{canonicalTypeName}>(processor.GetBufferRange({index}))"; isNonSpanBuffer = true; } + break; } @@ -470,7 +471,7 @@ namespace Ryujinx.Horizon.Generators.Hipc { if (outObjectsCount != 0) { - generator.AppendLine($"processor.SetOutObjects(ref context, {ResponseVariableName}, {OutObjectsVariableName});"); + generator.AppendLine($"HipcCommandProcessor.SetOutObjects(ref context, {ResponseVariableName}, {OutObjectsVariableName});"); } if (buffersCount != 0) diff --git a/src/Ryujinx.Horizon.Kernel.Generators/SyscallGenerator.cs b/src/Ryujinx.Horizon.Kernel.Generators/SyscallGenerator.cs index b4063eda2..2a09001db 100644 --- a/src/Ryujinx.Horizon.Kernel.Generators/SyscallGenerator.cs +++ b/src/Ryujinx.Horizon.Kernel.Generators/SyscallGenerator.cs @@ -492,12 +492,12 @@ namespace Ryujinx.Horizon.Kernel.Generators private static bool Is32BitInteger(string canonicalTypeName) { - return canonicalTypeName == TypeSystemInt32 || canonicalTypeName == TypeSystemUInt32; + return canonicalTypeName is TypeSystemInt32 or TypeSystemUInt32; } private static bool Is64BitInteger(string canonicalTypeName) { - return canonicalTypeName == TypeSystemInt64 || canonicalTypeName == TypeSystemUInt64; + return canonicalTypeName is TypeSystemInt64 or TypeSystemUInt64; } private static string GenerateCastFromUInt64(string value, string canonicalTargetTypeName, string targetTypeName) diff --git a/src/Ryujinx.Horizon.Kernel.Generators/SyscallSyntaxReceiver.cs b/src/Ryujinx.Horizon.Kernel.Generators/SyscallSyntaxReceiver.cs index abeea4020..1351bdfeb 100644 --- a/src/Ryujinx.Horizon.Kernel.Generators/SyscallSyntaxReceiver.cs +++ b/src/Ryujinx.Horizon.Kernel.Generators/SyscallSyntaxReceiver.cs @@ -16,7 +16,7 @@ namespace Ryujinx.Horizon.Kernel.Generators public void OnVisitSyntaxNode(SyntaxNode syntaxNode) { - if (!(syntaxNode is ClassDeclarationSyntax classDeclaration) || classDeclaration.AttributeLists.Count == 0) + if (syntaxNode is not ClassDeclarationSyntax classDeclaration || classDeclaration.AttributeLists.Count == 0) { return; } diff --git a/src/Ryujinx.Horizon/HorizonStatic.cs b/src/Ryujinx.Horizon/HorizonStatic.cs index a936a5a2d..b0343a2cd 100644 --- a/src/Ryujinx.Horizon/HorizonStatic.cs +++ b/src/Ryujinx.Horizon/HorizonStatic.cs @@ -8,14 +8,14 @@ namespace Ryujinx.Horizon { public static class HorizonStatic { - internal static void HandlePlayReport(PlayReport report) => + internal static void HandlePlayReport(PlayReport report) => new Thread(() => PlayReport?.Invoke(report)) { - Name = "HLE.PlayReportEvent", + Name = "HLE.PlayReportEvent", IsBackground = true, Priority = ThreadPriority.AboveNormal }.Start(); - + public static event Action PlayReport; [field: ThreadStatic] diff --git a/src/Ryujinx.Horizon/Prepo/Ipc/PrepoService.cs b/src/Ryujinx.Horizon/Prepo/Ipc/PrepoService.cs index 0ca851e6e..8336adb18 100644 --- a/src/Ryujinx.Horizon/Prepo/Ipc/PrepoService.cs +++ b/src/Ryujinx.Horizon/Prepo/Ipc/PrepoService.cs @@ -131,7 +131,7 @@ namespace Ryujinx.Horizon.Prepo.Ipc { enabled = false; - if (_permissionLevel == PrepoServicePermissionLevel.User || _permissionLevel == PrepoServicePermissionLevel.System) + if (_permissionLevel is PrepoServicePermissionLevel.User or PrepoServicePermissionLevel.System) { enabled = _userAgreementCheckEnabled; @@ -148,7 +148,7 @@ namespace Ryujinx.Horizon.Prepo.Ipc [CmifCommand(40101)] // 2.0.0+ public Result SetUserAgreementCheckEnabled(bool enabled) { - if (_permissionLevel == PrepoServicePermissionLevel.User || _permissionLevel == PrepoServicePermissionLevel.System) + if (_permissionLevel is PrepoServicePermissionLevel.User or PrepoServicePermissionLevel.System) { _userAgreementCheckEnabled = enabled; @@ -188,17 +188,17 @@ namespace Ryujinx.Horizon.Prepo.Ipc { return PrepoResult.InvalidBufferSize; } - + StringBuilder builder = new(); MessagePackObject deserializedReport = MessagePackSerializer.UnpackMessagePackObject(reportBuffer.ToArray()); PlayReport playReport = new() { - Kind = playReportKind, + Kind = playReportKind, Room = gameRoom, ReportData = deserializedReport }; - + builder.AppendLine(); builder.AppendLine("PlayReport log:"); builder.AppendLine($" Kind: {playReportKind}"); @@ -225,7 +225,7 @@ namespace Ryujinx.Horizon.Prepo.Ipc _arp.GetApplicationLaunchProperty(out ApplicationLaunchProperty applicationLaunchProperty, applicationInstanceId).AbortOnFailure(); playReport.Version = applicationLaunchProperty.Version; - + builder.AppendLine($" ApplicationVersion: {applicationLaunchProperty.Version}"); if (!userId.IsNull) @@ -236,7 +236,7 @@ namespace Ryujinx.Horizon.Prepo.Ipc builder.AppendLine($" Room: {gameRoom}"); builder.AppendLine($" Report: {MessagePackObjectFormatter.Format(deserializedReport)}"); - + HorizonStatic.HandlePlayReport(playReport); Logger.Info?.Print(LogClass.ServicePrepo, builder.ToString()); diff --git a/src/Ryujinx.Horizon/Prepo/Types/PlayReport.cs b/src/Ryujinx.Horizon/Prepo/Types/PlayReport.cs index e896219d5..54106eaea 100644 --- a/src/Ryujinx.Horizon/Prepo/Types/PlayReport.cs +++ b/src/Ryujinx.Horizon/Prepo/Types/PlayReport.cs @@ -1,4 +1,4 @@ -using MsgPack; +using MsgPack; using Ryujinx.Horizon.Sdk.Account; using Ryujinx.Horizon.Sdk.Ncm; @@ -9,13 +9,13 @@ namespace Ryujinx.Horizon.Prepo.Types public PlayReportKind Kind { get; init; } public string Room { get; init; } public MessagePackObject ReportData { get; init; } - + public ApplicationId? AppId; public ulong? Pid; public uint Version; public Uid? UserId; } - + public enum PlayReportKind { Normal, diff --git a/src/Ryujinx.Horizon/Ryujinx.Horizon.csproj b/src/Ryujinx.Horizon/Ryujinx.Horizon.csproj index 727513484..5ee37b7fa 100644 --- a/src/Ryujinx.Horizon/Ryujinx.Horizon.csproj +++ b/src/Ryujinx.Horizon/Ryujinx.Horizon.csproj @@ -14,6 +14,6 @@ - + diff --git a/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioDevice.cs b/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioDevice.cs index 2d3aa7ba9..583a04de3 100644 --- a/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioDevice.cs +++ b/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioDevice.cs @@ -121,7 +121,7 @@ namespace Ryujinx.Horizon.Sdk.Audio.Detail if (!_isUsbDeviceSupported && device.IsUsbDevice()) { - device = _registry.DefaultDevice; + device = VirtualDeviceSessionRegistry.DefaultDevice; } if (name.Length > 0) @@ -147,7 +147,7 @@ namespace Ryujinx.Horizon.Sdk.Audio.Detail if (!_isUsbDeviceSupported && device.IsUsbDevice()) { - device = _registry.DefaultDevice; + device = VirtualDeviceSessionRegistry.DefaultDevice; } channelCount = (int)device.ChannelCount; diff --git a/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioInManager.cs b/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioInManager.cs index b190cb8ae..64394b251 100644 --- a/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioInManager.cs +++ b/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioInManager.cs @@ -22,7 +22,7 @@ namespace Ryujinx.Horizon.Sdk.Audio.Detail [CmifCommand(0)] public Result ListAudioIns(out int count, [Buffer(HipcBufferFlags.Out | HipcBufferFlags.MapAlias)] Span names) { - string[] deviceNames = _impl.ListAudioIns(filtered: false); + string[] deviceNames = AudioInputManager.ListAudioIns(filtered: false); count = 0; @@ -94,7 +94,7 @@ namespace Ryujinx.Horizon.Sdk.Audio.Detail [CmifCommand(4)] // 3.0.0+ public Result ListAudioInsAutoFiltered(out int count, [Buffer(HipcBufferFlags.Out | HipcBufferFlags.AutoSelect)] Span names) { - string[] deviceNames = _impl.ListAudioIns(filtered: true); + string[] deviceNames = AudioInputManager.ListAudioIns(filtered: true); count = 0; diff --git a/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioOutManager.cs b/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioOutManager.cs index facfbbc03..37e51b042 100644 --- a/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioOutManager.cs +++ b/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioOutManager.cs @@ -22,7 +22,7 @@ namespace Ryujinx.Horizon.Sdk.Audio.Detail [CmifCommand(0)] public Result ListAudioOuts(out int count, [Buffer(HipcBufferFlags.Out | HipcBufferFlags.MapAlias)] Span names) { - string[] deviceNames = _impl.ListAudioOuts(); + string[] deviceNames = AudioOutputManager.ListAudioOuts(); count = 0; diff --git a/src/Ryujinx.Horizon/Sdk/Codec/Detail/HardwareOpusDecoderManager.cs b/src/Ryujinx.Horizon/Sdk/Codec/Detail/HardwareOpusDecoderManager.cs index d74e50a61..9c981b765 100644 --- a/src/Ryujinx.Horizon/Sdk/Codec/Detail/HardwareOpusDecoderManager.cs +++ b/src/Ryujinx.Horizon/Sdk/Codec/Detail/HardwareOpusDecoderManager.cs @@ -229,7 +229,7 @@ namespace Ryujinx.Horizon.Sdk.Codec.Detail return GetWorkBufferSizeForMultiStreamExImpl(out size, in parameter, fromDsp: true); } - private Result GetWorkBufferSizeExImpl(out int size, in HardwareOpusDecoderParameterInternalEx parameter, bool fromDsp) + private static Result GetWorkBufferSizeExImpl(out int size, in HardwareOpusDecoderParameterInternalEx parameter, bool fromDsp) { size = 0; @@ -253,7 +253,7 @@ namespace Ryujinx.Horizon.Sdk.Codec.Detail return Result.Success; } - private Result GetWorkBufferSizeForMultiStreamExImpl(out int size, in HardwareOpusMultiStreamDecoderParameterInternalEx parameter, bool fromDsp) + private static Result GetWorkBufferSizeForMultiStreamExImpl(out int size, in HardwareOpusMultiStreamDecoderParameterInternalEx parameter, bool fromDsp) { size = 0; @@ -305,7 +305,7 @@ namespace Ryujinx.Horizon.Sdk.Codec.Detail { const int SilkDecoderSize = 0x2160; - if (channelsCount < 1 || channelsCount > 2) + if (channelsCount is < 1 or > 2) { return 0; } @@ -351,12 +351,12 @@ namespace Ryujinx.Horizon.Sdk.Codec.Detail private static bool IsValidChannelCount(int channelsCount) { - return channelsCount > 0 && channelsCount <= 2; + return channelsCount is > 0 and <= 2; } private static bool IsValidMultiChannelCount(int channelsCount) { - return channelsCount > 0 && channelsCount <= 255; + return channelsCount is > 0 and <= 255; } private static bool IsValidSampleRate(int sampleRate) diff --git a/src/Ryujinx.Horizon/Sdk/Ngc/Detail/ContentsReader.cs b/src/Ryujinx.Horizon/Sdk/Ngc/Detail/ContentsReader.cs index d3ed37e78..0f84a2c62 100644 --- a/src/Ryujinx.Horizon/Sdk/Ngc/Detail/ContentsReader.cs +++ b/src/Ryujinx.Horizon/Sdk/Ngc/Detail/ContentsReader.cs @@ -47,6 +47,7 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail { path = $"{MountName}:/ac_{regionIndex}_not_b_nx"; } + break; case AcType.AcB1: if (regionIndex < 0) @@ -57,6 +58,7 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail { path = $"{MountName}:/ac_{regionIndex}_b1_nx"; } + break; case AcType.AcB2: if (regionIndex < 0) @@ -67,6 +69,7 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail { path = $"{MountName}:/ac_{regionIndex}_b2_nx"; } + break; case AcType.AcSimilarForm: path = $"{MountName}:/ac_similar_form_nx"; diff --git a/src/Ryujinx.Horizon/Sdk/Ngc/Detail/ProfanityFilterBase.cs b/src/Ryujinx.Horizon/Sdk/Ngc/Detail/ProfanityFilterBase.cs index 9f3c6b449..3046be228 100644 --- a/src/Ryujinx.Horizon/Sdk/Ngc/Detail/ProfanityFilterBase.cs +++ b/src/Ryujinx.Horizon/Sdk/Ngc/Detail/ProfanityFilterBase.cs @@ -8,7 +8,6 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail { abstract class ProfanityFilterBase { -#pragma warning disable IDE0230 // Use UTF-8 string literal private static readonly byte[][] _wordSeparators = [ [0x0D], @@ -92,7 +91,6 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail [0xEF, 0xBC, 0x8D], [0xEF, 0xBC, 0xBD] ]; -#pragma warning restore IDE0230 private enum SignFilterStep { @@ -115,7 +113,7 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail { break; } - else if (word[index] == '@' || word[index] == '\uFF20') + else if (word[index] is '@' or '\uFF20') { return true; } @@ -142,6 +140,7 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail step = SignFilterStep.DetectEmailUserAtSign; matchStart = index; } + break; case SignFilterStep.DetectEmailUserAtSign: bool hasMatch = false; @@ -205,6 +204,7 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail { index = domainIndex - 1; } + break; } } @@ -232,7 +232,7 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail text[startOffset] = 0xc1; text[startOffset + 1] = 0xc1; } - else if (maskMode == MaskMode.Overwrite || maskMode == MaskMode.ReplaceByOneCharacter) + else if (maskMode is MaskMode.Overwrite or MaskMode.ReplaceByOneCharacter) { text[startOffset] = 0xc0; text[startOffset + 1] = 0xc0; @@ -312,7 +312,7 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail } else if ((character & 0x80) != 0) { - if (character >= 0xc2 && character < 0xe0) + if (character is >= 0xc2 and < 0xe0) { characterByteLength = 2; } @@ -621,7 +621,7 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail if ((character & 0x80) != 0) { - if (character >= 0xc2 && character < 0xe0) + if (character is >= 0xc2 and < 0xe0) { characterByteLength = 2; } @@ -751,7 +751,7 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail if ((character & 0x80) != 0 || character == 0) { - if (character >= 0xc2 && character < 0xe0) + if (character is >= 0xc2 and < 0xe0) { characterByteLength = 2; } diff --git a/src/Ryujinx.Horizon/Sdk/OsTypes/Impl/InterProcessEvent.cs b/src/Ryujinx.Horizon/Sdk/OsTypes/Impl/InterProcessEvent.cs index 4da4ee86c..c45239b14 100644 --- a/src/Ryujinx.Horizon/Sdk/OsTypes/Impl/InterProcessEvent.cs +++ b/src/Ryujinx.Horizon/Sdk/OsTypes/Impl/InterProcessEvent.cs @@ -33,6 +33,7 @@ namespace Ryujinx.Horizon.Sdk.OsTypes.Impl { InterProcessEventImpl.Close(ipEvent.ReadableHandle); } + ipEvent.ReadableHandleManaged = false; } @@ -42,6 +43,7 @@ namespace Ryujinx.Horizon.Sdk.OsTypes.Impl { InterProcessEventImpl.Close(ipEvent.WritableHandle); } + ipEvent.WritableHandleManaged = false; } } diff --git a/src/Ryujinx.Horizon/Sdk/OsTypes/Impl/MultiWaitImpl.cs b/src/Ryujinx.Horizon/Sdk/OsTypes/Impl/MultiWaitImpl.cs index 2fbcfdc88..d723e5322 100644 --- a/src/Ryujinx.Horizon/Sdk/OsTypes/Impl/MultiWaitImpl.cs +++ b/src/Ryujinx.Horizon/Sdk/OsTypes/Impl/MultiWaitImpl.cs @@ -124,6 +124,7 @@ namespace Ryujinx.Horizon.Sdk.OsTypes.Impl { return null; } + break; case WaitCancelled: lock (_lock) @@ -133,6 +134,7 @@ namespace Ryujinx.Horizon.Sdk.OsTypes.Impl return _signaledHolder; } } + break; default: lock (_lock) diff --git a/src/Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchTableBase.cs b/src/Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchTableBase.cs index f2292feff..df1472560 100644 --- a/src/Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchTableBase.cs +++ b/src/Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchTableBase.cs @@ -62,8 +62,8 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif Result commandResult = commandHandler.Invoke(ref outHeader, ref context, inMessageRawData); - if (commandResult.Module == SfResult.ModuleId || - commandResult.Module == HipcResult.ModuleId) + if (commandResult.Module is SfResult.ModuleId or + HipcResult.ModuleId) { Logger.Warning?.Print(LogClass.KernelIpc, $"{commandHandler.MethodName} returned error {commandResult}"); } diff --git a/src/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerSessionManager.cs b/src/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerSessionManager.cs index f51e0811e..ca13e611e 100644 --- a/src/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerSessionManager.cs +++ b/src/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerSessionManager.cs @@ -206,6 +206,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc { return MemoryMarshal.Cast(inMessage)[3]; } + break; } diff --git a/src/Ryujinx.Horizon/Sdk/Sf/HipcCommandProcessor.cs b/src/Ryujinx.Horizon/Sdk/Sf/HipcCommandProcessor.cs index b553115eb..ec0acbdea 100644 --- a/src/Ryujinx.Horizon/Sdk/Sf/HipcCommandProcessor.cs +++ b/src/Ryujinx.Horizon/Sdk/Sf/HipcCommandProcessor.cs @@ -82,6 +82,7 @@ namespace Ryujinx.Horizon.Sdk.Sf _outMapAliasBuffersCount++; } } + break; case CommandArgType.InCopyHandle: _inCopyHandlesCount++; @@ -386,9 +387,7 @@ namespace Ryujinx.Horizon.Sdk.Sf outRawData = MemoryMarshal.Cast(response.DataWords); } -#pragma warning disable CA1822 // Mark member as static - public void SetOutObjects(ref ServiceDispatchContext context, HipcMessageData response, Span objects) -#pragma warning restore CA1822 + public static void SetOutObjects(ref ServiceDispatchContext context, HipcMessageData response, Span objects) { if (objects.Length == 0) { diff --git a/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs b/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs index 6f1b79d38..4b868efeb 100644 --- a/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs +++ b/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs @@ -86,7 +86,7 @@ namespace Ryujinx.Input.SDL2 Id = driverId; Features = GetFeaturesFlag(); _triggerThreshold = 0.0f; - + // Enable motion tracking if (Features.HasFlag(GamepadFeaturesFlag.Motion)) { @@ -104,12 +104,13 @@ namespace Ryujinx.Input.SDL2 public void SetLed(uint packedRgb) { - if (!Features.HasFlag(GamepadFeaturesFlag.Led)) return; + if (!Features.HasFlag(GamepadFeaturesFlag.Led)) + return; byte red = packedRgb > 0 ? (byte)(packedRgb >> 16) : (byte)0; byte green = packedRgb > 0 ? (byte)(packedRgb >> 8) : (byte)0; byte blue = packedRgb > 0 ? (byte)(packedRgb % 256) : (byte)0; - + if (SDL_GameControllerSetLED(_gamepadHandle, red, green, blue) != 0) Logger.Debug?.Print(LogClass.Hid, "LED setting failed; probably in the middle of disconnecting."); } @@ -155,6 +156,7 @@ namespace Ryujinx.Input.SDL2 public void Dispose() { Dispose(true); + GC.SuppressFinalize(this); } public void SetTriggerThreshold(float triggerThreshold) @@ -223,7 +225,7 @@ namespace Ryujinx.Input.SDL2 private static Vector3 RadToDegree(Vector3 rad) => rad * (180 / MathF.PI); private static Vector3 GsToMs2(Vector3 gs) => gs / SDL_STANDARD_GRAVITY; - + public void SetConfiguration(InputConfig configuration) { lock (_userMappingLock) @@ -236,11 +238,11 @@ namespace Ryujinx.Input.SDL2 (this as IGamepad).ClearLed(); else if (_configuration.Led.UseRainbow) SetLed((uint)Rainbow.Color.ToArgb()); - + if (!_configuration.Led.TurnOffLed && !_configuration.Led.UseRainbow) SetLed(_configuration.Led.LedColor); } - + _buttonsUserMapping.Clear(); // First update sticks @@ -290,7 +292,6 @@ namespace Ryujinx.Input.SDL2 if (_buttonsUserMapping.Count == 0) return rawState; - // ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator foreach (ButtonMappingEntry entry in _buttonsUserMapping) { @@ -336,6 +337,7 @@ namespace Ryujinx.Input.SDL2 else return _configuration.RightJoyconStick; } + return null; } diff --git a/src/Ryujinx.Input.SDL2/SDL2GamepadDriver.cs b/src/Ryujinx.Input.SDL2/SDL2GamepadDriver.cs index dfcc9e213..5b3756fb6 100644 --- a/src/Ryujinx.Input.SDL2/SDL2GamepadDriver.cs +++ b/src/Ryujinx.Input.SDL2/SDL2GamepadDriver.cs @@ -60,7 +60,7 @@ namespace Ryujinx.Input.SDL2 } // Remove the first 4 char of the guid (CRC part) to make it stable - string guidString = "0000" + guid.ToString().Substring(4); + string guidString = $"0000{guid.ToString()[4..]}"; string id; @@ -89,7 +89,7 @@ namespace Ryujinx.Input.SDL2 private void HandleJoyStickDisconnected(int joystickInstanceId) { bool joyConPairDisconnected = false; - + if (!_gamepadsInstanceIdsMapping.Remove(joystickInstanceId, out string id)) return; @@ -113,7 +113,7 @@ namespace Ryujinx.Input.SDL2 private void HandleJoyStickConnected(int joystickDeviceId, int joystickInstanceId) { bool joyConPairConnected = false; - + if (SDL_IsGameController(joystickDeviceId) == SDL_bool.SDL_TRUE) { if (_gamepadsInstanceIdsMapping.ContainsKey(joystickInstanceId)) @@ -138,7 +138,7 @@ namespace Ryujinx.Input.SDL2 _gamepadsIds.Insert(joystickDeviceId, id); else _gamepadsIds.Add(id); - + if (SDL2JoyConPair.IsCombinable(_gamepadsIds)) { _gamepadsIds.Remove(SDL2JoyConPair.Id); @@ -155,14 +155,13 @@ namespace Ryujinx.Input.SDL2 } } } - + private void HandleJoyBatteryUpdated(int joystickDeviceId, SDL_JoystickPowerLevel powerLevel) { Logger.Info?.Print(LogClass.Hid, $"{SDL_GameControllerNameForIndex(joystickDeviceId)} power level: {powerLevel}"); } - protected virtual void Dispose(bool disposing) { if (disposing) @@ -200,7 +199,7 @@ namespace Ryujinx.Input.SDL2 return SDL2JoyConPair.GetGamepad(_gamepadsIds); } } - + int joystickIndex = GetJoystickIndexByGamepadId(id); if (joystickIndex == -1) @@ -214,10 +213,10 @@ namespace Ryujinx.Input.SDL2 { return null; } - + if (SDL_GameControllerName(gamepadHandle).StartsWith(SDL2JoyCon.Prefix)) { - return new SDL2JoyCon(gamepadHandle, id); + return new SDL2JoyCon(gamepadHandle, id); } return new SDL2Gamepad(gamepadHandle, id); diff --git a/src/Ryujinx.Input.SDL2/SDL2JoyCon.cs b/src/Ryujinx.Input.SDL2/SDL2JoyCon.cs index 246a9ed8d..0c00c1899 100644 --- a/src/Ryujinx.Input.SDL2/SDL2JoyCon.cs +++ b/src/Ryujinx.Input.SDL2/SDL2JoyCon.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Configuration.Hid; +using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid.Controller; using Ryujinx.Common.Logging; using System; @@ -20,7 +20,7 @@ namespace Ryujinx.Input.SDL2 private StandardControllerInputConfig _configuration; - private readonly Dictionary _leftButtonsDriverMapping = new() + private readonly Dictionary _leftButtonsDriverMapping = new() { { GamepadButtonInputId.LeftStick , SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_LEFTSTICK }, {GamepadButtonInputId.DpadUp ,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_Y}, @@ -33,7 +33,7 @@ namespace Ryujinx.Input.SDL2 {GamepadButtonInputId.SingleRightTrigger0,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}, {GamepadButtonInputId.SingleLeftTrigger0,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, }; - private readonly Dictionary _rightButtonsDriverMapping = new() + private readonly Dictionary _rightButtonsDriverMapping = new() { {GamepadButtonInputId.RightStick,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_LEFTSTICK}, {GamepadButtonInputId.A,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_B}, @@ -155,7 +155,6 @@ namespace Ryujinx.Input.SDL2 Dispose(true); } - public void SetTriggerThreshold(float triggerThreshold) { @@ -212,7 +211,8 @@ namespace Ryujinx.Input.SDL2 Vector3 value = _joyConType switch { JoyConType.Left => new Vector3(-values[2], values[1], values[0]), - JoyConType.Right => new Vector3(values[2], values[1], -values[0]) + JoyConType.Right => new Vector3(values[2], values[1], -values[0]), + _ => throw new NotSupportedException($"Unsupported JoyCon type: {_joyConType}") }; return inputId switch @@ -240,7 +240,6 @@ namespace Ryujinx.Input.SDL2 _stickUserMapping[(int)StickInputId.Left] = (StickInputId)_configuration.LeftJoyconStick.Joystick; _stickUserMapping[(int)StickInputId.Right] = (StickInputId)_configuration.RightJoyconStick.Joystick; - switch (_joyConType) { case JoyConType.Left: @@ -268,9 +267,9 @@ namespace Ryujinx.Input.SDL2 _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger1, (GamepadButtonInputId)_configuration.RightJoycon.ButtonSl)); break; default: - throw new ArgumentOutOfRangeException(); + throw new NotSupportedException($"Unsupported JoyCon type: {_joyConType}"); } - + SetTriggerThreshold(_configuration.TriggerThreshold); } } @@ -294,7 +293,6 @@ namespace Ryujinx.Input.SDL2 if (_buttonsUserMapping.Count == 0) return rawState; - // ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator foreach (ButtonMappingEntry entry in _buttonsUserMapping) { @@ -318,7 +316,6 @@ namespace Ryujinx.Input.SDL2 return result; } - private static float ConvertRawStickValue(short value) { const float ConvertRate = 1.0f / (short.MaxValue + 0.5f); @@ -348,7 +345,6 @@ namespace Ryujinx.Input.SDL2 return null; } - public (float, float) GetStick(StickInputId inputId) { if (inputId == StickInputId.Unbound) @@ -358,7 +354,7 @@ namespace Ryujinx.Input.SDL2 { return (0.0f, 0.0f); } - + (short stickX, short stickY) = GetStickXY(); float resultX = ConvertRawStickValue(stickX); @@ -399,7 +395,7 @@ namespace Ryujinx.Input.SDL2 SDL_GameControllerGetAxis(_gamepadHandle, SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_LEFTX), SDL_GameControllerGetAxis(_gamepadHandle, SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_LEFTY)); } - + public bool IsPressed(GamepadButtonInputId inputId) { if (!_buttonsDriverMapping.TryGetValue(inputId, out var button)) diff --git a/src/Ryujinx.Input.SDL2/SDL2JoyConPair.cs b/src/Ryujinx.Input.SDL2/SDL2JoyConPair.cs index e3280ccb4..a1e13aa45 100644 --- a/src/Ryujinx.Input.SDL2/SDL2JoyConPair.cs +++ b/src/Ryujinx.Input.SDL2/SDL2JoyConPair.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Configuration.Hid; +using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid.Controller; using System; using System.Collections.Generic; @@ -10,15 +10,6 @@ namespace Ryujinx.Input.SDL2 { internal class SDL2JoyConPair(IGamepad left, IGamepad right) : IGamepad { - private StandardControllerInputConfig _configuration; - - private readonly StickInputId[] _stickUserMapping = - [ - StickInputId.Unbound, - StickInputId.Left, - StickInputId.Right - ]; - public GamepadFeaturesFlag Features => (left?.Features ?? GamepadFeaturesFlag.None) | (right?.Features ?? GamepadFeaturesFlag.None); @@ -138,7 +129,6 @@ namespace Ryujinx.Input.SDL2 return null; } - return new SDL2JoyConPair(new SDL2JoyCon(leftGamepadHandle, gamepadsIds[leftIndex]), new SDL2JoyCon(rightGamepadHandle, gamepadsIds[rightIndex])); } diff --git a/src/Ryujinx.Input.SDL2/SDL2Keyboard.cs b/src/Ryujinx.Input.SDL2/SDL2Keyboard.cs index 6f4f839a5..1cbf4d35c 100644 --- a/src/Ryujinx.Input.SDL2/SDL2Keyboard.cs +++ b/src/Ryujinx.Input.SDL2/SDL2Keyboard.cs @@ -195,7 +195,7 @@ namespace Ryujinx.Input.SDL2 [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int ToSDL2Scancode(Key key) { - if (key >= Key.Unknown && key <= Key.Menu) + if (key is >= Key.Unknown and <= Key.Menu) { return -1; } diff --git a/src/Ryujinx.Input.SDL2/SDL2MouseDriver.cs b/src/Ryujinx.Input.SDL2/SDL2MouseDriver.cs index 7a9679901..a1f6c1d7b 100644 --- a/src/Ryujinx.Input.SDL2/SDL2MouseDriver.cs +++ b/src/Ryujinx.Input.SDL2/SDL2MouseDriver.cs @@ -106,7 +106,7 @@ namespace Ryujinx.Input.SDL2 case SDL_EventType.SDL_MOUSEBUTTONUP: uint rawButton = evnt.button.button; - if (rawButton > 0 && rawButton <= (int)MouseButton.Count) + if (rawButton is > 0 and <= ((int)MouseButton.Count)) { PressedButtons[(int)DriverButtonToMouseButton(rawButton)] = evnt.type == SDL_EventType.SDL_MOUSEBUTTONDOWN; diff --git a/src/Ryujinx.Input/GamepadFeaturesFlag.cs b/src/Ryujinx.Input/GamepadFeaturesFlag.cs index 52e8519d1..8d3cda426 100644 --- a/src/Ryujinx.Input/GamepadFeaturesFlag.cs +++ b/src/Ryujinx.Input/GamepadFeaturesFlag.cs @@ -24,7 +24,7 @@ namespace Ryujinx.Input /// Also named sixaxis ///
Motion, - + /// /// The LED on the back of modern PlayStation controllers (DualSense & DualShock 4). /// diff --git a/src/Ryujinx.Input/GamepadStateSnapshot.cs b/src/Ryujinx.Input/GamepadStateSnapshot.cs index ed1bf5fe8..bf38b7c8a 100644 --- a/src/Ryujinx.Input/GamepadStateSnapshot.cs +++ b/src/Ryujinx.Input/GamepadStateSnapshot.cs @@ -32,7 +32,6 @@ namespace Ryujinx.Input [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsPressed(GamepadButtonInputId inputId) => _buttonsState[(int)inputId]; - /// /// Set the state of a given button. /// diff --git a/src/Ryujinx.Input/IGamepadDriver.cs b/src/Ryujinx.Input/IGamepadDriver.cs index 25b2295db..50548c979 100644 --- a/src/Ryujinx.Input/IGamepadDriver.cs +++ b/src/Ryujinx.Input/IGamepadDriver.cs @@ -34,7 +34,7 @@ namespace Ryujinx.Input /// The unique id of the gamepad /// An instance of associated to the gamepad id given or null if not found IGamepad GetGamepad(string id); - + /// /// Returns an of the connected gamepads. /// diff --git a/src/Ryujinx.Input/Motion/CemuHook/Client.cs b/src/Ryujinx.Input/Motion/CemuHook/Client.cs index d07ae6431..21e31a76e 100644 --- a/src/Ryujinx.Input/Motion/CemuHook/Client.cs +++ b/src/Ryujinx.Input/Motion/CemuHook/Client.cs @@ -1,3 +1,4 @@ +using Microsoft.IO; using Ryujinx.Common; using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid.Controller; @@ -367,6 +368,7 @@ namespace Ryujinx.Input.Motion.CemuHook RemoveClient(clientId); } } + break; } } @@ -380,7 +382,7 @@ namespace Ryujinx.Input.Motion.CemuHook Header header = GenerateHeader(clientId); - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter writer = new(stream); writer.WriteStruct(header); @@ -419,7 +421,7 @@ namespace Ryujinx.Input.Motion.CemuHook Header header = GenerateHeader(clientId); - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter writer = new(stream); writer.WriteStruct(header); diff --git a/src/Ryujinx.Input/MotionInputId.cs b/src/Ryujinx.Input/MotionInputId.cs index 9835e70b7..c3768da96 100644 --- a/src/Ryujinx.Input/MotionInputId.cs +++ b/src/Ryujinx.Input/MotionInputId.cs @@ -21,7 +21,7 @@ namespace Ryujinx.Input /// /// Values are in degrees Gyroscope, - + /// /// Second accelerometer. /// diff --git a/src/Ryujinx.Memory/Ryujinx.Memory.csproj b/src/Ryujinx.Memory/Ryujinx.Memory.csproj index eda3ed17f..9cdeba3f1 100644 --- a/src/Ryujinx.Memory/Ryujinx.Memory.csproj +++ b/src/Ryujinx.Memory/Ryujinx.Memory.csproj @@ -3,6 +3,7 @@ true $(DefaultItemExcludes);._* + true diff --git a/src/Ryujinx.Memory/Tracking/IMultiRegionHandle.cs b/src/Ryujinx.Memory/Tracking/IMultiRegionHandle.cs index 62b58344d..c4fd15f7e 100644 --- a/src/Ryujinx.Memory/Tracking/IMultiRegionHandle.cs +++ b/src/Ryujinx.Memory/Tracking/IMultiRegionHandle.cs @@ -23,7 +23,6 @@ namespace Ryujinx.Memory.Tracking /// Action to perform for modified regions void QueryModified(Action modifiedAction); - /// /// Check if part of the region has been modified within a given range, and perform an action for each. /// The range is aligned to the level of granularity of the contained handles. diff --git a/src/Ryujinx.Memory/Tracking/MultiRegionHandle.cs b/src/Ryujinx.Memory/Tracking/MultiRegionHandle.cs index a9b79ab3e..20d2a07ef 100644 --- a/src/Ryujinx.Memory/Tracking/MultiRegionHandle.cs +++ b/src/Ryujinx.Memory/Tracking/MultiRegionHandle.cs @@ -282,6 +282,7 @@ namespace Ryujinx.Memory.Tracking modifiedAction(rgStart, rgSize); rgSize = 0; } + rgStart = handle.RealAddress; } diff --git a/src/Ryujinx.Memory/Tracking/RegionHandle.cs b/src/Ryujinx.Memory/Tracking/RegionHandle.cs index b938c6ea9..f0edee3fc 100644 --- a/src/Ryujinx.Memory/Tracking/RegionHandle.cs +++ b/src/Ryujinx.Memory/Tracking/RegionHandle.cs @@ -177,7 +177,7 @@ namespace Ryujinx.Memory.Tracking InitializeRegions(); } - private List GetGuestRegions(MemoryTracking tracking, ulong address, ulong size, RegionFlags flags) + private static List GetGuestRegions(MemoryTracking tracking, ulong address, ulong size, RegionFlags flags) { ulong guestAddress; ulong guestSize; @@ -305,6 +305,7 @@ namespace Ryujinx.Memory.Tracking { OnDirty?.Invoke(); } + Parent?.SignalWrite(); } } diff --git a/src/Ryujinx.Memory/Tracking/SmartMultiRegionHandle.cs b/src/Ryujinx.Memory/Tracking/SmartMultiRegionHandle.cs index 1e44c0916..ccd60e8da 100644 --- a/src/Ryujinx.Memory/Tracking/SmartMultiRegionHandle.cs +++ b/src/Ryujinx.Memory/Tracking/SmartMultiRegionHandle.cs @@ -110,6 +110,7 @@ namespace Ryujinx.Memory.Tracking { splitLow.RegisterAction(signal); } + _handles[handleIndex] = splitLow; RegionHandle splitHigh = _tracking.BeginTracking(address + size, handle.Size - size, _id); @@ -118,6 +119,7 @@ namespace Ryujinx.Memory.Tracking { splitHigh.RegisterAction(signal); } + _handles[splitIndex] = splitHigh; } @@ -136,6 +138,7 @@ namespace Ryujinx.Memory.Tracking SplitHandle(i, startHandle); return; // The remainer of this handle should be filled in later on. } + break; } } @@ -201,6 +204,7 @@ namespace Ryujinx.Memory.Tracking modifiedAction(rgStart, rgSize); rgSize = 0; } + rgStart = handle.EndAddress; } @@ -255,6 +259,7 @@ namespace Ryujinx.Memory.Tracking modifiedAction(rgStart, rgSize); rgSize = 0; } + rgStart = handle.EndAddress; } diff --git a/src/Ryujinx.Memory/Tracking/VirtualRegion.cs b/src/Ryujinx.Memory/Tracking/VirtualRegion.cs index f9267d85b..b86631db2 100644 --- a/src/Ryujinx.Memory/Tracking/VirtualRegion.cs +++ b/src/Ryujinx.Memory/Tracking/VirtualRegion.cs @@ -98,6 +98,7 @@ namespace Ryujinx.Memory.Tracking return result; } } + return result; } @@ -142,7 +143,7 @@ namespace Ryujinx.Memory.Tracking Size = splitAddress - Address; // The new region inherits all of our parents. - newRegion.Handles = new List(Handles); + newRegion.Handles = [.. Handles]; foreach (RegionHandle parent in Handles) { parent.AddChild(newRegion); diff --git a/src/Ryujinx.Memory/VirtualMemoryManagerBase.cs b/src/Ryujinx.Memory/VirtualMemoryManagerBase.cs index eb5d66829..9c49286b9 100644 --- a/src/Ryujinx.Memory/VirtualMemoryManagerBase.cs +++ b/src/Ryujinx.Memory/VirtualMemoryManagerBase.cs @@ -400,6 +400,5 @@ namespace Ryujinx.Memory } } } - } } diff --git a/src/Ryujinx.SDL2.Common/SDL2Driver.cs b/src/Ryujinx.SDL2.Common/SDL2Driver.cs index 70453e549..df11966bc 100644 --- a/src/Ryujinx.SDL2.Common/SDL2Driver.cs +++ b/src/Ryujinx.SDL2.Common/SDL2Driver.cs @@ -32,12 +32,11 @@ namespace Ryujinx.SDL2.Common private Thread _worker; private const uint SDL_JOYBATTERYUPDATED = 1543; - + public event Action OnJoyStickConnected; public event Action OnJoystickDisconnected; - - public event Action OnJoyBatteryUpdated; + public event Action OnJoyBatteryUpdated; private ConcurrentDictionary> _registeredWindowHandlers; @@ -66,7 +65,6 @@ namespace Ryujinx.SDL2.Common SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1"); SDL_SetHint(SDL_HINT_VIDEO_ALLOW_SCREENSAVER, "1"); - // NOTE: As of SDL2 2.24.0, joycons are combined by default but the motion source only come from one of them. // We disable this behavior for now. SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_COMBINE_JOY_CONS, "0"); diff --git a/src/Ryujinx.Tests.Memory/MultiRegionTrackingTests.cs b/src/Ryujinx.Tests.Memory/MultiRegionTrackingTests.cs index c9ac4dc94..b35de3a82 100644 --- a/src/Ryujinx.Tests.Memory/MultiRegionTrackingTests.cs +++ b/src/Ryujinx.Tests.Memory/MultiRegionTrackingTests.cs @@ -400,6 +400,8 @@ namespace Ryujinx.Tests.Memory Assert.AreEqual(singlePages[2], combinedHandles.ElementAt(10)); } + static readonly bool[] _expectedPagesModified = [true, false, false]; + [Test] public void PreciseAction() { @@ -409,7 +411,11 @@ namespace Ryujinx.Tests.Memory PreparePages(granular, 3, PageSize * 3); // Add a precise action to the second and third handle in the multiregion. - granular.RegisterPreciseAction(PageSize * 4, PageSize * 2, (_, _, _) => { actionTriggered = true; return true; }); + granular.RegisterPreciseAction(PageSize * 4, PageSize * 2, (_, _, _) => + { + actionTriggered = true; + return true; + }); // Precise write to first handle in the multiregion. _tracking.VirtualMemoryEvent(PageSize * 3, PageSize, true, precise: true); @@ -433,7 +439,7 @@ namespace Ryujinx.Tests.Memory Assert.IsTrue(actionTriggered); // Action triggered. // Precise writes are ignored on two later handles due to the action returning true. - Assert.AreEqual(pagesModified, new bool[] { true, false, false }); + Assert.AreEqual(pagesModified, _expectedPagesModified); } } } diff --git a/src/Ryujinx.Tests.Memory/TrackingTests.cs b/src/Ryujinx.Tests.Memory/TrackingTests.cs index 675179ede..ac661924e 100644 --- a/src/Ryujinx.Tests.Memory/TrackingTests.cs +++ b/src/Ryujinx.Tests.Memory/TrackingTests.cs @@ -329,6 +329,7 @@ namespace Ryujinx.Tests.Memory { _tracking.VirtualMemoryEvent((ulong)random.Next(PageSize), 4, false); } + Interlocked.Increment(ref signalThreadsDone); }); } diff --git a/src/Ryujinx.Tests.Unicorn/Ryujinx.Tests.Unicorn.csproj b/src/Ryujinx.Tests.Unicorn/Ryujinx.Tests.Unicorn.csproj index f9f42416f..00fe473c5 100644 --- a/src/Ryujinx.Tests.Unicorn/Ryujinx.Tests.Unicorn.csproj +++ b/src/Ryujinx.Tests.Unicorn/Ryujinx.Tests.Unicorn.csproj @@ -1,4 +1,4 @@ - + true @@ -7,7 +7,7 @@ - false + true diff --git a/src/Ryujinx.Tests/Audio/Renderer/Server/PoolMapperTests.cs b/src/Ryujinx.Tests/Audio/Renderer/Server/PoolMapperTests.cs index d7879d627..941afae6f 100644 --- a/src/Ryujinx.Tests/Audio/Renderer/Server/PoolMapperTests.cs +++ b/src/Ryujinx.Tests/Audio/Renderer/Server/PoolMapperTests.cs @@ -85,7 +85,6 @@ namespace Ryujinx.Tests.Audio.Renderer.Server memoryPoolStateArray[i].SetCpuAddress(CpuAddress + (ulong)i * CpuSize, CpuSize); } - AddressInfo addressInfo = AddressInfo.Create(); PoolMapper poolMapper = new(DummyProcessHandle, true); diff --git a/src/Ryujinx.Tests/Cpu/CpuTest.cs b/src/Ryujinx.Tests/Cpu/CpuTest.cs index 6f749463e..c01a9e4e8 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTest.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTest.cs @@ -13,11 +13,8 @@ namespace Ryujinx.Tests.Cpu public class CpuTest { protected static readonly ulong Size = MemoryBlock.GetPageSize(); -#pragma warning disable CA2211 // Non-constant fields should not be visible - protected static ulong CodeBaseAddress = Size; - protected static ulong DataBaseAddress = CodeBaseAddress + Size; -#pragma warning restore CA2211 - + protected static ulong CodeBaseAddress { get; set; } = Size; + protected static ulong DataBaseAddress { get; set; } = CodeBaseAddress + Size; private static readonly bool _ignoreFpcrFz = false; private static readonly bool _ignoreFpcrDn = false; diff --git a/src/Ryujinx.Tests/Cpu/CpuTest32.cs b/src/Ryujinx.Tests/Cpu/CpuTest32.cs index d4c8156d7..e742c1713 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTest32.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTest32.cs @@ -13,11 +13,8 @@ namespace Ryujinx.Tests.Cpu public class CpuTest32 { protected static readonly uint Size = (uint)MemoryBlock.GetPageSize(); -#pragma warning disable CA2211 // Non-constant fields should not be visible - protected static uint CodeBaseAddress = Size; - protected static uint DataBaseAddress = CodeBaseAddress + Size; -#pragma warning restore CA2211 - + protected static uint CodeBaseAddress { get; set; } = Size; + protected static uint DataBaseAddress { get; set; } = CodeBaseAddress + Size; private uint _currAddress; private MemoryBlock _ram; @@ -421,6 +418,7 @@ namespace Ryujinx.Tests.Cpu { ManageFpTolerances(fpTolerances); } + Assert.That(V128ToSimdValue(_context.GetV(1)), Is.EqualTo(_unicornEmu.Q[1]), "V1"); Assert.That(V128ToSimdValue(_context.GetV(2)), Is.EqualTo(_unicornEmu.Q[2]), "V2"); Assert.That(V128ToSimdValue(_context.GetV(3)), Is.EqualTo(_unicornEmu.Q[3]), "V3"); diff --git a/src/Ryujinx.Tests/Cpu/CpuTestAluRs32.cs b/src/Ryujinx.Tests/Cpu/CpuTestAluRs32.cs index a6f8976c6..48480f58b 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTestAluRs32.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTestAluRs32.cs @@ -35,7 +35,6 @@ namespace Ryujinx.Tests.Cpu } #endregion - [Test, Pairwise] public void Adc_Adcs_Rsc_Rscs_Sbc_Sbcs([ValueSource(nameof(_Adc_Adcs_Rsc_Rscs_Sbc_Sbcs_))] uint opcode, [Values(0u, 13u)] uint rd, diff --git a/src/Ryujinx.Tests/Cpu/CpuTestBf32.cs b/src/Ryujinx.Tests/Cpu/CpuTestBf32.cs index 197171b8d..2006ae5f8 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTestBf32.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTestBf32.cs @@ -65,6 +65,7 @@ namespace Ryujinx.Tests.Cpu { widthm1 -= (lsb + widthm1) - 31; } + uint opcode = 0xe7e00050u; // UBFX R0, R0, #0, #1 opcode |= ((rd & 0xf) << 12); opcode |= ((rn & 0xf) << 0); @@ -90,6 +91,7 @@ namespace Ryujinx.Tests.Cpu { widthm1 -= (lsb + widthm1) - 31; } + uint opcode = 0xe7a00050u; // SBFX R0, R0, #0, #1 opcode |= ((rd & 0xf) << 12); opcode |= ((rn & 0xf) << 0); diff --git a/src/Ryujinx.Tests/Cpu/CpuTestMisc32.cs b/src/Ryujinx.Tests/Cpu/CpuTestMisc32.cs index e984a1584..4921193a2 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTestMisc32.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTestMisc32.cs @@ -90,16 +90,19 @@ namespace Ryujinx.Tests.Cpu { Opcode(0xEEE10A10); // VMSR FPSCR, R0 } + Opcode(0xEEB48A4A); // VCMP.F32 S16, S20 if (mode2) { Opcode(0xEEF10A10); // VMRS R0, FPSCR Opcode(0xE200020F); // AND R0, #0xF0000000 // R0 &= "Fpsr.Nzcv". } + if (mode3) { Opcode(0xEEF1FA10); // VMRS APSR_NZCV, FPSCR } + Opcode(0xE12FFF1E); // BX LR ExecuteOpcodes(); diff --git a/src/Ryujinx.Tests/Cpu/CpuTestSimdMemory32.cs b/src/Ryujinx.Tests/Cpu/CpuTestSimdMemory32.cs index 9bc24b300..04310dbbe 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTestSimdMemory32.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTestSimdMemory32.cs @@ -267,6 +267,7 @@ namespace Ryujinx.Tests.Cpu opcode |= ((sd & 0x10) << 18); opcode |= ((sd & 0xf) << 12); } + opcode |= imm & 0xff; SingleOpcode(opcode, r0: _testOffset); @@ -302,6 +303,7 @@ namespace Ryujinx.Tests.Cpu opcode |= ((sd & 0x10) << 18); opcode |= ((sd & 0xf) << 12); } + opcode |= imm & 0xff; (V128 vec1, V128 vec2, _, _) = GenerateTestVectors(); diff --git a/src/Ryujinx.Tests/Cpu/CpuTestSimdMov32.cs b/src/Ryujinx.Tests/Cpu/CpuTestSimdMov32.cs index 3956115d1..17e8f4d40 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTestSimdMov32.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTestSimdMov32.cs @@ -459,6 +459,7 @@ namespace Ryujinx.Tests.Cpu { opcode |= 1 << 6; } + opcode |= (vm & 0x10) << 1; opcode |= (vm & 0xf); opcode |= (vd & 0x10) << 18; @@ -511,6 +512,7 @@ namespace Ryujinx.Tests.Cpu { return; // Undefined. } + opcode |= (vm & 0x10) << 1; opcode |= (vm & 0xf); opcode |= (vd & 0x10) << 18; diff --git a/src/Ryujinx.Tests/Cpu/CpuTestSimdRegElem.cs b/src/Ryujinx.Tests/Cpu/CpuTestSimdRegElem.cs index 810c617f0..4d765fe1d 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTestSimdRegElem.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTestSimdRegElem.cs @@ -82,7 +82,6 @@ namespace Ryujinx.Tests.Cpu } #endregion - [Test, Pairwise] public void Mla_Mls_Mul_Sqdmulh_Sqrdmulh_Ve_4H_8H([ValueSource(nameof(_Mla_Mls_Mul_Sqdmulh_Sqrdmulh_Ve_4H_8H_))] uint opcodes, [Values(0u)] uint rd, diff --git a/src/Ryujinx.Tests/Cpu/CpuTestT32Flow.cs b/src/Ryujinx.Tests/Cpu/CpuTestT32Flow.cs index 01159afc6..b73072207 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTestT32Flow.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTestT32Flow.cs @@ -100,6 +100,7 @@ namespace Ryujinx.Tests.Cpu { ThumbOpcode(0xe7fe); } + ThumbOpcode(0x4670); // label: MOV R0, LR ThumbOpcode(0x2100); // MOVS R1, #0 ThumbOpcode(0x468e); // MOV LR, R1 diff --git a/src/Ryujinx.Tests/Cpu/CpuTestThumb.cs b/src/Ryujinx.Tests/Cpu/CpuTestThumb.cs index 4e90fdeac..1f00c663d 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTestThumb.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTestThumb.cs @@ -111,6 +111,7 @@ namespace Ryujinx.Tests.Cpu Assert.That(GetContext().GetPstateFlag(PState.CFlag), Is.EqualTo(w1 >= imm)); Assert.That(GetContext().GetPstateFlag(PState.VFlag), Is.EqualTo((overflow >> 31) != 0)); } + break; case 2: Assert.That(GetContext().GetX(1), Is.EqualTo((w1 + imm) & 0xffffffffu)); @@ -166,6 +167,7 @@ namespace Ryujinx.Tests.Cpu Assert.That(GetContext().GetPstateFlag(PState.NFlag), Is.EqualTo((result >> 31) != 0)); Assert.That(GetContext().GetPstateFlag(PState.ZFlag), Is.EqualTo(result == 0)); } + break; case 9: Assert.That(GetContext().GetX(1), Is.EqualTo((uint)-w2)); @@ -180,6 +182,7 @@ namespace Ryujinx.Tests.Cpu Assert.That(GetContext().GetPstateFlag(PState.CFlag), Is.EqualTo(w1 >= w2)); Assert.That(GetContext().GetPstateFlag(PState.VFlag), Is.EqualTo((overflow >> 31) != 0)); } + break; case 11: Assert.That(GetContext().GetX(1), Is.EqualTo(w1)); @@ -191,6 +194,7 @@ namespace Ryujinx.Tests.Cpu Assert.That(GetContext().GetPstateFlag(PState.CFlag), Is.EqualTo(result < w1)); Assert.That(GetContext().GetPstateFlag(PState.VFlag), Is.EqualTo((overflow >> 31) != 0)); } + break; case 12: Assert.That(GetContext().GetX(1), Is.EqualTo(w1 | w2)); @@ -244,6 +248,7 @@ namespace Ryujinx.Tests.Cpu Assert.That(GetContext().GetPstateFlag(PState.CFlag), Is.EqualTo(w1 >= w2)); Assert.That(GetContext().GetPstateFlag(PState.VFlag), Is.EqualTo((overflow >> 31) != 0)); } + break; case 2: Assert.That(GetContext().GetX((int)rd), Is.EqualTo(w2)); diff --git a/src/Ryujinx.Tests/Cpu/EnvironmentTests.cs b/src/Ryujinx.Tests/Cpu/EnvironmentTests.cs index da4997e26..d67f22160 100644 --- a/src/Ryujinx.Tests/Cpu/EnvironmentTests.cs +++ b/src/Ryujinx.Tests/Cpu/EnvironmentTests.cs @@ -12,15 +12,13 @@ namespace Ryujinx.Tests.Cpu { internal class EnvironmentTests { -#pragma warning disable IDE0052 // Remove unread private member private static Translator _translator; -#pragma warning restore IDE0052 private static void EnsureTranslator() { // Create a translator, as one is needed to register the signal handler or emit methods. _translator ??= new Translator( - new JitMemoryAllocator(), + new JitMemoryAllocator(), new MockMemoryManager(), AddressTable.CreateForArm(true, MemoryManagerType.SoftwarePageTable)); } diff --git a/src/Ryujinx.Tests/Memory/PartialUnmaps.cs b/src/Ryujinx.Tests/Memory/PartialUnmaps.cs index e723a3c74..92b994279 100644 --- a/src/Ryujinx.Tests/Memory/PartialUnmaps.cs +++ b/src/Ryujinx.Tests/Memory/PartialUnmaps.cs @@ -14,6 +14,7 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Versioning; using System.Threading; namespace Ryujinx.Tests.Memory @@ -57,8 +58,8 @@ namespace Ryujinx.Tests.Memory { // Create a translator, as one is needed to register the signal handler or emit methods. _translator ??= new Translator( - new JitMemoryAllocator(), - new MockMemoryManager(), + new JitMemoryAllocator(), + new MockMemoryManager(), AddressTable.CreateForArm(true, MemoryManagerType.SoftwarePageTable)); } @@ -289,7 +290,7 @@ namespace Ryujinx.Tests.Memory [Test] // Only test in Windows, as this is only used on Windows and uses Windows APIs for trimming. [Platform("Win")] - [SuppressMessage("Interoperability", "CA1416: Validate platform compatibility")] + [SupportedOSPlatform("windows")] public void ThreadLocalMap() { PartialUnmapState.Reset(); diff --git a/src/Ryujinx.Tests/Ryujinx.Tests.csproj b/src/Ryujinx.Tests/Ryujinx.Tests.csproj index daa2b4287..2ac6410ef 100644 --- a/src/Ryujinx.Tests/Ryujinx.Tests.csproj +++ b/src/Ryujinx.Tests/Ryujinx.Tests.csproj @@ -1,4 +1,4 @@ - + Exe @@ -13,7 +13,7 @@ - false + true True diff --git a/src/Ryujinx.Tests/TreeDictionaryTests.cs b/src/Ryujinx.Tests/TreeDictionaryTests.cs index ea9fb0731..61ea88d7c 100644 --- a/src/Ryujinx.Tests/TreeDictionaryTests.cs +++ b/src/Ryujinx.Tests/TreeDictionaryTests.cs @@ -84,6 +84,7 @@ namespace Ryujinx.Tests.Collections { Console.WriteLine($"{node.Key} -> {node.Value}"); } + Assert.AreEqual(list.Count, dictionary.Count); Assert.AreEqual(list[0].Key, 4); Assert.AreEqual(list[1].Key, 2); @@ -118,6 +119,7 @@ namespace Ryujinx.Tests.Collections { Console.WriteLine($"{node.Key} -> {node.Value}"); } + Assert.AreEqual(list[0].Key, 4); Assert.AreEqual(list[1].Key, 2); Assert.AreEqual(list[2].Key, 10); @@ -149,6 +151,7 @@ namespace Ryujinx.Tests.Collections { Console.WriteLine($"{node.Key} -> {node.Value}"); } + Assert.AreEqual(list[0].Key, 4); Assert.AreEqual(list[1].Key, 2); Assert.AreEqual(list[2].Key, 9); @@ -224,7 +227,6 @@ namespace Ryujinx.Tests.Collections Assert.AreEqual(list[4].Value, 4); - // Assure that none of the nodes locations have been modified. Assert.AreEqual(list[0].Key, 4); Assert.AreEqual(list[1].Key, 2); diff --git a/src/Ryujinx.UI.LocaleGenerator/LocaleGenerator.cs b/src/Ryujinx.UI.LocaleGenerator/LocaleGenerator.cs index a3d16c660..4de92ee4a 100644 --- a/src/Ryujinx.UI.LocaleGenerator/LocaleGenerator.cs +++ b/src/Ryujinx.UI.LocaleGenerator/LocaleGenerator.cs @@ -26,6 +26,7 @@ namespace Ryujinx.UI.LocaleGenerator { enumSourceBuilder.AppendLine($" {line},"); } + enumSourceBuilder.AppendLine("}"); spc.AddSource("LocaleKeys", enumSourceBuilder.ToString()); diff --git a/src/Ryujinx/Assets/Styles/Styles.xaml b/src/Ryujinx/Assets/Styles/Styles.xaml index ff9a528a5..ea6096792 100644 --- a/src/Ryujinx/Assets/Styles/Styles.xaml +++ b/src/Ryujinx/Assets/Styles/Styles.xaml @@ -372,6 +372,12 @@ +