diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml new file mode 100644 index 000000000..b64fc1d92 --- /dev/null +++ b/.github/workflows/canary.yml @@ -0,0 +1,254 @@ +name: Canary release job + +on: + workflow_dispatch: + inputs: {} + push: + branches: [ master ] + paths-ignore: + - '.github/**' + - 'docs/**' + - 'assets/**' + - '*.yml' + - '*.json' + - '*.config' + - '*.md' + +concurrency: release + +env: + POWERSHELL_TELEMETRY_OPTOUT: 1 + DOTNET_CLI_TELEMETRY_OPTOUT: 1 + RYUJINX_BASE_VERSION: "1.2" + RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "canary" + RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "GreemDev" + RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Ryujinx-Canary" + RELEASE: 1 + +jobs: + tag: + name: Create tag + runs-on: ubuntu-20.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: Create tag + uses: actions/github-script@v7 + with: + script: | + github.rest.git.createRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: 'refs/tags/Canary-${{ steps.version_info.outputs.build_version }}', + sha: context.sha + }) + + - 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: "**Full Changelog**: https://github.com/${{ github.repository }}/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 }} + strategy: + matrix: + platform: + - { name: win-x64, os: windows-latest, zip_os_name: win_x64 } + - { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 } + - { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 } + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-dotnet@v4 + with: + global-json-file: global.json + + - name: Overwrite csc problem matcher + run: echo "::add-matcher::.github/csc.json" + + - name: Get version info + id: version_info + run: | + echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT + echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT + echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT + shell: bash + + - name: Configure for release + run: | + sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs + shell: bash + + - name: Create output dir + run: "mkdir release_output" + + - name: Publish + run: | + dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained -p:IncludeNativeLibrariesForSelfExtract=true + dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --self-contained -p:IncludeNativeLibrariesForSelfExtract=true + + - name: Packing Windows builds + if: matrix.platform.os == 'windows-latest' + run: | + pushd publish_ava + rm publish/libarmeilleure-jitsupport.dylib + 7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish + popd + + pushd publish_sdl2_headless + rm publish/libarmeilleure-jitsupport.dylib + 7z a ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish + popd + shell: bash + + - name: Packing Linux builds + if: matrix.platform.os == 'ubuntu-latest' + run: | + pushd publish_ava + rm publish/libarmeilleure-jitsupport.dylib + chmod +x publish/Ryujinx.sh publish/Ryujinx + tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish + popd + + pushd publish_sdl2_headless + rm publish/libarmeilleure-jitsupport.dylib + chmod +x publish/Ryujinx.sh publish/Ryujinx.Headless.SDL2 + tar -czvf ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish + popd + 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_ava OUTDIR=publish_ava_appimage distribution/linux/appimage/build-appimage.sh + + # Add to release output + # pushd publish_ava_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 + # 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" + #artifacts: "release_output/*.tar.gz,release_output/*.zip/*AppImage*" + tag: ${{ steps.version_info.outputs.build_version }} + body: "**Full Changelog**: https://github.com/${{ github.repository }}/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 }} + + macos_release: + name: Release MacOS universal + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-dotnet@v4 + with: + global-json-file: global.json + + - name: Setup LLVM 15 + run: | + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh 15 + + - name: Install rcodesign + run: | + mkdir -p $HOME/.bin + gh release download -R indygreg/apple-platform-rs -O apple-codesign.tar.gz -p 'apple-codesign-*-x86_64-unknown-linux-musl.tar.gz' + tar -xzvf apple-codesign.tar.gz --wildcards '*/rcodesign' --strip-components=1 + rm apple-codesign.tar.gz + mv rcodesign $HOME/.bin/ + echo "$HOME/.bin" >> $GITHUB_PATH + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get version info + id: version_info + run: | + echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT + echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT + echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT + + - name: Configure for release + run: | + sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs + shell: bash + + - name: Publish macOS Ryujinx + 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 + + - name: Publish macOS Ryujinx.Headless.SDL2 + run: | + ./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release + + - name: Pushing new release + uses: ncipollo/release-action@v1 + with: + name: "Canary ${{ steps.version_info.outputs.build_version }}" + artifacts: "publish_ava/*.tar.gz, publish_headless/*.tar.gz" + tag: ${{ steps.version_info.outputs.build_version }} + body: "**Full Changelog**: https://github.com/${{ github.repository }}/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 }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index aad32deb6..c3c1e2a28 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: inputs: {} push: - branches: [ master ] + branches: [ release ] paths-ignore: - '.github/**' - 'docs/**' @@ -20,7 +20,7 @@ env: POWERSHELL_TELEMETRY_OPTOUT: 1 DOTNET_CLI_TELEMETRY_OPTOUT: 1 RYUJINX_BASE_VERSION: "1.2" - RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "master" + RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release" RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "GreemDev" RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Ryujinx" RELEASE: 1 diff --git a/README.md b/README.md index f03a1205f..d2ce7ca01 100644 --- a/README.md +++ b/README.md @@ -61,9 +61,9 @@ Use the search function to see if a game has been tested already! To run this emulator, your PC must be equipped with at least 8GiB of RAM; failing to meet this requirement may result in a poor gameplay experience or unexpected crashes. -## Latest build +## Latest release -These builds are compiled automatically for each commit on the master branch. +Releases are compiled automatically for each commit on the master branch. While we strive to ensure optimal stability and performance prior to pushing an update, our automated builds **may be unstable or completely broken**. You can find the latest release [here](https://github.com/GreemDev/Ryujinx/releases/latest). @@ -74,6 +74,7 @@ If you are planning to contribute or just want to learn more about this project ## Building +Building the project is for advanced users. If you wish to build the emulator yourself, follow these steps: ### Step 1 diff --git a/Ryujinx.sln b/Ryujinx.sln index eaa28f8dd..d661b903c 100644 --- a/Ryujinx.sln +++ b/Ryujinx.sln @@ -29,14 +29,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec", "s EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio", "src\Ryujinx.Audio\Ryujinx.Audio.csproj", "{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}" - ProjectSection(SolutionItems) = preProject - .editorconfig = .editorconfig - Directory.Packages.props = Directory.Packages.props - Release Script = .github/workflows/release.yml - Build Script = .github/workflows/build.yml - EndProjectSection -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Memory", "src\Ryujinx.Memory\Ryujinx.Memory.csproj", "{A5E6C691-9E22-4263-8F40-42F002CE66BE}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Tests.Memory", "src\Ryujinx.Tests.Memory\Ryujinx.Tests.Memory.csproj", "{D1CC5322-7325-4F6B-9625-194B30BE1296}" @@ -89,6 +81,15 @@ 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("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + Directory.Packages.props = Directory.Packages.props + .github/workflows/release.yml = .github/workflows/release.yml + .github/workflows/canary.yml = .github/workflows/canary.yml + .github/workflows/build.yml = .github/workflows/build.yml + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/distribution/macos/Ryujinx.icns b/distribution/macos/Ryujinx.icns index f54a9aeb7..1bb88a5d7 100644 Binary files a/distribution/macos/Ryujinx.icns and b/distribution/macos/Ryujinx.icns differ diff --git a/distribution/macos/create_app_bundle.sh b/distribution/macos/create_app_bundle.sh index 0fa54eadd..e4397da84 100755 --- a/distribution/macos/create_app_bundle.sh +++ b/distribution/macos/create_app_bundle.sh @@ -46,5 +46,5 @@ then rcodesign sign --entitlements-xml-path "$ENTITLEMENTS_FILE_PATH" "$APP_BUNDLE_DIRECTORY" else echo "Usign codesign for ad-hoc signing" - codesign --entitlements "$ENTITLEMENTS_FILE_PATH" -f --deep -s - "$APP_BUNDLE_DIRECTORY" -fi \ No newline at end of file + 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 6785cbb23..80bd6662c 100755 --- a/distribution/macos/create_macos_build_ava.sh +++ b/distribution/macos/create_macos_build_ava.sh @@ -99,7 +99,7 @@ then rcodesign sign --entitlements-xml-path "$ENTITLEMENTS_FILE_PATH" "$UNIVERSAL_APP_BUNDLE" else echo "Using codesign for ad-hoc signing" - codesign --entitlements "$ENTITLEMENTS_FILE_PATH" -f --deep -s - "$UNIVERSAL_APP_BUNDLE" + codesign --entitlements "$ENTITLEMENTS_FILE_PATH" -f -s - "$UNIVERSAL_APP_BUNDLE" fi echo "Creating archive" @@ -111,4 +111,4 @@ rm "$RELEASE_TAR_FILE_NAME" popd -echo "Done" \ No newline at end of file +echo "Done" diff --git a/distribution/macos/create_macos_build_headless.sh b/distribution/macos/create_macos_build_headless.sh index a439aef45..2715699d0 100755 --- a/distribution/macos/create_macos_build_headless.sh +++ b/distribution/macos/create_macos_build_headless.sh @@ -95,7 +95,7 @@ else echo "Using codesign for ad-hoc signing" for FILE in "$UNIVERSAL_OUTPUT"/*; do if [[ $(file "$FILE") == *"Mach-O"* ]]; then - codesign --entitlements "$ENTITLEMENTS_FILE_PATH" -f --deep -s - "$FILE" + codesign --entitlements "$ENTITLEMENTS_FILE_PATH" -f -s - "$FILE" fi done fi @@ -108,4 +108,4 @@ gzip -9 < "$RELEASE_TAR_FILE_NAME" > "$RELEASE_TAR_FILE_NAME.gz" rm "$RELEASE_TAR_FILE_NAME" popd -echo "Done" \ No newline at end of file +echo "Done" diff --git a/src/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs b/src/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs index 5cb4509ff..8b497fe2a 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs @@ -81,7 +81,7 @@ 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}"); diff --git a/src/Ryujinx.Common/Logging/LogClass.cs b/src/Ryujinx.Common/Logging/LogClass.cs index 1b404a06a..a4117580e 100644 --- a/src/Ryujinx.Common/Logging/LogClass.cs +++ b/src/Ryujinx.Common/Logging/LogClass.cs @@ -72,5 +72,6 @@ namespace Ryujinx.Common.Logging TamperMachine, UI, Vic, + XCIFileTrimmer } } diff --git a/src/Ryujinx.Common/Logging/XCIFileTrimmerLog.cs b/src/Ryujinx.Common/Logging/XCIFileTrimmerLog.cs new file mode 100644 index 000000000..fb11432b0 --- /dev/null +++ b/src/Ryujinx.Common/Logging/XCIFileTrimmerLog.cs @@ -0,0 +1,30 @@ +using Ryujinx.Common.Utilities; + +namespace Ryujinx.Common.Logging +{ + public class XCIFileTrimmerLog : XCIFileTrimmer.ILog + { + public virtual void Progress(long current, long total, string text, bool complete) + { + } + + public void Write(XCIFileTrimmer.LogType logType, string text) + { + switch (logType) + { + case XCIFileTrimmer.LogType.Info: + Logger.Notice.Print(LogClass.XCIFileTrimmer, text); + break; + case XCIFileTrimmer.LogType.Warn: + Logger.Warning?.Print(LogClass.XCIFileTrimmer, text); + break; + case XCIFileTrimmer.LogType.Error: + Logger.Error?.Print(LogClass.XCIFileTrimmer, text); + break; + case XCIFileTrimmer.LogType.Progress: + Logger.Info?.Print(LogClass.XCIFileTrimmer, text); + break; + } + } + } +} diff --git a/src/Ryujinx.Common/ReleaseInformation.cs b/src/Ryujinx.Common/ReleaseInformation.cs index dfba64191..888c57e81 100644 --- a/src/Ryujinx.Common/ReleaseInformation.cs +++ b/src/Ryujinx.Common/ReleaseInformation.cs @@ -5,7 +5,9 @@ namespace Ryujinx.Common // DO NOT EDIT, filled by CI public static class ReleaseInformation { - private const string FlatHubChannelOwner = "flathub"; + private const string FlatHubChannel = "flathub"; + private const string CanaryChannel = "canary"; + private const string ReleaseChannel = "release"; private const string BuildVersion = "%%RYUJINX_BUILD_VERSION%%"; public const string BuildGitHash = "%%RYUJINX_BUILD_GIT_HASH%%"; @@ -24,7 +26,11 @@ namespace Ryujinx.Common !ReleaseChannelRepo.StartsWith("%%") && !ConfigFileName.StartsWith("%%"); - public static bool IsFlatHubBuild => IsValid && ReleaseChannelOwner.Equals(FlatHubChannelOwner); + public static bool IsFlatHubBuild => IsValid && ReleaseChannelOwner.Equals(FlatHubChannel); + + public static bool IsCanaryBuild => IsValid && ReleaseChannelOwner.Equals(CanaryChannel); + + public static bool IsReleaseBuild => IsValid && ReleaseChannelOwner.Equals(ReleaseChannel); public static string Version => IsValid ? BuildVersion : Assembly.GetEntryAssembly()!.GetCustomAttribute()?.InformationalVersion; } diff --git a/src/Ryujinx.Common/Utilities/XCIFileTrimmer.cs b/src/Ryujinx.Common/Utilities/XCIFileTrimmer.cs new file mode 100644 index 000000000..050e78d1e --- /dev/null +++ b/src/Ryujinx.Common/Utilities/XCIFileTrimmer.cs @@ -0,0 +1,524 @@ +// Uncomment the line below to ensure XCIFileTrimmer does not modify files +//#define XCI_TRIMMER_READ_ONLY_MODE + +using Gommon; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Threading; + +namespace Ryujinx.Common.Utilities +{ + public sealed class XCIFileTrimmer + { + private const long BytesInAMegabyte = 1024 * 1024; + private const int BufferSize = 8 * (int)BytesInAMegabyte; + + private const long CartSizeMBinFormattedGB = 952; + private const int CartKeyAreaSize = 0x1000; + private const byte PaddingByte = 0xFF; + private const int HeaderFilePos = 0x100; + private const int CartSizeFilePos = 0x10D; + private const int DataSizeFilePos = 0x118; + private const string HeaderMagicValue = "HEAD"; + + /// + /// Cartridge Sizes (ByteIdentifier, SizeInGB) + /// + private static readonly Dictionary _cartSizesGB = new() + { + { 0xFA, 1 }, + { 0xF8, 2 }, + { 0xF0, 4 }, + { 0xE0, 8 }, + { 0xE1, 16 }, + { 0xE2, 32 } + }; + + private static long RecordsToByte(long records) + { + return 512 + (records * 512); + } + + public static bool CanTrim(string filename, ILog log = null) + { + if (Path.GetExtension(filename).Equals(".XCI", StringComparison.InvariantCultureIgnoreCase)) + { + var trimmer = new XCIFileTrimmer(filename, log); + return trimmer.CanBeTrimmed; + } + + return false; + } + + public static bool CanUntrim(string filename, ILog log = null) + { + if (Path.GetExtension(filename).Equals(".XCI", StringComparison.InvariantCultureIgnoreCase)) + { + var trimmer = new XCIFileTrimmer(filename, log); + return trimmer.CanBeUntrimmed; + } + + return false; + } + + private ILog _log; + private string _filename; + private FileStream _fileStream; + private BinaryReader _binaryReader; + private long _offsetB, _dataSizeB, _cartSizeB, _fileSizeB; + private bool _fileOK = true; + private bool _freeSpaceChecked = false; + private bool _freeSpaceValid = false; + + public enum OperationOutcome + { + Undetermined, + InvalidXCIFile, + NoTrimNecessary, + NoUntrimPossible, + FreeSpaceCheckFailed, + FileIOWriteError, + ReadOnlyFileCannotFix, + FileSizeChanged, + Successful, + Cancelled + } + + public enum LogType + { + Info, + Warn, + Error, + Progress + } + + public interface ILog + { + public void Write(LogType logType, string text); + public void Progress(long current, long total, string text, bool complete); + } + + public bool FileOK => _fileOK; + public bool Trimmed => _fileOK && FileSizeB < UntrimmedFileSizeB; + public bool ContainsKeyArea => _offsetB != 0; + public bool CanBeTrimmed => _fileOK && FileSizeB > TrimmedFileSizeB; + public bool CanBeUntrimmed => _fileOK && FileSizeB < UntrimmedFileSizeB; + public bool FreeSpaceChecked => _fileOK && _freeSpaceChecked; + public bool FreeSpaceValid => _fileOK && _freeSpaceValid; + public long DataSizeB => _dataSizeB; + public long CartSizeB => _cartSizeB; + public long FileSizeB => _fileSizeB; + public long DiskSpaceSavedB => CartSizeB - FileSizeB; + public long DiskSpaceSavingsB => CartSizeB - DataSizeB; + public long TrimmedFileSizeB => _offsetB + _dataSizeB; + public long UntrimmedFileSizeB => _offsetB + _cartSizeB; + + public ILog Log + { + get => _log; + set => _log = value; + } + + public String Filename + { + get => _filename; + set + { + _filename = value; + Reset(); + } + } + + public long Pos + { + get => _fileStream.Position; + set => _fileStream.Position = value; + } + + public XCIFileTrimmer(string path, ILog log = null) + { + Log = log; + Filename = path; + ReadHeader(); + } + + public void CheckFreeSpace(CancellationToken? cancelToken = null) + { + if (FreeSpaceChecked) + return; + + try + { + if (CanBeTrimmed) + { + _freeSpaceValid = false; + + OpenReaders(); + + try + { + Pos = TrimmedFileSizeB; + bool freeSpaceValid = true; + long readSizeB = FileSizeB - TrimmedFileSizeB; + + Stopwatch timedSw = Lambda.Timed(() => + { + freeSpaceValid = CheckPadding(readSizeB, cancelToken); + }); + + if (timedSw.Elapsed.TotalSeconds > 0) + { + Log?.Write(LogType.Info, $"Checked at {readSizeB / (double)XCIFileTrimmer.BytesInAMegabyte / timedSw.Elapsed.TotalSeconds:N} Mb/sec"); + } + + if (freeSpaceValid) + Log?.Write(LogType.Info, "Free space is valid"); + + _freeSpaceValid = freeSpaceValid; + } + finally + { + CloseReaders(); + } + + } + else + { + Log?.Write(LogType.Warn, "There is no free space to check."); + _freeSpaceValid = false; + } + } + finally + { + _freeSpaceChecked = true; + } + } + + private bool CheckPadding(long readSizeB, CancellationToken? cancelToken = null) + { + long maxReads = readSizeB / XCIFileTrimmer.BufferSize; + long read = 0; + var buffer = new byte[BufferSize]; + + while (true) + { + if (cancelToken.HasValue && cancelToken.Value.IsCancellationRequested) + { + return false; + } + + int bytes = _fileStream.Read(buffer, 0, XCIFileTrimmer.BufferSize); + if (bytes == 0) + break; + + Log?.Progress(read, maxReads, "Verifying file can be trimmed", false); + if (buffer.Take(bytes).AsParallel().Any(b => b != XCIFileTrimmer.PaddingByte)) + { + Log?.Write(LogType.Warn, "Free space is NOT valid"); + return false; + } + + read++; + } + + return true; + } + + private void Reset() + { + _freeSpaceChecked = false; + _freeSpaceValid = false; + ReadHeader(); + } + + public OperationOutcome Trim(CancellationToken? cancelToken = null) + { + if (!FileOK) + { + return OperationOutcome.InvalidXCIFile; + } + + if (!CanBeTrimmed) + { + return OperationOutcome.NoTrimNecessary; + } + + if (!FreeSpaceChecked) + { + CheckFreeSpace(cancelToken); + } + + if (!FreeSpaceValid) + { + if (cancelToken.HasValue && cancelToken.Value.IsCancellationRequested) + { + return OperationOutcome.Cancelled; + } + else + { + return OperationOutcome.FreeSpaceCheckFailed; + } + } + + Log?.Write(LogType.Info, "Trimming..."); + + try + { + var info = new FileInfo(Filename); + if ((info.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) + { + try + { + Log?.Write(LogType.Info, "Attempting to remove ReadOnly attribute"); + File.SetAttributes(Filename, info.Attributes & ~FileAttributes.ReadOnly); + } + catch (Exception e) + { + Log?.Write(LogType.Error, e.ToString()); + return OperationOutcome.ReadOnlyFileCannotFix; + } + } + + if (info.Length != FileSizeB) + { + Log?.Write(LogType.Error, "File size has changed, cannot safely trim."); + return OperationOutcome.FileSizeChanged; + } + + var outfileStream = new FileStream(_filename, FileMode.Open, FileAccess.Write, FileShare.Write); + + try + { + +#if !XCI_TRIMMER_READ_ONLY_MODE + outfileStream.SetLength(TrimmedFileSizeB); +#endif + return OperationOutcome.Successful; + } + finally + { + outfileStream.Close(); + Reset(); + } + } + catch (Exception e) + { + Log?.Write(LogType.Error, e.ToString()); + return OperationOutcome.FileIOWriteError; + } + } + + public OperationOutcome Untrim(CancellationToken? cancelToken = null) + { + if (!FileOK) + { + return OperationOutcome.InvalidXCIFile; + } + + if (!CanBeUntrimmed) + { + return OperationOutcome.NoUntrimPossible; + } + + try + { + Log?.Write(LogType.Info, "Untrimming..."); + + var info = new FileInfo(Filename); + if ((info.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) + { + try + { + Log?.Write(LogType.Info, "Attempting to remove ReadOnly attribute"); + File.SetAttributes(Filename, info.Attributes & ~FileAttributes.ReadOnly); + } + catch (Exception e) + { + Log?.Write(LogType.Error, e.ToString()); + return OperationOutcome.ReadOnlyFileCannotFix; + } + } + + if (info.Length != FileSizeB) + { + Log?.Write(LogType.Error, "File size has changed, cannot safely untrim."); + return OperationOutcome.FileSizeChanged; + } + + var outfileStream = new FileStream(_filename, FileMode.Append, FileAccess.Write, FileShare.Write); + long bytesToWriteB = UntrimmedFileSizeB - FileSizeB; + + try + { + Stopwatch timedSw = Lambda.Timed(() => + { + WritePadding(outfileStream, bytesToWriteB, cancelToken); + }); + + if (timedSw.Elapsed.TotalSeconds > 0) + { + Log?.Write(LogType.Info, $"Wrote at {bytesToWriteB / (double)XCIFileTrimmer.BytesInAMegabyte / timedSw.Elapsed.TotalSeconds:N} Mb/sec"); + } + + if (cancelToken.HasValue && cancelToken.Value.IsCancellationRequested) + { + return OperationOutcome.Cancelled; + } + else + { + return OperationOutcome.Successful; + } + } + finally + { + outfileStream.Close(); + Reset(); + } + } + catch (Exception e) + { + Log?.Write(LogType.Error, e.ToString()); + return OperationOutcome.FileIOWriteError; + } + } + + private void WritePadding(FileStream outfileStream, long bytesToWriteB, CancellationToken? cancelToken = null) + { + long bytesLeftToWriteB = bytesToWriteB; + long writes = bytesLeftToWriteB / XCIFileTrimmer.BufferSize; + int write = 0; + + try + { + var buffer = new byte[BufferSize]; + Array.Fill(buffer, XCIFileTrimmer.PaddingByte); + + while (bytesLeftToWriteB > 0) + { + if (cancelToken.HasValue && cancelToken.Value.IsCancellationRequested) + { + return; + } + + long bytesToWrite = Math.Min(XCIFileTrimmer.BufferSize, bytesLeftToWriteB); + +#if !XCI_TRIMMER_READ_ONLY_MODE + outfileStream.Write(buffer, 0, (int)bytesToWrite); +#endif + + bytesLeftToWriteB -= bytesToWrite; + Log?.Progress(write, writes, "Writing padding data...", false); + write++; + } + } + finally + { + Log?.Progress(write, writes, "Writing padding data...", true); + } + } + + private void OpenReaders() + { + if (_binaryReader == null) + { + _fileStream = new FileStream(_filename, FileMode.Open, FileAccess.Read, FileShare.Read); + _binaryReader = new BinaryReader(_fileStream); + } + } + + private void CloseReaders() + { + if (_binaryReader != null && _binaryReader.BaseStream != null) + _binaryReader.Close(); + _binaryReader = null; + _fileStream = null; + GC.Collect(); + } + + private void ReadHeader() + { + try + { + OpenReaders(); + + try + { + // Attempt without key area + bool success = CheckAndReadHeader(false); + + if (!success) + { + // Attempt with key area + success = CheckAndReadHeader(true); + } + + _fileOK = success; + } + finally + { + CloseReaders(); + } + } + catch (Exception ex) + { + Log?.Write(LogType.Error, ex.Message); + _fileOK = false; + _dataSizeB = 0; + _cartSizeB = 0; + _fileSizeB = 0; + _offsetB = 0; + } + } + + private bool CheckAndReadHeader(bool assumeKeyArea) + { + // Read file size + _fileSizeB = _fileStream.Length; + if (_fileSizeB < 32 * 1024) + { + Log?.Write(LogType.Error, "The source file doesn't look like an XCI file as the data size is too small"); + return false; + } + + // Setup offset + _offsetB = (long)(assumeKeyArea ? XCIFileTrimmer.CartKeyAreaSize : 0); + + // Check header + Pos = _offsetB + XCIFileTrimmer.HeaderFilePos; + string head = System.Text.Encoding.ASCII.GetString(_binaryReader.ReadBytes(4)); + if (head != XCIFileTrimmer.HeaderMagicValue) + { + if (!assumeKeyArea) + { + Log?.Write(LogType.Warn, $"Incorrect header found, file mat contain a key area..."); + } + else + { + Log?.Write(LogType.Error, "The source file doesn't look like an XCI file as the header is corrupted"); + } + + return false; + } + + // Read Cart Size + Pos = _offsetB + XCIFileTrimmer.CartSizeFilePos; + byte cartSizeId = _binaryReader.ReadByte(); + if (!_cartSizesGB.TryGetValue(cartSizeId, out long cartSizeNGB)) + { + 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 + Pos = _offsetB + XCIFileTrimmer.DataSizeFilePos; + long records = (long)BitConverter.ToUInt32(_binaryReader.ReadBytes(4), 0); + _dataSizeB = RecordsToByte(records); + + return true; + } + } +} diff --git a/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs b/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs index 5dcd49af5..5cac4d13a 100644 --- a/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs +++ b/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs @@ -13,6 +13,7 @@ namespace Ryujinx.HLE.Generators var syntaxReceiver = (ServiceSyntaxReceiver)context.SyntaxReceiver; CodeGenerator generator = new CodeGenerator(); + generator.AppendLine("#nullable enable"); generator.AppendLine("using System;"); generator.EnterScope($"namespace Ryujinx.HLE.HOS.Services.Sm"); generator.EnterScope($"partial class IUserInterface"); @@ -58,6 +59,7 @@ namespace Ryujinx.HLE.Generators generator.LeaveScope(); generator.LeaveScope(); + generator.AppendLine("#nullable disable"); context.AddSource($"IUserInterface.g.cs", generator.ToString()); } diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/Hid.cs b/src/Ryujinx.HLE/HOS/Services/Hid/Hid.cs index dbcbe1870..66b5a5cba 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/Hid.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/Hid.cs @@ -5,6 +5,7 @@ using Ryujinx.HLE.Exceptions; using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory; using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common; +using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.DebugMouse; using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.DebugPad; using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Keyboard; using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Mouse; @@ -28,6 +29,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid public DebugPadDevice DebugPad; public TouchDevice Touchscreen; public MouseDevice Mouse; + public DebugMouseDevice DebugMouse; public KeyboardDevice Keyboard; public NpadDevices Npads; @@ -44,6 +46,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid CheckTypeSizeOrThrow>(0x2c8); CheckTypeSizeOrThrow>(0x2C38); CheckTypeSizeOrThrow>(0x350); + CheckTypeSizeOrThrow>(0x350); CheckTypeSizeOrThrow>(0x3D8); CheckTypeSizeOrThrow>(0x32000); CheckTypeSizeOrThrow(Horizon.HidSize); @@ -64,6 +67,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid DebugPad = new DebugPadDevice(_device, true); Touchscreen = new TouchDevice(_device, true); Mouse = new MouseDevice(_device, false); + DebugMouse = new DebugMouseDevice(_device, false); Keyboard = new KeyboardDevice(_device, false); Npads = new NpadDevices(_device, true); } diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/HidDevices/DebugMouseDevice.cs b/src/Ryujinx.HLE/HOS/Services/Hid/HidDevices/DebugMouseDevice.cs new file mode 100644 index 000000000..cb917444b --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Hid/HidDevices/DebugMouseDevice.cs @@ -0,0 +1,29 @@ +using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common; +using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.DebugMouse; + +namespace Ryujinx.HLE.HOS.Services.Hid +{ + public class DebugMouseDevice : BaseDevice + { + public DebugMouseDevice(Switch device, bool active) : base(device, active) { } + + public void Update() + { + ref RingLifo lifo = ref _device.Hid.SharedMemory.DebugMouse; + + ref DebugMouseState previousEntry = ref lifo.GetCurrentEntryRef(); + + DebugMouseState newState = new() + { + SamplingNumber = previousEntry.SamplingNumber + 1, + }; + + if (Active) + { + // TODO: This is a debug device only present in dev environment, do we want to support it? + } + + lifo.Write(ref newState); + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs b/src/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs index e3f505f37..556e35ea6 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs @@ -130,6 +130,26 @@ namespace Ryujinx.HLE.HOS.Services.Hid return ResultCode.Success; } + + [CommandCmif(26)] + // ActivateDebugMouse(nn::applet::AppletResourceUserId) + public ResultCode ActivateDebugMouse(ServiceCtx context) + { + long appletResourceUserId = context.RequestData.ReadInt64(); + + context.Device.Hid.DebugMouse.Active = true; + + // Initialize entries to avoid issues with some games. + + for (int entry = 0; entry < Hid.SharedMemEntryCount; entry++) + { + context.Device.Hid.DebugMouse.Update(); + } + + Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId }); + + return ResultCode.Success; + } [CommandCmif(31)] // ActivateKeyboard(nn::applet::AppletResourceUserId) diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugMouse/DebugMouseAttribute.cs b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugMouse/DebugMouseAttribute.cs new file mode 100644 index 000000000..0b55277d4 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugMouse/DebugMouseAttribute.cs @@ -0,0 +1,12 @@ +using System; + +namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.DebugMouse +{ + [Flags] + enum DebugMouseAttribute : uint + { + None = 0, + Transferable = 1 << 0, + IsConnected = 1 << 1, + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugMouse/DebugMouseButton.cs b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugMouse/DebugMouseButton.cs new file mode 100644 index 000000000..c07fa84af --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugMouse/DebugMouseButton.cs @@ -0,0 +1,15 @@ +using System; + +namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.DebugMouse +{ + [Flags] + enum DebugMouseButton : uint + { + None = 0, + Left = 1 << 0, + Right = 1 << 1, + Middle = 1 << 2, + Forward = 1 << 3, + Back = 1 << 4, + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugMouse/DebugMouseState.cs b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugMouse/DebugMouseState.cs new file mode 100644 index 000000000..e2860c9f5 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/DebugMouse/DebugMouseState.cs @@ -0,0 +1,19 @@ +using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common; +using System.Runtime.InteropServices; + +namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.DebugMouse +{ + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct DebugMouseState : ISampledDataStruct + { + public ulong SamplingNumber; + public int X; + public int Y; + public int DeltaX; + public int DeltaY; + public int WheelDeltaX; + public int WheelDeltaY; + public DebugMouseButton Buttons; + public DebugMouseAttribute Attributes; + } +} 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 d6283eb57..59d8f4489 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs @@ -1,5 +1,6 @@ using Ryujinx.Common.Memory; using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common; +using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.DebugMouse; using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.DebugPad; using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Keyboard; using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Mouse; @@ -44,6 +45,12 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory /// [FieldOffset(0x9A00)] public Array10 Npads; + + /// + /// Debug mouse. + /// + [FieldOffset(0x3DC00)] + public RingLifo DebugMouse; public static SharedMemory Create() { diff --git a/src/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj b/src/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj index 610229544..ebda97b46 100644 --- a/src/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj +++ b/src/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -17,7 +17,7 @@ - + diff --git a/src/Ryujinx.UI.Common/Models/XCITrimmerFileModel.cs b/src/Ryujinx.UI.Common/Models/XCITrimmerFileModel.cs new file mode 100644 index 000000000..05fa82920 --- /dev/null +++ b/src/Ryujinx.UI.Common/Models/XCITrimmerFileModel.cs @@ -0,0 +1,55 @@ +using Ryujinx.Common.Logging; +using Ryujinx.Common.Utilities; +using Ryujinx.UI.App.Common; + +namespace Ryujinx.UI.Common.Models +{ + public record XCITrimmerFileModel( + string Name, + string Path, + bool Trimmable, + bool Untrimmable, + long PotentialSavingsB, + long CurrentSavingsB, + int? PercentageProgress, + XCIFileTrimmer.OperationOutcome ProcessingOutcome) + { + public static XCITrimmerFileModel FromApplicationData(ApplicationData applicationData, XCIFileTrimmerLog logger) + { + var trimmer = new XCIFileTrimmer(applicationData.Path, logger); + + return new XCITrimmerFileModel( + applicationData.Name, + applicationData.Path, + trimmer.CanBeTrimmed, + trimmer.CanBeUntrimmed, + trimmer.DiskSpaceSavingsB, + trimmer.DiskSpaceSavedB, + null, + XCIFileTrimmer.OperationOutcome.Undetermined + ); + } + + public bool IsFailed + { + get + { + return ProcessingOutcome != XCIFileTrimmer.OperationOutcome.Undetermined && + ProcessingOutcome != XCIFileTrimmer.OperationOutcome.Successful; + } + } + + public virtual bool Equals(XCITrimmerFileModel obj) + { + if (obj == null) + return false; + else + return this.Path == obj.Path; + } + + public override int GetHashCode() + { + return this.Path.GetHashCode(); + } + } +} diff --git a/src/Ryujinx/App.axaml.cs b/src/Ryujinx/App.axaml.cs index 509deb34c..15ada201c 100644 --- a/src/Ryujinx/App.axaml.cs +++ b/src/Ryujinx/App.axaml.cs @@ -23,8 +23,10 @@ namespace Ryujinx.Ava { internal static string FormatTitle(LocaleKeys? windowTitleKey = null) => windowTitleKey is null - ? $"Ryujinx {Program.Version}" - : $"Ryujinx {Program.Version} - {LocaleManager.Instance[windowTitleKey.Value]}"; + ? $"{FullAppName} {Program.Version}" + : $"{FullAppName} {Program.Version} - {LocaleManager.Instance[windowTitleKey.Value]}"; + + public static readonly string FullAppName = ReleaseInformation.IsCanaryBuild ? "Ryujinx Canary" : "Ryujinx"; public static MainWindow MainWindow => Current! .ApplicationLifetime.Cast() diff --git a/src/Ryujinx/Assets/Locales/ar_SA.json b/src/Ryujinx/Assets/Locales/ar_SA.json index 22e270901..f2720b669 100644 --- a/src/Ryujinx/Assets/Locales/ar_SA.json +++ b/src/Ryujinx/Assets/Locales/ar_SA.json @@ -10,7 +10,10 @@ "SettingsTabSystemUseHypervisor": "استخدم مراقب الأجهزة الافتراضية", "MenuBarFile": "_ملف", "MenuBarFileOpenFromFile": "_تحميل تطبيق من ملف", + "MenuBarFileOpenFromFileError": "No applications found in selected file.", "MenuBarFileOpenUnpacked": "تحميل لُعْبَة غير محزومة", + "MenuBarFileLoadDlcFromFolder": "Load DLC From Folder", + "MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder", "MenuBarFileOpenEmuFolder": "‫فتح مجلد Ryujinx", "MenuBarFileOpenLogsFolder": "فتح مجلد السجلات", "MenuBarFileExit": "_خروج", @@ -103,6 +106,8 @@ "SettingsTabGeneralHideCursorOnIdle": "عند الخمول", "SettingsTabGeneralHideCursorAlways": "دائما", "SettingsTabGeneralGameDirectories": "مجلدات الألعاب", + "SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories", + "SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically", "SettingsTabGeneralAdd": "إضافة", "SettingsTabGeneralRemove": "إزالة", "SettingsTabSystem": "النظام", @@ -411,6 +416,7 @@ "GameListContextMenuToggleFavorite": "تعيين كمفضل", "GameListContextMenuToggleFavoriteToolTip": "تبديل الحالة المفضلة للعبة", "SettingsTabGeneralTheme": "السمة:", + "SettingsTabGeneralThemeAuto": "Auto", "SettingsTabGeneralThemeDark": "داكن", "SettingsTabGeneralThemeLight": "فاتح", "ControllerSettingsConfigureGeneral": "ضبط", @@ -561,6 +567,9 @@ "AddGameDirBoxTooltip": "أدخل مجلد اللعبة لإضافته إلى القائمة", "AddGameDirTooltip": "إضافة مجلد اللعبة إلى القائمة", "RemoveGameDirTooltip": "إزالة مجلد اللعبة المحدد", + "AddAutoloadDirBoxTooltip": "Enter an autoload directory to add to the list", + "AddAutoloadDirTooltip": "Add an autoload directory to the list", + "RemoveAutoloadDirTooltip": "Remove selected autoload directory", "CustomThemeCheckTooltip": "استخدم سمة أفالونيا المخصصة لواجهة المستخدم الرسومية لتغيير مظهر قوائم المحاكي", "CustomThemePathTooltip": "مسار سمة واجهة المستخدم المخصصة", "CustomThemeBrowseTooltip": "تصفح للحصول على سمة واجهة المستخدم المخصصة", @@ -606,6 +615,8 @@ "DebugLogTooltip": "طباعة رسائل سجل التصحيح في وحدة التحكم.\n\nاستخدم هذا فقط إذا طلب منك أحد الموظفين تحديدًا ذلك، لأنه سيجعل من الصعب قراءة السجلات وسيؤدي إلى تدهور أداء المحاكي.", "LoadApplicationFileTooltip": "افتح مستكشف الملفات لاختيار ملف متوافق مع سويتش لتحميله", "LoadApplicationFolderTooltip": "افتح مستكشف الملفات لاختيار تطبيق متوافق مع سويتش للتحميل", + "LoadDlcFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load DLC from", + "LoadTitleUpdatesFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load title updates from", "OpenRyujinxFolderTooltip": "فتح مجلد نظام ملفات ريوجينكس", "OpenRyujinxLogsTooltip": "يفتح المجلد الذي تتم كتابة السجلات إليه", "ExitTooltip": "الخروج من ريوجينكس", @@ -657,6 +668,8 @@ "OpenSetupGuideMessage": "فتح دليل الإعداد", "NoUpdate": "لا يوجد تحديث", "TitleUpdateVersionLabel": "الإصدار: {0}", + "TitleBundledUpdateVersionLabel": "Bundled: Version {0}", + "TitleBundledDlcLabel": "Bundled:", "RyujinxInfo": "ريوجينكس - معلومات", "RyujinxConfirm": "ريوجينكس - تأكيد", "FileDialogAllTypes": "كل الأنواع", @@ -714,9 +727,17 @@ "DlcWindowTitle": "إدارة المحتوى القابل للتنزيل لـ {0} ({1})", "ModWindowTitle": "إدارة التعديلات لـ {0} ({1})", "UpdateWindowTitle": "مدير تحديث العنوان", + "UpdateWindowUpdateAddedMessage": "{0} new update(s) added", + "UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.", "CheatWindowHeading": "الغش متوفر لـ {0} [{1}]", "BuildId": "معرف البناء:", + "DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.", "DlcWindowHeading": "المحتويات القابلة للتنزيل {0}", + "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", + "AutoloadUpdateAddedMessage": "{0} new update(s) added", + "AutoloadUpdateRemovedMessage": "{0} missing update(s) removed", "ModWindowHeading": "{0} تعديل", "UserProfilesEditProfile": "تعديل المحدد", "Cancel": "إلغاء", @@ -767,6 +788,7 @@ "GraphicsScalingFilterBilinear": "Bilinear", "GraphicsScalingFilterNearest": "Nearest", "GraphicsScalingFilterFsr": "FSR", + "GraphicsScalingFilterArea": "Area", "GraphicsScalingFilterLevelLabel": "المستوى", "GraphicsScalingFilterLevelTooltip": "اضبط مستوى وضوح FSR 1.0. الأعلى هو أكثر وضوحا.", "SmaaLow": "SMAA منخفض", diff --git a/src/Ryujinx/Assets/Locales/de_DE.json b/src/Ryujinx/Assets/Locales/de_DE.json index 94e372e2e..4004ec325 100644 --- a/src/Ryujinx/Assets/Locales/de_DE.json +++ b/src/Ryujinx/Assets/Locales/de_DE.json @@ -10,7 +10,10 @@ "SettingsTabSystemUseHypervisor": "Hypervisor verwenden", "MenuBarFile": "_Datei", "MenuBarFileOpenFromFile": "Datei _öffnen", + "MenuBarFileOpenFromFileError": "No applications found in selected file.", "MenuBarFileOpenUnpacked": "_Entpacktes Spiel öffnen", + "MenuBarFileLoadDlcFromFolder": "Load DLC From Folder", + "MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder", "MenuBarFileOpenEmuFolder": "Ryujinx-Ordner öffnen", "MenuBarFileOpenLogsFolder": "Logs-Ordner öffnen", "MenuBarFileExit": "_Beenden", @@ -103,6 +106,8 @@ "SettingsTabGeneralHideCursorOnIdle": "Mauszeiger bei Inaktivität ausblenden", "SettingsTabGeneralHideCursorAlways": "Immer", "SettingsTabGeneralGameDirectories": "Spielverzeichnisse", + "SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories", + "SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically", "SettingsTabGeneralAdd": "Hinzufügen", "SettingsTabGeneralRemove": "Entfernen", "SettingsTabSystem": "System", @@ -411,6 +416,7 @@ "GameListContextMenuToggleFavorite": "Als Favoriten hinzufügen/entfernen", "GameListContextMenuToggleFavoriteToolTip": "Aktiviert den Favoriten-Status des Spiels", "SettingsTabGeneralTheme": "Design:", + "SettingsTabGeneralThemeAuto": "Auto", "SettingsTabGeneralThemeDark": "Dunkel", "SettingsTabGeneralThemeLight": "Hell", "ControllerSettingsConfigureGeneral": "Konfigurieren", @@ -561,6 +567,9 @@ "AddGameDirBoxTooltip": "Gibt das Spielverzeichnis an, das der Liste hinzuzufügt wird", "AddGameDirTooltip": "Fügt ein neues Spielverzeichnis hinzu", "RemoveGameDirTooltip": "Entfernt das ausgewähltes Spielverzeichnis", + "AddAutoloadDirBoxTooltip": "Enter an autoload directory to add to the list", + "AddAutoloadDirTooltip": "Add an autoload directory to the list", + "RemoveAutoloadDirTooltip": "Remove selected autoload directory", "CustomThemeCheckTooltip": "Verwende ein eigenes Design für die Emulator-Benutzeroberfläche", "CustomThemePathTooltip": "Gibt den Pfad zum Design für die Emulator-Benutzeroberfläche an", "CustomThemeBrowseTooltip": "Ermöglicht die Suche nach einem benutzerdefinierten Design für die Emulator-Benutzeroberfläche", @@ -606,6 +615,8 @@ "DebugLogTooltip": "Ausgabe von Debug-Logs in der Konsole.\n\nVerwende diese Option nur auf ausdrückliche Anweisung von Ryujinx Entwicklern, da sie das Lesen der Protokolle erschwert und die Leistung des Emulators verschlechtert.", "LoadApplicationFileTooltip": "Öffnet die Dateiauswahl um Datei zu laden, welche mit der Switch kompatibel ist", "LoadApplicationFolderTooltip": "Öffnet die Dateiauswahl um ein Spiel zu laden, welches mit der Switch kompatibel ist", + "LoadDlcFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load DLC from", + "LoadTitleUpdatesFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load title updates from", "OpenRyujinxFolderTooltip": "Öffnet den Ordner, der das Ryujinx Dateisystem enthält", "OpenRyujinxLogsTooltip": "Öffnet den Ordner, in welchem die Logs gespeichert werden", "ExitTooltip": "Beendet Ryujinx", @@ -657,6 +668,8 @@ "OpenSetupGuideMessage": "Öffne den 'Setup Guide'", "NoUpdate": "Kein Update", "TitleUpdateVersionLabel": "Version {0} - {1}", + "TitleBundledUpdateVersionLabel": "Bundled: Version {0}", + "TitleBundledDlcLabel": "Bundled:", "RyujinxInfo": "Ryujinx - Info", "RyujinxConfirm": "Ryujinx - Bestätigung", "FileDialogAllTypes": "Alle Typen", @@ -714,9 +727,17 @@ "DlcWindowTitle": "Spiel-DLC verwalten", "ModWindowTitle": "Manage Mods for {0} ({1})", "UpdateWindowTitle": "Spiel-Updates verwalten", + "UpdateWindowUpdateAddedMessage": "{0} new update(s) added", + "UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.", "CheatWindowHeading": "Cheats verfügbar für {0} [{1}]", + "DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.", "BuildId": "BuildId:", "DlcWindowHeading": "DLC verfügbar für {0} [{1}]", + "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", + "AutoloadUpdateAddedMessage": "{0} new update(s) added", + "AutoloadUpdateRemovedMessage": "{0} missing update(s) removed", "ModWindowHeading": "{0} Mod(s)", "UserProfilesEditProfile": "Profil bearbeiten", "Cancel": "Abbrechen", @@ -767,6 +788,7 @@ "GraphicsScalingFilterBilinear": "Bilinear", "GraphicsScalingFilterNearest": "Nächstes", "GraphicsScalingFilterFsr": "FSR", + "GraphicsScalingFilterArea": "Area", "GraphicsScalingFilterLevelLabel": "Stufe", "GraphicsScalingFilterLevelTooltip": "FSR 1.0 Schärfelevel festlegen. Höher ist schärfer.", "SmaaLow": "SMAA Niedrig", diff --git a/src/Ryujinx/Assets/Locales/el_GR.json b/src/Ryujinx/Assets/Locales/el_GR.json index 89389d337..56940ffc9 100644 --- a/src/Ryujinx/Assets/Locales/el_GR.json +++ b/src/Ryujinx/Assets/Locales/el_GR.json @@ -10,7 +10,10 @@ "SettingsTabSystemUseHypervisor": "Χρήση Hypervisor", "MenuBarFile": "_Αρχείο", "MenuBarFileOpenFromFile": "_Φόρτωση Αρχείου Εφαρμογής", + "MenuBarFileOpenFromFileError": "No applications found in selected file.", "MenuBarFileOpenUnpacked": "Φόρτωση Απακετάριστου _Παιχνιδιού", + "MenuBarFileLoadDlcFromFolder": "Load DLC From Folder", + "MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder", "MenuBarFileOpenEmuFolder": "Άνοιγμα Φακέλου Ryujinx", "MenuBarFileOpenLogsFolder": "Άνοιγμα Φακέλου Καταγραφής", "MenuBarFileExit": "_Έξοδος", @@ -103,6 +106,8 @@ "SettingsTabGeneralHideCursorOnIdle": "Απόκρυψη Δρομέα στην Αδράνεια", "SettingsTabGeneralHideCursorAlways": "Πάντα", "SettingsTabGeneralGameDirectories": "Τοποθεσίες παιχνιδιών", + "SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories", + "SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically", "SettingsTabGeneralAdd": "Προσθήκη", "SettingsTabGeneralRemove": "Αφαίρεση", "SettingsTabSystem": "Σύστημα", @@ -411,6 +416,7 @@ "GameListContextMenuToggleFavorite": "Εναλλαγή Αγαπημένου", "GameListContextMenuToggleFavoriteToolTip": "Εναλλαγή της Κατάστασης Αγαπημένο του Παιχνιδιού", "SettingsTabGeneralTheme": "Theme:", + "SettingsTabGeneralThemeAuto": "Auto", "SettingsTabGeneralThemeDark": "Dark", "SettingsTabGeneralThemeLight": "Light", "ControllerSettingsConfigureGeneral": "Παραμέτρων", @@ -561,6 +567,9 @@ "AddGameDirBoxTooltip": "Εισαγάγετε μία τοποθεσία παιχνιδιών για προσθήκη στη λίστα", "AddGameDirTooltip": "Προσθέστε μία τοποθεσία παιχνιδιών στη λίστα", "RemoveGameDirTooltip": "Αφαιρέστε την επιλεγμένη τοποθεσία παιχνιδιών", + "AddAutoloadDirBoxTooltip": "Enter an autoload directory to add to the list", + "AddAutoloadDirTooltip": "Add an autoload directory to the list", + "RemoveAutoloadDirTooltip": "Remove selected autoload directory", "CustomThemeCheckTooltip": "Ενεργοποίηση ή απενεργοποίηση προσαρμοσμένων θεμάτων στο GUI", "CustomThemePathTooltip": "Διαδρομή προς το προσαρμοσμένο θέμα GUI", "CustomThemeBrowseTooltip": "Αναζητήστε ένα προσαρμοσμένο θέμα GUI", @@ -606,6 +615,8 @@ "DebugLogTooltip": "Ενεργοποιεί την εκτύπωση μηνυμάτων αρχείου καταγραφής εντοπισμού σφαλμάτων", "LoadApplicationFileTooltip": "Ανοίξτε έναν επιλογέα αρχείων για να επιλέξετε ένα αρχείο συμβατό με το Switch για φόρτωση", "LoadApplicationFolderTooltip": "Ανοίξτε έναν επιλογέα αρχείων για να επιλέξετε μία μη συσκευασμένη εφαρμογή, συμβατή με το Switch για φόρτωση", + "LoadDlcFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load DLC from", + "LoadTitleUpdatesFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load title updates from", "OpenRyujinxFolderTooltip": "Ανοίξτε το φάκελο συστήματος αρχείων Ryujinx", "OpenRyujinxLogsTooltip": "Ανοίξτε το φάκελο στον οποίο διατηρούνται τα αρχεία καταγραφής", "ExitTooltip": "Έξοδος από το Ryujinx", @@ -657,6 +668,8 @@ "OpenSetupGuideMessage": "Ανοίξτε τον Οδηγό Εγκατάστασης.", "NoUpdate": "Καμία Eνημέρωση", "TitleUpdateVersionLabel": "Version {0} - {1}", + "TitleBundledUpdateVersionLabel": "Bundled: Version {0}", + "TitleBundledDlcLabel": "Bundled:", "RyujinxInfo": "Ryujinx - Πληροφορίες", "RyujinxConfirm": "Ryujinx - Επιβεβαίωση", "FileDialogAllTypes": "Όλοι οι τύποι", @@ -714,9 +727,17 @@ "DlcWindowTitle": "Downloadable Content Manager", "ModWindowTitle": "Manage Mods for {0} ({1})", "UpdateWindowTitle": "Διαχειριστής Ενημερώσεων Τίτλου", + "UpdateWindowUpdateAddedMessage": "{0} new update(s) added", + "UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.", "CheatWindowHeading": "Διαθέσιμα Cheats για {0} [{1}]", "BuildId": "BuildId:", + "DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.", "DlcWindowHeading": "{0} Downloadable Content(s) available for {1} ({2})", + "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", + "AutoloadUpdateAddedMessage": "{0} new update(s) added", + "AutoloadUpdateRemovedMessage": "{0} missing update(s) removed", "ModWindowHeading": "{0} Mod(s)", "UserProfilesEditProfile": "Επεξεργασία Επιλεγμένων", "Cancel": "Ακύρωση", @@ -767,6 +788,7 @@ "GraphicsScalingFilterBilinear": "Bilinear", "GraphicsScalingFilterNearest": "Nearest", "GraphicsScalingFilterFsr": "FSR", + "GraphicsScalingFilterArea": "Area", "GraphicsScalingFilterLevelLabel": "Επίπεδο", "GraphicsScalingFilterLevelTooltip": "Set FSR 1.0 sharpening level. Higher is sharper.", "SmaaLow": "Χαμηλό SMAA", diff --git a/src/Ryujinx/Assets/Locales/en_US.json b/src/Ryujinx/Assets/Locales/en_US.json index 68b48146b..faa53230d 100644 --- a/src/Ryujinx/Assets/Locales/en_US.json +++ b/src/Ryujinx/Assets/Locales/en_US.json @@ -33,6 +33,7 @@ "MenuBarToolsManageFileTypes": "Manage file types", "MenuBarToolsInstallFileTypes": "Install file types", "MenuBarToolsUninstallFileTypes": "Uninstall file types", + "MenuBarToolsXCITrimmer": "Trim XCI Files", "MenuBarView": "_View", "MenuBarViewWindow": "Window Size", "MenuBarViewWindow720": "720p", @@ -84,8 +85,11 @@ "GameListContextMenuOpenModsDirectoryToolTip": "Opens the directory which contains Application's Mods", "GameListContextMenuOpenSdModsDirectory": "Open Atmosphere Mods Directory", "GameListContextMenuOpenSdModsDirectoryToolTip": "Opens the alternative SD card Atmosphere directory which contains Application's Mods. Useful for mods that are packaged for real hardware.", + "GameListContextMenuTrimXCI": "Check and Trim XCI File", + "GameListContextMenuTrimXCIToolTip": "Check and Trim XCI File to Save Disk Space", "StatusBarGamesLoaded": "{0}/{1} Games Loaded", "StatusBarSystemVersion": "System Version: {0}", + "StatusBarXCIFileTrimming": "Trimming XCI File '{0}'", "LinuxVmMaxMapCountDialogTitle": "Low limit for memory mappings detected", "LinuxVmMaxMapCountDialogTextPrimary": "Would you like to increase the value of vm.max_map_count to {0}", "LinuxVmMaxMapCountDialogTextSecondary": "Some games might try to create more memory mappings than currently allowed. Ryujinx will crash as soon as this limit gets exceeded.", @@ -400,6 +404,8 @@ "InputDialogTitle": "Input Dialog", "InputDialogOk": "OK", "InputDialogCancel": "Cancel", + "InputDialogCancelling": "Cancelling", + "InputDialogClose": "Close", "InputDialogAddNewProfileTitle": "Choose the Profile Name", "InputDialogAddNewProfileHeader": "Please Enter a Profile Name", "InputDialogAddNewProfileSubtext": "(Max Length: {0})", @@ -439,13 +445,13 @@ "DialogNcaExtractionMessage": "Extracting {0} section from {1}...", "DialogNcaExtractionTitle": "Ryujinx - NCA Section Extractor", "DialogNcaExtractionMainNcaNotFoundErrorMessage": "Extraction failure. The main NCA was not present in the selected file.", - "DialogNcaExtractionCheckLogErrorMessage": "Extraction failure. Read the log file for further information.", + "DialogNcaExtractionCheckLogErrorMessage": "Extraction failed. Please check the log file for more details.", "DialogNcaExtractionSuccessMessage": "Extraction completed successfully.", - "DialogUpdaterConvertFailedMessage": "Failed to convert the current Ryujinx version.", - "DialogUpdaterCancelUpdateMessage": "Cancelling Update!", - "DialogUpdaterAlreadyOnLatestVersionMessage": "You are already using the most updated version of Ryujinx!", - "DialogUpdaterFailedToGetVersionMessage": "An error has occurred when trying to get release information from GitHub Release. This can be caused if a new release is being compiled by GitHub Actions. Try again in a few minutes.", - "DialogUpdaterConvertFailedGithubMessage": "Failed to convert the received Ryujinx version from Github Release.", + "DialogUpdaterConvertFailedMessage": "Unable to convert the current Ryujinx version.", + "DialogUpdaterCancelUpdateMessage": "Update canceled!", + "DialogUpdaterAlreadyOnLatestVersionMessage": "You are already using the latest version of Ryujinx!", + "DialogUpdaterFailedToGetVersionMessage": "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.", + "DialogUpdaterConvertFailedGithubMessage": "Failed to convert the Ryujinx version received from GitHub.", "DialogUpdaterDownloadingMessage": "Downloading Update...", "DialogUpdaterExtractionMessage": "Extracting Update...", "DialogUpdaterRenamingMessage": "Renaming Update...", @@ -455,7 +461,7 @@ "DialogUpdaterNoInternetMessage": "You are not connected to the Internet!", "DialogUpdaterNoInternetSubMessage": "Please verify that you have a working Internet connection!", "DialogUpdaterDirtyBuildMessage": "You Cannot update a Dirty build of Ryujinx!", - "DialogUpdaterDirtyBuildSubMessage": "Please download Ryujinx at https://https://github.com/GreemDev/Ryujinx/releases/ if you are looking for a supported version.", + "DialogUpdaterDirtyBuildSubMessage": "Please download Ryujinx at https://github.com/GreemDev/Ryujinx/releases/ if you are looking for a supported version.", "DialogRestartRequiredMessage": "Restart Required", "DialogThemeRestartMessage": "Theme has been saved. A restart is needed to apply the theme.", "DialogThemeRestartSubMessage": "Do you want to restart", @@ -468,6 +474,7 @@ "DialogUninstallFileTypesSuccessMessage": "Successfully uninstalled file types!", "DialogUninstallFileTypesErrorMessage": "Failed to uninstall file types.", "DialogOpenSettingsWindowLabel": "Open Settings Window", + "DialogOpenXCITrimmerWindowLabel": "XCI Trimmer Window", "DialogControllerAppletTitle": "Controller Applet", "DialogMessageDialogErrorExceptionMessage": "Error displaying Message Dialog: {0}", "DialogSoftwareKeyboardErrorExceptionMessage": "Error displaying Software Keyboard: {0}", @@ -670,6 +677,12 @@ "TitleUpdateVersionLabel": "Version {0}", "TitleBundledUpdateVersionLabel": "Bundled: Version {0}", "TitleBundledDlcLabel": "Bundled:", + "TitleXCIStatusPartialLabel": "Partial", + "TitleXCIStatusTrimmableLabel": "Untrimmed", + "TitleXCIStatusUntrimmableLabel": "Trimmed", + "TitleXCIStatusFailedLabel": "(Failed)", + "TitleXCICanSaveLabel": "Save {0:n0} Mb", + "TitleXCISavingLabel": "Saved {0:n0} Mb", "RyujinxInfo": "Ryujinx - Info", "RyujinxConfirm": "Ryujinx - Confirmation", "FileDialogAllTypes": "All types", @@ -722,17 +735,43 @@ "SelectDlcDialogTitle": "Select DLC files", "SelectUpdateDialogTitle": "Select update files", "SelectModDialogTitle": "Select mod directory", + "TrimXCIFileDialogTitle": "Check and Trim XCI File", + "TrimXCIFileDialogPrimaryText": "This function will first check the empty space and then trim the XCI File to save disk space.", + "TrimXCIFileDialogSecondaryText": "Current File Size: {0:n} MB\nGame Data Size: {1:n} MB\nDisk Space Savings: {2:n} MB", + "TrimXCIFileNoTrimNecessary": "XCI File does not need to be trimmed. Check logs for further details", + "TrimXCIFileNoUntrimPossible": "XCI File cannot be untrimmed. Check logs for further details", + "TrimXCIFileReadOnlyFileCannotFix": "XCI File is Read Only and could not be made writable. Check logs for further details", + "TrimXCIFileFileSizeChanged": "XCI File has changed in size since it was scanned. Please check the file is not being written to and try again.", + "TrimXCIFileFreeSpaceCheckFailed": "XCI File has data in the free space area, it is not safe to trim", + "TrimXCIFileInvalidXCIFile": "XCI File contains invalid data. Check logs for further details", + "TrimXCIFileFileIOWriteError": "XCI File could not be opened for writing. Check logs for further details", + "TrimXCIFileFailedPrimaryText": "Trimming of the XCI file failed", + "TrimXCIFileCancelled": "The operation was cancelled", + "TrimXCIFileFileUndertermined": "No operation was performed", "UserProfileWindowTitle": "User Profiles Manager", "CheatWindowTitle": "Cheats Manager", "DlcWindowTitle": "Manage Downloadable Content for {0} ({1})", "ModWindowTitle": "Manage Mods for {0} ({1})", "UpdateWindowTitle": "Title Update Manager", + "XCITrimmerWindowTitle": "XCI File Trimmer", + "XCITrimmerTitleStatusCount": "{0} of {1} Title(s) Selected", + "XCITrimmerTitleStatusCountWithFilter": "{0} of {1} Title(s) Selected ({2} displayed)", + "XCITrimmerTitleStatusTrimming": "Trimming {0} Title(s)...", + "XCITrimmerTitleStatusUntrimming": "Untrimming {0} Title(s)...", + "XCITrimmerTitleStatusFailed": "Failed", + "XCITrimmerPotentialSavings": "Potential Savings", + "XCITrimmerActualSavings": "Actual Savings", + "XCITrimmerSavingsMb": "{0:n0} Mb", + "XCITrimmerSelectDisplayed": "Select Shown", + "XCITrimmerDeselectDisplayed": "Deselect Shown", + "XCITrimmerSortName": "Title", + "XCITrimmerSortSaved": "Space Savings", "UpdateWindowUpdateAddedMessage": "{0} new update(s) added", "UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.", "CheatWindowHeading": "Cheats Available for {0} [{1}]", "BuildId": "BuildId:", "DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.", - "DlcWindowHeading": "{0} Downloadable Content(s)", + "DlcWindowHeading": "{0} Downloadable Content(s) available for {1} ({2})", "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", @@ -740,6 +779,7 @@ "AutoloadUpdateRemovedMessage": "{0} missing update(s) removed", "ModWindowHeading": "{0} Mod(s)", "UserProfilesEditProfile": "Edit Selected", + "Continue": "Continue", "Cancel": "Cancel", "Save": "Save", "Discard": "Discard", diff --git a/src/Ryujinx/Assets/Locales/es_ES.json b/src/Ryujinx/Assets/Locales/es_ES.json index d6eb8017a..bbc86ed0c 100644 --- a/src/Ryujinx/Assets/Locales/es_ES.json +++ b/src/Ryujinx/Assets/Locales/es_ES.json @@ -10,7 +10,10 @@ "SettingsTabSystemUseHypervisor": "Usar hipervisor", "MenuBarFile": "_Archivo", "MenuBarFileOpenFromFile": "_Cargar aplicación desde un archivo", + "MenuBarFileOpenFromFileError": "No applications found in selected file.", "MenuBarFileOpenUnpacked": "Cargar juego _desempaquetado", + "MenuBarFileLoadDlcFromFolder": "Load DLC From Folder", + "MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder", "MenuBarFileOpenEmuFolder": "Abrir carpeta de Ryujinx", "MenuBarFileOpenLogsFolder": "Abrir carpeta de registros", "MenuBarFileExit": "_Salir", @@ -103,6 +106,8 @@ "SettingsTabGeneralHideCursorOnIdle": "Ocultar cursor cuando esté inactivo", "SettingsTabGeneralHideCursorAlways": "Siempre", "SettingsTabGeneralGameDirectories": "Carpetas de juegos", + "SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories", + "SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically", "SettingsTabGeneralAdd": "Agregar", "SettingsTabGeneralRemove": "Quitar", "SettingsTabSystem": "Sistema", @@ -411,6 +416,7 @@ "GameListContextMenuToggleFavorite": "Marcar favorito", "GameListContextMenuToggleFavoriteToolTip": "Marca o desmarca el juego como favorito", "SettingsTabGeneralTheme": "Tema:", + "SettingsTabGeneralThemeAuto": "Auto", "SettingsTabGeneralThemeDark": "Oscuro", "SettingsTabGeneralThemeLight": "Claro", "ControllerSettingsConfigureGeneral": "Configurar", @@ -561,6 +567,9 @@ "AddGameDirBoxTooltip": "Elige un directorio de juegos para mostrar en la ventana principal", "AddGameDirTooltip": "Agrega un directorio de juegos a la lista", "RemoveGameDirTooltip": "Quita el directorio seleccionado de la lista", + "AddAutoloadDirBoxTooltip": "Enter an autoload directory to add to the list", + "AddAutoloadDirTooltip": "Add an autoload directory to the list", + "RemoveAutoloadDirTooltip": "Remove selected autoload directory", "CustomThemeCheckTooltip": "Activa o desactiva los temas personalizados para la interfaz", "CustomThemePathTooltip": "Carpeta que contiene los temas personalizados para la interfaz", "CustomThemeBrowseTooltip": "Busca un tema personalizado para la interfaz", @@ -606,6 +615,8 @@ "DebugLogTooltip": "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.", "LoadApplicationFileTooltip": "Abre el explorador de archivos para elegir un archivo compatible con Switch para cargar", "LoadApplicationFolderTooltip": "Abre el explorador de archivos para elegir un archivo desempaquetado y compatible con Switch para cargar", + "LoadDlcFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load DLC from", + "LoadTitleUpdatesFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load title updates from", "OpenRyujinxFolderTooltip": "Abre la carpeta de sistema de Ryujinx", "OpenRyujinxLogsTooltip": "Abre la carpeta en la que se guardan los registros", "ExitTooltip": "Cierra Ryujinx", @@ -657,6 +668,8 @@ "OpenSetupGuideMessage": "Abrir la guía de instalación", "NoUpdate": "No actualizado", "TitleUpdateVersionLabel": "Versión {0} - {1}", + "TitleBundledUpdateVersionLabel": "Bundled: Version {0}", + "TitleBundledDlcLabel": "Bundled:", "RyujinxInfo": "Ryujinx - Info", "RyujinxConfirm": "Ryujinx - Confirmación", "FileDialogAllTypes": "Todos los tipos", @@ -714,9 +727,16 @@ "DlcWindowTitle": "Administrar contenido descargable", "ModWindowTitle": "Manage Mods for {0} ({1})", "UpdateWindowTitle": "Administrar actualizaciones", + "UpdateWindowUpdateAddedMessage": "{0} new update(s) added", + "UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.", "CheatWindowHeading": "Cheats disponibles para {0} [{1}]", "BuildId": "Id de compilación:", "DlcWindowHeading": "Contenido descargable disponible para {0} [{1}]", + "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", + "AutoloadUpdateAddedMessage": "{0} new update(s) added", + "AutoloadUpdateRemovedMessage": "{0} missing update(s) removed", "ModWindowHeading": "{0} Mod(s)", "UserProfilesEditProfile": "Editar selección", "Cancel": "Cancelar", @@ -767,6 +787,7 @@ "GraphicsScalingFilterBilinear": "Bilinear\n", "GraphicsScalingFilterNearest": "Cercano", "GraphicsScalingFilterFsr": "FSR", + "GraphicsScalingFilterArea": "Area", "GraphicsScalingFilterLevelLabel": "Nivel", "GraphicsScalingFilterLevelTooltip": "Ajuste el nivel de nitidez FSR 1.0. Mayor es más nítido.", "SmaaLow": "SMAA Bajo", diff --git a/src/Ryujinx/Assets/Locales/fr_FR.json b/src/Ryujinx/Assets/Locales/fr_FR.json index df8adac00..0c673f719 100644 --- a/src/Ryujinx/Assets/Locales/fr_FR.json +++ b/src/Ryujinx/Assets/Locales/fr_FR.json @@ -100,7 +100,7 @@ "SettingsTabGeneralCheckUpdatesOnLaunch": "Vérifier les mises à jour au démarrage", "SettingsTabGeneralShowConfirmExitDialog": "Afficher le message de \"Confirmation de sortie\"", "SettingsTabGeneralRememberWindowState": "Mémoriser la taille/position de la fenêtre", - "SettingsTabGeneralShowTitleBar": "Show Title Bar (Requires restart)", + "SettingsTabGeneralShowTitleBar": "Afficher Barre de Titre (Nécessite redémarrage)", "SettingsTabGeneralHideCursor": "Masquer le Curseur :", "SettingsTabGeneralHideCursorNever": "Jamais", "SettingsTabGeneralHideCursorOnIdle": "Masquer le curseur si inactif", @@ -151,7 +151,7 @@ "SettingsTabSystemAudioBackendSDL2": "SDL2", "SettingsTabSystemHacks": "Hacks", "SettingsTabSystemHacksNote": "Cela peut causer des instabilités", - "SettingsTabSystemDramSize": "Taille de la DRAM:", + "SettingsTabSystemDramSize": "Taille de la DRAM :", "SettingsTabSystemDramSize4GiB": "4GiO", "SettingsTabSystemDramSize6GiB": "6GiO", "SettingsTabSystemDramSize8GiB": "8GiO", @@ -181,7 +181,7 @@ "SettingsTabGraphicsAspectRatio32x9": "32:9", "SettingsTabGraphicsAspectRatioStretch": "Étirer pour remplir la fenêtre", "SettingsTabGraphicsDeveloperOptions": "Options développeur", - "SettingsTabGraphicsShaderDumpPath": "Chemin du dossier de copie des shaders:", + "SettingsTabGraphicsShaderDumpPath": "Chemin du dossier de copie des shaders :", "SettingsTabLogging": "Journaux", "SettingsTabLoggingLogging": "Journaux", "SettingsTabLoggingEnableLoggingToFile": "Activer la sauvegarde des journaux vers un fichier", @@ -387,7 +387,7 @@ "UserProfilesSelectedUserProfile": "Profil utilisateur sélectionné :", "UserProfilesSaveProfileName": "Enregistrer le nom du profil", "UserProfilesChangeProfileImage": "Changer l'image du profil", - "UserProfilesAvailableUserProfiles": "Profils utilisateurs disponibles:", + "UserProfilesAvailableUserProfiles": "Profils utilisateurs disponibles :", "UserProfilesAddNewProfile": "Créer un profil", "UserProfilesDelete": "Supprimer", "UserProfilesClose": "Fermer", @@ -669,7 +669,7 @@ "NoUpdate": "Aucune mise à jour", "TitleUpdateVersionLabel": "Version {0}", "TitleBundledUpdateVersionLabel": "Inclus avec le jeu: Version {0}", - "TitleBundledDlcLabel": "Inclus avec le jeu:", + "TitleBundledDlcLabel": "Inclus avec le jeu :", "RyujinxInfo": "Ryujinx - Info", "RyujinxConfirm": "Ryujinx - Confirmation", "FileDialogAllTypes": "Tous les types", diff --git a/src/Ryujinx/Assets/Locales/he_IL.json b/src/Ryujinx/Assets/Locales/he_IL.json index eb7ccf322..cac3fbf53 100644 --- a/src/Ryujinx/Assets/Locales/he_IL.json +++ b/src/Ryujinx/Assets/Locales/he_IL.json @@ -10,7 +10,10 @@ "SettingsTabSystemUseHypervisor": "השתמש ב Hypervisor", "MenuBarFile": "_קובץ", "MenuBarFileOpenFromFile": "_טען יישום מקובץ", + "MenuBarFileOpenFromFileError": "No applications found in selected file.", "MenuBarFileOpenUnpacked": "טען משחק _שאינו ארוז", + "MenuBarFileLoadDlcFromFolder": "Load DLC From Folder", + "MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder", "MenuBarFileOpenEmuFolder": "פתח את תיקיית ריוג'ינקס", "MenuBarFileOpenLogsFolder": "פתח את תיקיית קבצי הלוג", "MenuBarFileExit": "_יציאה", @@ -103,6 +106,8 @@ "SettingsTabGeneralHideCursorOnIdle": "במצב סרק", "SettingsTabGeneralHideCursorAlways": "תמיד", "SettingsTabGeneralGameDirectories": "תקיות משחקים", + "SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories", + "SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically", "SettingsTabGeneralAdd": "הוסף", "SettingsTabGeneralRemove": "הסר", "SettingsTabSystem": "מערכת", @@ -411,6 +416,7 @@ "GameListContextMenuToggleFavorite": "למתג העדפה", "GameListContextMenuToggleFavoriteToolTip": "למתג סטטוס העדפה של משחק", "SettingsTabGeneralTheme": "ערכת נושא:", + "SettingsTabGeneralThemeAuto": "Auto", "SettingsTabGeneralThemeDark": "כהה", "SettingsTabGeneralThemeLight": "בהיר", "ControllerSettingsConfigureGeneral": "הגדר", @@ -561,6 +567,9 @@ "AddGameDirBoxTooltip": "הזן תקיית משחקים כדי להוסיף לרשימה", "AddGameDirTooltip": "הוסף תקיית משחקים לרשימה", "RemoveGameDirTooltip": "הסר את תקיית המשחקים שנבחרה", + "AddAutoloadDirBoxTooltip": "Enter an autoload directory to add to the list", + "AddAutoloadDirTooltip": "Add an autoload directory to the list", + "RemoveAutoloadDirTooltip": "Remove selected autoload directory", "CustomThemeCheckTooltip": "השתמש בעיצוב מותאם אישית של אבלוניה עבור ה-ממשק הגראפי כדי לשנות את המראה של תפריטי האמולטור", "CustomThemePathTooltip": "נתיב לערכת נושא לממשק גראפי מותאם אישית", "CustomThemeBrowseTooltip": "חפש עיצוב ממשק גראפי מותאם אישית", @@ -606,6 +615,8 @@ "DebugLogTooltip": "מדפיס הודעות יומן ניפוי באגים בשורת הפקודות.", "LoadApplicationFileTooltip": "פתח סייר קבצים כדי לבחור קובץ תואם סוויץ' לטעינה", "LoadApplicationFolderTooltip": "פתח סייר קבצים כדי לבחור יישום תואם סוויץ', לא ארוז לטעינה.", + "LoadDlcFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load DLC from", + "LoadTitleUpdatesFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load title updates from", "OpenRyujinxFolderTooltip": "פתח את תיקיית מערכת הקבצים ריוג'ינקס", "OpenRyujinxLogsTooltip": "פותח את התיקיה שאליה נכתבים רישומים", "ExitTooltip": "צא מריוג'ינקס", @@ -657,6 +668,8 @@ "OpenSetupGuideMessage": "פתח מדריך התקנה", "NoUpdate": "אין עדכון", "TitleUpdateVersionLabel": "גרסה {0}", + "TitleBundledUpdateVersionLabel": "Bundled: Version {0}", + "TitleBundledDlcLabel": "Bundled:", "RyujinxInfo": "ריוג'ינקס - מידע", "RyujinxConfirm": "ריוג'ינקס - אישור", "FileDialogAllTypes": "כל הסוגים", @@ -714,9 +727,17 @@ "DlcWindowTitle": "נהל הרחבות משחק עבור {0} ({1})", "ModWindowTitle": "Manage Mods for {0} ({1})", "UpdateWindowTitle": "נהל עדכוני משחקים", + "UpdateWindowUpdateAddedMessage": "{0} new update(s) added", + "UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.", "CheatWindowHeading": "צ'יטים זמינים עבור {0} [{1}]", "BuildId": "מזהה בניה:", + "DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.", "DlcWindowHeading": "{0} הרחבות משחק", + "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", + "AutoloadUpdateAddedMessage": "{0} new update(s) added", + "AutoloadUpdateRemovedMessage": "{0} missing update(s) removed", "ModWindowHeading": "{0} מוד(ים)", "UserProfilesEditProfile": "ערוך נבחר/ים", "Cancel": "בטל", @@ -767,6 +788,7 @@ "GraphicsScalingFilterBilinear": "Bilinear", "GraphicsScalingFilterNearest": "Nearest", "GraphicsScalingFilterFsr": "FSR", + "GraphicsScalingFilterArea": "Area", "GraphicsScalingFilterLevelLabel": "רמה", "GraphicsScalingFilterLevelTooltip": "Set FSR 1.0 sharpening level. Higher is sharper.", "SmaaLow": "SMAA נמוך", diff --git a/src/Ryujinx/Assets/Locales/it_IT.json b/src/Ryujinx/Assets/Locales/it_IT.json index 87c8e6bab..419a5dd2b 100644 --- a/src/Ryujinx/Assets/Locales/it_IT.json +++ b/src/Ryujinx/Assets/Locales/it_IT.json @@ -788,12 +788,12 @@ "GraphicsScalingFilterBilinear": "Bilineare", "GraphicsScalingFilterNearest": "Nearest", "GraphicsScalingFilterFsr": "FSR", + "GraphicsScalingFilterArea": "Area", "GraphicsScalingFilterLevelLabel": "Livello", "GraphicsScalingFilterLevelTooltip": "Imposta il livello di nitidezza di FSR 1.0. Valori più alti comportano una maggiore nitidezza.", "SmaaLow": "SMAA Basso", "SmaaMedium": "SMAA Medio", "SmaaHigh": "SMAA Alto", - "GraphicsScalingFilterArea": "Area", "SmaaUltra": "SMAA Ultra", "UserEditorTitle": "Modificare L'Utente", "UserEditorTitleCreate": "Crea Un Utente", diff --git a/src/Ryujinx/Assets/Locales/ja_JP.json b/src/Ryujinx/Assets/Locales/ja_JP.json index d43dedc2a..b2c0a506e 100644 --- a/src/Ryujinx/Assets/Locales/ja_JP.json +++ b/src/Ryujinx/Assets/Locales/ja_JP.json @@ -10,7 +10,10 @@ "SettingsTabSystemUseHypervisor": "ハイパーバイザーを使用", "MenuBarFile": "ファイル(_F)", "MenuBarFileOpenFromFile": "ファイルからアプリケーションをロード(_L)", + "MenuBarFileOpenFromFileError": "No applications found in selected file.", "MenuBarFileOpenUnpacked": "展開されたゲームをロード", + "MenuBarFileLoadDlcFromFolder": "Load DLC From Folder", + "MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder", "MenuBarFileOpenEmuFolder": "Ryujinx フォルダを開く", "MenuBarFileOpenLogsFolder": "ログフォルダを開く", "MenuBarFileExit": "終了(_E)", @@ -103,6 +106,8 @@ "SettingsTabGeneralHideCursorOnIdle": "アイドル時", "SettingsTabGeneralHideCursorAlways": "常時", "SettingsTabGeneralGameDirectories": "ゲームディレクトリ", + "SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories", + "SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically", "SettingsTabGeneralAdd": "追加", "SettingsTabGeneralRemove": "削除", "SettingsTabSystem": "システム", @@ -411,6 +416,7 @@ "GameListContextMenuToggleFavorite": "お気に入りを切り替え", "GameListContextMenuToggleFavoriteToolTip": "ゲームをお気に入りに含めるかどうかを切り替えます", "SettingsTabGeneralTheme": "テーマ:", + "SettingsTabGeneralThemeAuto": "Auto", "SettingsTabGeneralThemeDark": "ダーク", "SettingsTabGeneralThemeLight": "ライト", "ControllerSettingsConfigureGeneral": "設定", @@ -561,6 +567,9 @@ "AddGameDirBoxTooltip": "リストに追加するゲームディレクトリを入力します", "AddGameDirTooltip": "リストにゲームディレクトリを追加します", "RemoveGameDirTooltip": "選択したゲームディレクトリを削除します", + "AddAutoloadDirBoxTooltip": "Enter an autoload directory to add to the list", + "AddAutoloadDirTooltip": "Add an autoload directory to the list", + "RemoveAutoloadDirTooltip": "Remove selected autoload directory", "CustomThemeCheckTooltip": "エミュレータのメニュー外観を変更するためカスタム Avalonia テーマを使用します", "CustomThemePathTooltip": "カスタム GUI テーマのパスです", "CustomThemeBrowseTooltip": "カスタム GUI テーマを参照します", @@ -606,6 +615,8 @@ "DebugLogTooltip": "デバッグログメッセージをコンソールに出力します.\n\nログが読みづらくなり,エミュレータのパフォーマンスが低下するため,開発者から特別な指示がある場合のみ使用してください.", "LoadApplicationFileTooltip": "ロードする Switch 互換のファイルを選択するためファイルエクスプローラを開きます", "LoadApplicationFolderTooltip": "ロードする Switch 互換の展開済みアプリケーションを選択するためファイルエクスプローラを開きます", + "LoadDlcFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load DLC from", + "LoadTitleUpdatesFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load title updates from", "OpenRyujinxFolderTooltip": "Ryujinx ファイルシステムフォルダを開きます", "OpenRyujinxLogsTooltip": "ログが格納されるフォルダを開きます", "ExitTooltip": "Ryujinx を終了します", @@ -657,6 +668,8 @@ "OpenSetupGuideMessage": "セットアップガイドを開く", "NoUpdate": "アップデートなし", "TitleUpdateVersionLabel": "バージョン {0} - {1}", + "TitleBundledUpdateVersionLabel": "Bundled: Version {0}", + "TitleBundledDlcLabel": "Bundled:", "RyujinxInfo": "Ryujinx - 情報", "RyujinxConfirm": "Ryujinx - 確認", "FileDialogAllTypes": "すべての種別", @@ -714,9 +727,16 @@ "DlcWindowTitle": "DLC 管理", "ModWindowTitle": "Manage Mods for {0} ({1})", "UpdateWindowTitle": "アップデート管理", + "UpdateWindowUpdateAddedMessage": "{0} new update(s) added", + "UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.", "CheatWindowHeading": "利用可能なチート {0} [{1}]", "BuildId": "ビルドID:", "DlcWindowHeading": "利用可能な DLC {0} [{1}]", + "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", + "AutoloadUpdateAddedMessage": "{0} new update(s) added", + "AutoloadUpdateRemovedMessage": "{0} missing update(s) removed", "ModWindowHeading": "{0} Mod(s)", "UserProfilesEditProfile": "編集", "Cancel": "キャンセル", @@ -767,6 +787,7 @@ "GraphicsScalingFilterBilinear": "Bilinear", "GraphicsScalingFilterNearest": "Nearest", "GraphicsScalingFilterFsr": "FSR", + "GraphicsScalingFilterArea": "Area", "GraphicsScalingFilterLevelLabel": "レベル", "GraphicsScalingFilterLevelTooltip": "FSR 1.0のシャープ化レベルを設定します. 高い値ほどシャープになります.", "SmaaLow": "SMAA Low", diff --git a/src/Ryujinx/Assets/Locales/ko_KR.json b/src/Ryujinx/Assets/Locales/ko_KR.json index 6e5a7f187..bce762d19 100644 --- a/src/Ryujinx/Assets/Locales/ko_KR.json +++ b/src/Ryujinx/Assets/Locales/ko_KR.json @@ -10,7 +10,10 @@ "SettingsTabSystemUseHypervisor": "하이퍼바이저 사용하기", "MenuBarFile": "_파일", "MenuBarFileOpenFromFile": "_파일에서 응용 프로그램 불러오기", + "MenuBarFileOpenFromFileError": "No applications found in selected file.", "MenuBarFileOpenUnpacked": "_압축을 푼 게임 불러오기", + "MenuBarFileLoadDlcFromFolder": "Load DLC From Folder", + "MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder", "MenuBarFileOpenEmuFolder": "Ryujinx 폴더 열기", "MenuBarFileOpenLogsFolder": "로그 폴더 열기", "MenuBarFileExit": "_종료", @@ -103,6 +106,8 @@ "SettingsTabGeneralHideCursorOnIdle": "유휴 상태", "SettingsTabGeneralHideCursorAlways": "언제나", "SettingsTabGeneralGameDirectories": "게임 디렉터리", + "SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories", + "SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically", "SettingsTabGeneralAdd": "추가", "SettingsTabGeneralRemove": "제거", "SettingsTabSystem": "시스템", @@ -411,6 +416,7 @@ "GameListContextMenuToggleFavorite": "즐겨찾기 전환", "GameListContextMenuToggleFavoriteToolTip": "게임 즐겨찾기 상태 전환", "SettingsTabGeneralTheme": "테마:", + "SettingsTabGeneralThemeAuto": "Auto", "SettingsTabGeneralThemeDark": "어두운 테마", "SettingsTabGeneralThemeLight": "밝은 테마", "ControllerSettingsConfigureGeneral": "구성", @@ -561,6 +567,9 @@ "AddGameDirBoxTooltip": "목록에 추가할 게임 디렉터리 입력", "AddGameDirTooltip": "목록에 게임 디렉터리 추가", "RemoveGameDirTooltip": "선택한 게임 디렉터리 제거", + "AddAutoloadDirBoxTooltip": "Enter an autoload directory to add to the list", + "AddAutoloadDirTooltip": "Add an autoload directory to the list", + "RemoveAutoloadDirTooltip": "Remove selected autoload directory", "CustomThemeCheckTooltip": "GUI에 사용자 지정 Avalonia 테마를 사용하여 에뮬레이터 메뉴의 모양 변경", "CustomThemePathTooltip": "사용자 정의 GUI 테마 경로", "CustomThemeBrowseTooltip": "사용자 정의 GUI 테마 찾아보기", @@ -606,6 +615,8 @@ "DebugLogTooltip": "콘솔에 디버그 로그 메시지를 인쇄합니다.\n\n로그를 읽기 어렵게 만들고 에뮬레이터 성능을 악화시키므로 직원이 구체적으로 지시한 경우에만 사용하세요.", "LoadApplicationFileTooltip": "파일 탐색기를 열어 불러올 스위치 호환 파일 선택", "LoadApplicationFolderTooltip": "파일 탐색기를 열어 불러올 스위치 호환 압축 해제 응용 프로그램 선택", + "LoadDlcFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load DLC from", + "LoadTitleUpdatesFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load title updates from", "OpenRyujinxFolderTooltip": "Ryujinx 파일 시스템 폴더 열기", "OpenRyujinxLogsTooltip": "로그가 기록된 폴더 열기", "ExitTooltip": "Ryujinx 종료", @@ -657,6 +668,8 @@ "OpenSetupGuideMessage": "설정 가이드 열기", "NoUpdate": "업데이트 없음", "TitleUpdateVersionLabel": "버전 {0}", + "TitleBundledUpdateVersionLabel": "Bundled: Version {0}", + "TitleBundledDlcLabel": "Bundled:", "RyujinxInfo": "Ryujinx - 정보", "RyujinxConfirm": "Ryujinx - 확인", "FileDialogAllTypes": "모든 유형", @@ -714,9 +727,17 @@ "DlcWindowTitle": "{0} ({1})의 다운로드 가능한 콘텐츠 관리", "ModWindowTitle": "{0} ({1})의 Mod 관리", "UpdateWindowTitle": "타이틀 업데이트 관리자", + "UpdateWindowUpdateAddedMessage": "{0} new update(s) added", + "UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.", "CheatWindowHeading": "{0} [{1}]에 사용할 수 있는 치트", "BuildId": "빌드ID :", + "DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.", "DlcWindowHeading": "{0} 내려받기 가능한 콘텐츠", + "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", + "AutoloadUpdateAddedMessage": "{0} new update(s) added", + "AutoloadUpdateRemovedMessage": "{0} missing update(s) removed", "ModWindowHeading": "{0} Mod(s)", "UserProfilesEditProfile": "선택된 항목 편집", "Cancel": "취소", @@ -767,6 +788,7 @@ "GraphicsScalingFilterBilinear": "Bilinear", "GraphicsScalingFilterNearest": "Nearest", "GraphicsScalingFilterFsr": "FSR", + "GraphicsScalingFilterArea": "Area", "GraphicsScalingFilterLevelLabel": "수준", "GraphicsScalingFilterLevelTooltip": "FSR 1.0의 샤프닝 레벨을 설정하세요. 높을수록 더 또렷해집니다.", "SmaaLow": "SMAA 낮음", diff --git a/src/Ryujinx/Assets/Locales/pl_PL.json b/src/Ryujinx/Assets/Locales/pl_PL.json index a377979bd..5a276a7c5 100644 --- a/src/Ryujinx/Assets/Locales/pl_PL.json +++ b/src/Ryujinx/Assets/Locales/pl_PL.json @@ -10,7 +10,10 @@ "SettingsTabSystemUseHypervisor": "Użyj Hipernadzorcy", "MenuBarFile": "_Plik", "MenuBarFileOpenFromFile": "_Załaduj aplikację z pliku", + "MenuBarFileOpenFromFileError": "No applications found in selected file.", "MenuBarFileOpenUnpacked": "Załaduj _rozpakowaną grę", + "MenuBarFileLoadDlcFromFolder": "Load DLC From Folder", + "MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder", "MenuBarFileOpenEmuFolder": "Otwórz folder Ryujinx", "MenuBarFileOpenLogsFolder": "Otwórz folder plików dziennika zdarzeń", "MenuBarFileExit": "_Wyjdź", @@ -103,6 +106,8 @@ "SettingsTabGeneralHideCursorOnIdle": "Gdy bezczynny", "SettingsTabGeneralHideCursorAlways": "Zawsze", "SettingsTabGeneralGameDirectories": "Katalogi gier", + "SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories", + "SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically", "SettingsTabGeneralAdd": "Dodaj", "SettingsTabGeneralRemove": "Usuń", "SettingsTabSystem": "System", @@ -411,6 +416,7 @@ "GameListContextMenuToggleFavorite": "Przełącz na ulubione", "GameListContextMenuToggleFavoriteToolTip": "Przełącz status Ulubionej Gry", "SettingsTabGeneralTheme": "Motyw:", + "SettingsTabGeneralThemeAuto": "Auto", "SettingsTabGeneralThemeDark": "Ciemny", "SettingsTabGeneralThemeLight": "Jasny", "ControllerSettingsConfigureGeneral": "Konfiguruj", @@ -561,6 +567,9 @@ "AddGameDirBoxTooltip": "Wprowadź katalog gier aby dodać go do listy", "AddGameDirTooltip": "Dodaj katalog gier do listy", "RemoveGameDirTooltip": "Usuń wybrany katalog gier", + "AddAutoloadDirBoxTooltip": "Enter an autoload directory to add to the list", + "AddAutoloadDirTooltip": "Add an autoload directory to the list", + "RemoveAutoloadDirTooltip": "Remove selected autoload directory", "CustomThemeCheckTooltip": "Użyj niestandardowego motywu Avalonia dla GUI, aby zmienić wygląd menu emulatora", "CustomThemePathTooltip": "Ścieżka do niestandardowego motywu GUI", "CustomThemeBrowseTooltip": "Wyszukaj niestandardowy motyw GUI", @@ -606,6 +615,8 @@ "DebugLogTooltip": "Wyświetla komunikaty dziennika debugowania w konsoli.\n\nUżywaj tego tylko na wyraźne polecenie członka załogi, ponieważ utrudni to odczytanie dzienników i pogorszy wydajność emulatora.", "LoadApplicationFileTooltip": "Otwórz eksplorator plików, aby wybrać plik kompatybilny z Switch do wczytania", "LoadApplicationFolderTooltip": "Otwórz eksplorator plików, aby wybrać zgodną z Switch, rozpakowaną aplikację do załadowania", + "LoadDlcFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load DLC from", + "LoadTitleUpdatesFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load title updates from", "OpenRyujinxFolderTooltip": "Otwórz folder systemu plików Ryujinx", "OpenRyujinxLogsTooltip": "Otwiera folder, w którym zapisywane są logi", "ExitTooltip": "Wyjdź z Ryujinx", @@ -657,6 +668,8 @@ "OpenSetupGuideMessage": "Otwórz Podręcznik Konfiguracji", "NoUpdate": "Brak Aktualizacji", "TitleUpdateVersionLabel": "Wersja {0} - {1}", + "TitleBundledUpdateVersionLabel": "Bundled: Version {0}", + "TitleBundledDlcLabel": "Bundled:", "RyujinxInfo": "Ryujinx - Info", "RyujinxConfirm": "Ryujinx - Potwierdzenie", "FileDialogAllTypes": "Wszystkie typy", @@ -714,9 +727,17 @@ "DlcWindowTitle": "Menedżer Zawartości do Pobrania", "ModWindowTitle": "Zarządzaj modami dla {0} ({1})", "UpdateWindowTitle": "Menedżer Aktualizacji Tytułu", + "UpdateWindowUpdateAddedMessage": "{0} new update(s) added", + "UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.", "CheatWindowHeading": "Kody Dostępne dla {0} [{1}]", "BuildId": "Identyfikator wersji:", + "DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.", "DlcWindowHeading": "{0} Zawartości do Pobrania dostępna dla {1} ({2})", + "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", + "AutoloadUpdateAddedMessage": "{0} new update(s) added", + "AutoloadUpdateRemovedMessage": "{0} missing update(s) removed", "ModWindowHeading": "{0} Mod(y/ów)", "UserProfilesEditProfile": "Edytuj Zaznaczone", "Cancel": "Anuluj", @@ -767,6 +788,7 @@ "GraphicsScalingFilterBilinear": "Dwuliniowe", "GraphicsScalingFilterNearest": "Najbliższe", "GraphicsScalingFilterFsr": "FSR", + "GraphicsScalingFilterArea": "Area", "GraphicsScalingFilterLevelLabel": "Poziom", "GraphicsScalingFilterLevelTooltip": "Ustaw poziom ostrzeżenia FSR 1.0. Wyższy jest ostrzejszy.", "SmaaLow": "SMAA Niskie", diff --git a/src/Ryujinx/Assets/Locales/ru_RU.json b/src/Ryujinx/Assets/Locales/ru_RU.json index 8b9d39302..4980a9a5d 100644 --- a/src/Ryujinx/Assets/Locales/ru_RU.json +++ b/src/Ryujinx/Assets/Locales/ru_RU.json @@ -10,7 +10,10 @@ "SettingsTabSystemUseHypervisor": "Использовать Hypervisor", "MenuBarFile": "_Файл", "MenuBarFileOpenFromFile": "_Добавить приложение из файла", + "MenuBarFileOpenFromFileError": "No applications found in selected file.", "MenuBarFileOpenUnpacked": "Добавить _распакованную игру", + "MenuBarFileLoadDlcFromFolder": "Load DLC From Folder", + "MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder", "MenuBarFileOpenEmuFolder": "Открыть папку Ryujinx", "MenuBarFileOpenLogsFolder": "Открыть папку с логами", "MenuBarFileExit": "_Выход", @@ -103,6 +106,8 @@ "SettingsTabGeneralHideCursorOnIdle": "В простое", "SettingsTabGeneralHideCursorAlways": "Всегда", "SettingsTabGeneralGameDirectories": "Папки с играми", + "SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories", + "SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically", "SettingsTabGeneralAdd": "Добавить", "SettingsTabGeneralRemove": "Удалить", "SettingsTabSystem": "Система", @@ -411,6 +416,7 @@ "GameListContextMenuToggleFavorite": "Добавить в избранное", "GameListContextMenuToggleFavoriteToolTip": "Добавляет игру в избранное и помечает звездочкой", "SettingsTabGeneralTheme": "Тема:", + "SettingsTabGeneralThemeAuto": "Auto", "SettingsTabGeneralThemeDark": "Темная", "SettingsTabGeneralThemeLight": "Светлая", "ControllerSettingsConfigureGeneral": "Настройка", @@ -561,6 +567,9 @@ "AddGameDirBoxTooltip": "Введите путь к папке с играми для добавления ее в список выше", "AddGameDirTooltip": "Добавить папку с играми в список", "RemoveGameDirTooltip": "Удалить выбранную папку игры", + "AddAutoloadDirBoxTooltip": "Enter an autoload directory to add to the list", + "AddAutoloadDirTooltip": "Add an autoload directory to the list", + "RemoveAutoloadDirTooltip": "Remove selected autoload directory", "CustomThemeCheckTooltip": "Включить или отключить пользовательские темы", "CustomThemePathTooltip": "Путь к пользовательской теме для интерфейса", "CustomThemeBrowseTooltip": "Просмотр пользовательской темы интерфейса", @@ -606,6 +615,8 @@ "DebugLogTooltip": "Выводит журнал сообщений отладки в консоли.\n\nИспользуйте только в случае просьбы разработчика, так как включение этой функции затруднит чтение журналов и ухудшит работу эмулятора.", "LoadApplicationFileTooltip": "Открывает файловый менеджер для выбора файла, совместимого с Nintendo Switch.", "LoadApplicationFolderTooltip": "Открывает файловый менеджер для выбора распакованного приложения, совместимого с Nintendo Switch.", + "LoadDlcFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load DLC from", + "LoadTitleUpdatesFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load title updates from", "OpenRyujinxFolderTooltip": "Открывает папку с файлами Ryujinx. ", "OpenRyujinxLogsTooltip": "Открывает папку в которую записываются логи", "ExitTooltip": "Выйти из Ryujinx", @@ -657,6 +668,8 @@ "OpenSetupGuideMessage": "Открыть руководство по установке", "NoUpdate": "Без обновлений", "TitleUpdateVersionLabel": "Version {0} - {1}", + "TitleBundledUpdateVersionLabel": "Bundled: Version {0}", + "TitleBundledDlcLabel": "Bundled:", "RyujinxInfo": "Ryujinx - Информация", "RyujinxConfirm": "Ryujinx - Подтверждение", "FileDialogAllTypes": "Все типы", @@ -714,9 +727,17 @@ "DlcWindowTitle": "Управление DLC для {0} ({1})", "ModWindowTitle": "Управление модами для {0} ({1})", "UpdateWindowTitle": "Менеджер обновлений игр", + "UpdateWindowUpdateAddedMessage": "{0} new update(s) added", + "UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.", "CheatWindowHeading": "Доступные читы для {0} [{1}]", "BuildId": "ID версии:", + "DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.", "DlcWindowHeading": "{0} DLC", + "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", + "AutoloadUpdateAddedMessage": "{0} new update(s) added", + "AutoloadUpdateRemovedMessage": "{0} missing update(s) removed", "ModWindowHeading": "Моды для {0} ", "UserProfilesEditProfile": "Изменить выбранные", "Cancel": "Отмена", @@ -767,6 +788,7 @@ "GraphicsScalingFilterBilinear": "Билинейная", "GraphicsScalingFilterNearest": "Ступенчатая", "GraphicsScalingFilterFsr": "FSR", + "GraphicsScalingFilterArea": "Area", "GraphicsScalingFilterLevelLabel": "Уровень", "GraphicsScalingFilterLevelTooltip": "Выбор режима работы FSR 1.0. Выше - четче.", "SmaaLow": "SMAA Низкое", diff --git a/src/Ryujinx/Assets/Locales/th_TH.json b/src/Ryujinx/Assets/Locales/th_TH.json index 9e267dc9e..16c2d9455 100644 --- a/src/Ryujinx/Assets/Locales/th_TH.json +++ b/src/Ryujinx/Assets/Locales/th_TH.json @@ -107,6 +107,7 @@ "SettingsTabGeneralHideCursorAlways": "ตลอดเวลา", "SettingsTabGeneralGameDirectories": "ไดเรกทอรี่ของเกม", "SettingsTabGeneralAutoloadDirectories": "โหลดไดเรกทอรี DLC/ไฟล์อัปเดต อัตโนมัติ", + "SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically", "SettingsTabGeneralAdd": "เพิ่ม", "SettingsTabGeneralRemove": "เอาออก", "SettingsTabSystem": "ระบบ", @@ -734,8 +735,9 @@ "DlcWindowHeading": "{0} DLC ที่สามารถดาวน์โหลดได้", "DlcWindowDlcAddedMessage": "{0} DLC ใหม่ที่เพิ่มเข้ามา", "AutoloadDlcAddedMessage": "{0} ใหม่ที่เพิ่มเข้ามา", + "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", "AutoloadUpdateAddedMessage": "{0} อัพเดตใหม่ที่เพิ่มเข้ามา", - "AutoloadDlcAndUpdateAddedMessage": "{0} DLC ใหม่ที่เพิ่มเข้ามาและ {1} อัพเดตใหม่ที่เพิ่มเข้ามา", + "AutoloadUpdateRemovedMessage": "{0} missing update(s) removed", "ModWindowHeading": "{0} ม็อด", "UserProfilesEditProfile": "แก้ไขที่เลือกแล้ว", "Cancel": "ยกเลิก", diff --git a/src/Ryujinx/Assets/Locales/tr_TR.json b/src/Ryujinx/Assets/Locales/tr_TR.json index 1360a122e..d26ca18b7 100644 --- a/src/Ryujinx/Assets/Locales/tr_TR.json +++ b/src/Ryujinx/Assets/Locales/tr_TR.json @@ -10,7 +10,10 @@ "SettingsTabSystemUseHypervisor": "Hypervisor Kullan", "MenuBarFile": "_Dosya", "MenuBarFileOpenFromFile": "_Dosyadan Uygulama Aç", + "MenuBarFileOpenFromFileError": "No applications found in selected file.", "MenuBarFileOpenUnpacked": "_Sıkıştırılmamış Oyun Aç", + "MenuBarFileLoadDlcFromFolder": "Load DLC From Folder", + "MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder", "MenuBarFileOpenEmuFolder": "Ryujinx Klasörünü aç", "MenuBarFileOpenLogsFolder": "Logs Klasörünü aç", "MenuBarFileExit": "_Çıkış", @@ -103,6 +106,8 @@ "SettingsTabGeneralHideCursorOnIdle": "Hareketsiz Durumda", "SettingsTabGeneralHideCursorAlways": "Her Zaman", "SettingsTabGeneralGameDirectories": "Oyun Dizinleri", + "SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories", + "SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically", "SettingsTabGeneralAdd": "Ekle", "SettingsTabGeneralRemove": "Kaldır", "SettingsTabSystem": "Sistem", @@ -411,6 +416,7 @@ "GameListContextMenuToggleFavorite": "Favori Ayarla", "GameListContextMenuToggleFavoriteToolTip": "Oyunu Favorilere Ekle/Çıkar", "SettingsTabGeneralTheme": "Tema:", + "SettingsTabGeneralThemeAuto": "Auto", "SettingsTabGeneralThemeDark": "Karanlık", "SettingsTabGeneralThemeLight": "Aydınlık", "ControllerSettingsConfigureGeneral": "Ayarla", @@ -561,6 +567,9 @@ "AddGameDirBoxTooltip": "Listeye eklemek için oyun dizini seçin", "AddGameDirTooltip": "Listeye oyun dizini ekle", "RemoveGameDirTooltip": "Seçili oyun dizinini kaldır", + "AddAutoloadDirBoxTooltip": "Enter an autoload directory to add to the list", + "AddAutoloadDirTooltip": "Add an autoload directory to the list", + "RemoveAutoloadDirTooltip": "Remove selected autoload directory", "CustomThemeCheckTooltip": "Emülatör pencerelerinin görünümünü değiştirmek için özel bir Avalonia teması kullan", "CustomThemePathTooltip": "Özel arayüz temasının yolu", "CustomThemeBrowseTooltip": "Özel arayüz teması için göz at", @@ -606,6 +615,8 @@ "DebugLogTooltip": "Debug log mesajlarını konsola yazdırır.\n\nBu seçeneği yalnızca geliştirici üyemiz belirtirse aktifleştirin, çünkü bu seçenek log dosyasını okumayı zorlaştırır ve emülatörün performansını düşürür.", "LoadApplicationFileTooltip": "Switch ile uyumlu bir dosya yüklemek için dosya tarayıcısını açar", "LoadApplicationFolderTooltip": "Switch ile uyumlu ayrıştırılmamış bir uygulama yüklemek için dosya tarayıcısını açar", + "LoadDlcFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load DLC from", + "LoadTitleUpdatesFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load title updates from", "OpenRyujinxFolderTooltip": "Ryujinx dosya sistem klasörünü açar", "OpenRyujinxLogsTooltip": "Log dosyalarının bulunduğu klasörü açar", "ExitTooltip": "Ryujinx'ten çıkış yapmayı sağlar", @@ -657,6 +668,8 @@ "OpenSetupGuideMessage": "Kurulum Kılavuzunu Aç", "NoUpdate": "Güncelleme Yok", "TitleUpdateVersionLabel": "Sürüm {0} - {1}", + "TitleBundledUpdateVersionLabel": "Bundled: Version {0}", + "TitleBundledDlcLabel": "Bundled:", "RyujinxInfo": "Ryujinx - Bilgi", "RyujinxConfirm": "Ryujinx - Doğrulama", "FileDialogAllTypes": "Tüm türler", @@ -714,9 +727,17 @@ "DlcWindowTitle": "Oyun DLC'lerini Yönet", "ModWindowTitle": "Manage Mods for {0} ({1})", "UpdateWindowTitle": "Oyun Güncellemelerini Yönet", + "UpdateWindowUpdateAddedMessage": "{0} new update(s) added", + "UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.", "CheatWindowHeading": "{0} için Hile mevcut [{1}]", "BuildId": "BuildId:", - "DlcWindowHeading": "{0} için DLC mevcut [{1}]", + "DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.", + "DlcWindowHeading": "{0} Downloadable Content(s) available for {1} ({2})", + "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", + "AutoloadUpdateAddedMessage": "{0} new update(s) added", + "AutoloadUpdateRemovedMessage": "{0} missing update(s) removed", "ModWindowHeading": "{0} Mod(lar)", "UserProfilesEditProfile": "Seçiliyi Düzenle", "Cancel": "İptal", @@ -767,6 +788,7 @@ "GraphicsScalingFilterBilinear": "Bilinear", "GraphicsScalingFilterNearest": "Nearest", "GraphicsScalingFilterFsr": "FSR", + "GraphicsScalingFilterArea": "Area", "GraphicsScalingFilterLevelLabel": "Seviye", "GraphicsScalingFilterLevelTooltip": "Set FSR 1.0 sharpening level. Higher is sharper.", "SmaaLow": "Düşük SMAA", diff --git a/src/Ryujinx/Assets/Locales/uk_UA.json b/src/Ryujinx/Assets/Locales/uk_UA.json index 2fe5758b5..0a4f251fe 100644 --- a/src/Ryujinx/Assets/Locales/uk_UA.json +++ b/src/Ryujinx/Assets/Locales/uk_UA.json @@ -10,7 +10,10 @@ "SettingsTabSystemUseHypervisor": "Використовувати гіпервізор", "MenuBarFile": "_Файл", "MenuBarFileOpenFromFile": "_Завантажити програму з файлу", + "MenuBarFileOpenFromFileError": "No applications found in selected file.", "MenuBarFileOpenUnpacked": "Завантажити _розпаковану гру", + "MenuBarFileLoadDlcFromFolder": "Load DLC From Folder", + "MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder", "MenuBarFileOpenEmuFolder": "Відкрити теку Ryujinx", "MenuBarFileOpenLogsFolder": "Відкрити теку журналів змін", "MenuBarFileExit": "_Вихід", @@ -103,6 +106,8 @@ "SettingsTabGeneralHideCursorOnIdle": "Сховати у режимі очікування", "SettingsTabGeneralHideCursorAlways": "Завжди", "SettingsTabGeneralGameDirectories": "Тека ігор", + "SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories", + "SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically", "SettingsTabGeneralAdd": "Додати", "SettingsTabGeneralRemove": "Видалити", "SettingsTabSystem": "Система", @@ -411,6 +416,7 @@ "GameListContextMenuToggleFavorite": "Перемкнути вибране", "GameListContextMenuToggleFavoriteToolTip": "Перемкнути улюблений статус гри", "SettingsTabGeneralTheme": "Тема:", + "SettingsTabGeneralThemeAuto": "Auto", "SettingsTabGeneralThemeDark": "Темна", "SettingsTabGeneralThemeLight": "Світла", "ControllerSettingsConfigureGeneral": "Налаштування", @@ -561,6 +567,9 @@ "AddGameDirBoxTooltip": "Введіть каталог ігор, щоб додати до списку", "AddGameDirTooltip": "Додати каталог гри до списку", "RemoveGameDirTooltip": "Видалити вибраний каталог гри", + "AddAutoloadDirBoxTooltip": "Enter an autoload directory to add to the list", + "AddAutoloadDirTooltip": "Add an autoload directory to the list", + "RemoveAutoloadDirTooltip": "Remove selected autoload directory", "CustomThemeCheckTooltip": "Використовуйте користувацьку тему Avalonia для графічного інтерфейсу, щоб змінити вигляд меню емулятора", "CustomThemePathTooltip": "Шлях до користувацької теми графічного інтерфейсу", "CustomThemeBrowseTooltip": "Огляд користувацької теми графічного інтерфейсу", @@ -606,6 +615,8 @@ "DebugLogTooltip": "Друкує повідомлення журналу налагодження на консолі.\n\nВикористовуйте це лише за спеціальною вказівкою співробітника, оскільки це ускладнить читання журналів і погіршить роботу емулятора.", "LoadApplicationFileTooltip": "Відкриває файловий провідник, щоб вибрати для завантаження сумісний файл Switch", "LoadApplicationFolderTooltip": "Відкриває файловий провідник, щоб вибрати сумісну з комутатором розпаковану програму для завантаження", + "LoadDlcFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load DLC from", + "LoadTitleUpdatesFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load title updates from", "OpenRyujinxFolderTooltip": "Відкриває папку файлової системи Ryujinx", "OpenRyujinxLogsTooltip": "Відкриває папку, куди записуються журнали", "ExitTooltip": "Виходить з Ryujinx", @@ -657,6 +668,8 @@ "OpenSetupGuideMessage": "Відкрити посібник із налаштування", "NoUpdate": "Немає оновлень", "TitleUpdateVersionLabel": "Версія {0} - {1}", + "TitleBundledUpdateVersionLabel": "Bundled: Version {0}", + "TitleBundledDlcLabel": "Bundled:", "RyujinxInfo": "Ryujin x - Інформація", "RyujinxConfirm": "Ryujinx - Підтвердження", "FileDialogAllTypes": "Всі типи", @@ -714,9 +727,17 @@ "DlcWindowTitle": "Менеджер вмісту для завантаження", "ModWindowTitle": "Керувати модами для {0} ({1})", "UpdateWindowTitle": "Менеджер оновлення назв", + "UpdateWindowUpdateAddedMessage": "{0} new update(s) added", + "UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.", "CheatWindowHeading": "Коди доступні для {0} [{1}]", "BuildId": "ID збірки:", + "DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.", "DlcWindowHeading": "Вміст для завантаження, доступний для {1} ({2}): {0}", + "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", + "AutoloadUpdateAddedMessage": "{0} new update(s) added", + "AutoloadUpdateRemovedMessage": "{0} missing update(s) removed", "ModWindowHeading": "{0} мод(ів)", "UserProfilesEditProfile": "Редагувати вибране", "Cancel": "Скасувати", @@ -767,6 +788,7 @@ "GraphicsScalingFilterBilinear": "Білінійний", "GraphicsScalingFilterNearest": "Найближчий", "GraphicsScalingFilterFsr": "FSR", + "GraphicsScalingFilterArea": "Area", "GraphicsScalingFilterLevelLabel": "Рівень", "GraphicsScalingFilterLevelTooltip": "Встановити рівень різкості в FSR 1.0. Чим вище - тим різкіше.", "SmaaLow": "SMAA Низький", diff --git a/src/Ryujinx/Assets/Locales/zh_CN.json b/src/Ryujinx/Assets/Locales/zh_CN.json index e0fd15922..d1f3c13e3 100644 --- a/src/Ryujinx/Assets/Locales/zh_CN.json +++ b/src/Ryujinx/Assets/Locales/zh_CN.json @@ -107,6 +107,7 @@ "SettingsTabGeneralHideCursorAlways": "始终隐藏", "SettingsTabGeneralGameDirectories": "游戏目录", "SettingsTabGeneralAutoloadDirectories": "自动加载DLC/游戏更新目录", + "SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically", "SettingsTabGeneralAdd": "添加", "SettingsTabGeneralRemove": "删除", "SettingsTabSystem": "系统", @@ -734,8 +735,9 @@ "DlcWindowHeading": "{0} 个 DLC", "DlcWindowDlcAddedMessage": "{0} 个DLC被添加", "AutoloadDlcAddedMessage": "{0} 个DLC被添加", + "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", "AutoloadUpdateAddedMessage": "{0} 个游戏更新被添加", - "AutoloadDlcAndUpdateAddedMessage": "{0} 个DLC和{1} 个游戏更新被添加", + "AutoloadUpdateRemovedMessage": "{0} missing update(s) removed", "ModWindowHeading": "{0} Mod(s)", "UserProfilesEditProfile": "编辑所选", "Cancel": "取消", diff --git a/src/Ryujinx/Assets/Locales/zh_TW.json b/src/Ryujinx/Assets/Locales/zh_TW.json index e7cf35e5f..e67fcf566 100644 --- a/src/Ryujinx/Assets/Locales/zh_TW.json +++ b/src/Ryujinx/Assets/Locales/zh_TW.json @@ -10,7 +10,10 @@ "SettingsTabSystemUseHypervisor": "使用 Hypervisor", "MenuBarFile": "檔案(_F)", "MenuBarFileOpenFromFile": "從檔案載入應用程式(_L)", + "MenuBarFileOpenFromFileError": "No applications found in selected file.", "MenuBarFileOpenUnpacked": "載入未封裝的遊戲(_U)", + "MenuBarFileLoadDlcFromFolder": "Load DLC From Folder", + "MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder", "MenuBarFileOpenEmuFolder": "開啟 Ryujinx 資料夾", "MenuBarFileOpenLogsFolder": "開啟日誌資料夾", "MenuBarFileExit": "結束(_E)", @@ -103,6 +106,8 @@ "SettingsTabGeneralHideCursorOnIdle": "閒置時", "SettingsTabGeneralHideCursorAlways": "總是", "SettingsTabGeneralGameDirectories": "遊戲資料夾", + "SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories", + "SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically", "SettingsTabGeneralAdd": "新增", "SettingsTabGeneralRemove": "刪除", "SettingsTabSystem": "系統", @@ -411,6 +416,7 @@ "GameListContextMenuToggleFavorite": "加入/移除為我的最愛", "GameListContextMenuToggleFavoriteToolTip": "切換遊戲的我的最愛狀態", "SettingsTabGeneralTheme": "佈景主題:", + "SettingsTabGeneralThemeAuto": "Auto", "SettingsTabGeneralThemeDark": "深色", "SettingsTabGeneralThemeLight": "淺色", "ControllerSettingsConfigureGeneral": "配置", @@ -561,6 +567,9 @@ "AddGameDirBoxTooltip": "輸入要新增到清單中的遊戲資料夾", "AddGameDirTooltip": "新增遊戲資料夾到清單中", "RemoveGameDirTooltip": "移除選取的遊戲資料夾", + "AddAutoloadDirBoxTooltip": "Enter an autoload directory to add to the list", + "AddAutoloadDirTooltip": "Add an autoload directory to the list", + "RemoveAutoloadDirTooltip": "Remove selected autoload directory", "CustomThemeCheckTooltip": "為圖形使用者介面使用自訂 Avalonia 佈景主題,變更模擬器功能表的外觀", "CustomThemePathTooltip": "自訂 GUI 佈景主題的路徑", "CustomThemeBrowseTooltip": "瀏覽自訂 GUI 佈景主題", @@ -606,6 +615,8 @@ "DebugLogTooltip": "在控制台中輸出偵錯日誌訊息。\n\n只有在人員特別指示的情況下才能使用,因為這會導致日誌難以閱讀,並降低模擬器效能。", "LoadApplicationFileTooltip": "開啟檔案總管,選擇與 Switch 相容的檔案來載入", "LoadApplicationFolderTooltip": "開啟檔案總管,選擇與 Switch 相容且未封裝的應用程式來載入", + "LoadDlcFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load DLC from", + "LoadTitleUpdatesFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load title updates from", "OpenRyujinxFolderTooltip": "開啟 Ryujinx 檔案系統資料夾", "OpenRyujinxLogsTooltip": "開啟日誌被寫入的資料夾", "ExitTooltip": "結束 Ryujinx", @@ -657,6 +668,8 @@ "OpenSetupGuideMessage": "開啟設定指南", "NoUpdate": "沒有更新", "TitleUpdateVersionLabel": "版本 {0}", + "TitleBundledUpdateVersionLabel": "Bundled: Version {0}", + "TitleBundledDlcLabel": "Bundled:", "RyujinxInfo": "Ryujinx - 資訊", "RyujinxConfirm": "Ryujinx - 確認", "FileDialogAllTypes": "全部類型", @@ -714,9 +727,17 @@ "DlcWindowTitle": "管理 {0} 的可下載內容 ({1})", "ModWindowTitle": "管理 {0} 的模組 ({1})", "UpdateWindowTitle": "遊戲更新管理員", + "UpdateWindowUpdateAddedMessage": "{0} new update(s) added", + "UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.", "CheatWindowHeading": "可用於 {0} [{1}] 的密技", "BuildId": "組建識別碼:", + "DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.", "DlcWindowHeading": "{0} 個可下載內容", + "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", + "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", + "AutoloadUpdateAddedMessage": "{0} new update(s) added", + "AutoloadUpdateRemovedMessage": "{0} missing update(s) removed", "ModWindowHeading": "{0} 模組", "UserProfilesEditProfile": "編輯所選", "Cancel": "取消", @@ -767,6 +788,7 @@ "GraphicsScalingFilterBilinear": "雙線性 (Bilinear)", "GraphicsScalingFilterNearest": "近鄰性 (Nearest)", "GraphicsScalingFilterFsr": "FSR", + "GraphicsScalingFilterArea": "Area", "GraphicsScalingFilterLevelLabel": "日誌等級", "GraphicsScalingFilterLevelTooltip": "設定 FSR 1.0 銳化等級。越高越清晰。", "SmaaLow": "低階 SMAA", diff --git a/src/Ryujinx/Assets/Styles/Styles.xaml b/src/Ryujinx/Assets/Styles/Styles.xaml index b3a6f59c8..05212a7dd 100644 --- a/src/Ryujinx/Assets/Styles/Styles.xaml +++ b/src/Ryujinx/Assets/Styles/Styles.xaml @@ -43,6 +43,10 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Ryujinx/UI/Windows/XCITrimmerWindow.axaml.cs b/src/Ryujinx/UI/Windows/XCITrimmerWindow.axaml.cs new file mode 100644 index 000000000..580ebc9da --- /dev/null +++ b/src/Ryujinx/UI/Windows/XCITrimmerWindow.axaml.cs @@ -0,0 +1,101 @@ +using Avalonia.Controls; +using Avalonia.Interactivity; +using Avalonia.Styling; +using FluentAvalonia.UI.Controls; +using Ryujinx.Ava.Common.Locale; +using Ryujinx.Ava.UI.ViewModels; +using Ryujinx.UI.Common.Models; +using System; +using System.Threading.Tasks; + +namespace Ryujinx.Ava.UI.Windows +{ + public partial class XCITrimmerWindow : UserControl + { + public XCITrimmerViewModel ViewModel; + + public XCITrimmerWindow() + { + DataContext = this; + + InitializeComponent(); + } + + public XCITrimmerWindow(MainWindowViewModel mainWindowViewModel) + { + DataContext = ViewModel = new XCITrimmerViewModel(mainWindowViewModel); + + InitializeComponent(); + } + + public static async Task Show(MainWindowViewModel mainWindowViewModel) + { + ContentDialog contentDialog = new() + { + PrimaryButtonText = "", + SecondaryButtonText = "", + CloseButtonText = "", + Content = new XCITrimmerWindow(mainWindowViewModel), + Title = string.Format(LocaleManager.Instance[LocaleKeys.XCITrimmerWindowTitle]), + }; + + Style bottomBorder = new(x => x.OfType().Name("DialogSpace").Child().OfType()); + bottomBorder.Setters.Add(new Setter(IsVisibleProperty, false)); + + contentDialog.Styles.Add(bottomBorder); + + await contentDialog.ShowAsync(); + } + + private void Trim(object sender, RoutedEventArgs e) + { + ViewModel.TrimSelected(); + } + + private void Untrim(object sender, RoutedEventArgs e) + { + ViewModel.UntrimSelected(); + } + + private void Close(object sender, RoutedEventArgs e) + { + ((ContentDialog)Parent).Hide(); + } + + private void Cancel(Object sender, RoutedEventArgs e) + { + ViewModel.Cancel = true; + } + + public void Sort_Checked(object sender, RoutedEventArgs args) + { + if (sender is RadioButton { Tag: string sortField }) + ViewModel.SortingField = Enum.Parse(sortField); + } + + public void Order_Checked(object sender, RoutedEventArgs args) + { + if (sender is RadioButton { Tag: string sortOrder }) + ViewModel.SortingAscending = sortOrder is "Ascending"; + } + + private void OnSelectionChanged(object sender, SelectionChangedEventArgs e) + { + foreach (var content in e.AddedItems) + { + if (content is XCITrimmerFileModel applicationData) + { + ViewModel.Select(applicationData); + } + } + + foreach (var content in e.RemovedItems) + { + if (content is XCITrimmerFileModel applicationData) + { + ViewModel.Deselect(applicationData); + } + } + } + } +} diff --git a/src/Ryujinx/Updater.cs b/src/Ryujinx/Updater.cs index e8ef02052..7005fe528 100644 --- a/src/Ryujinx/Updater.cs +++ b/src/Ryujinx/Updater.cs @@ -32,6 +32,8 @@ namespace Ryujinx.Ava internal static class Updater { private const string GitHubApiUrl = "https://api.github.com"; + private const string LatestReleaseUrl = $"{GitHubApiUrl}/repos/{ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelRepo}/releases/latest"; + private static readonly GithubReleasesJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions()); private static readonly string _homeDir = AppDomain.CurrentDomain.BaseDirectory; @@ -46,9 +48,9 @@ namespace Ryujinx.Ava private static bool _updateSuccessful; private static bool _running; - private static readonly string[] _windowsDependencyDirs = Array.Empty(); + private static readonly string[] _windowsDependencyDirs = []; - public static async Task BeginParse(Window mainWindow, bool showVersionUpToDate) + public static async Task BeginUpdateAsync(this Window mainWindow, bool showVersionUpToDate = false) { if (_running) { @@ -96,9 +98,8 @@ namespace Ryujinx.Ava try { using HttpClient jsonClient = ConstructHttpClient(); - - string buildInfoUrl = $"{GitHubApiUrl}/repos/{ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelRepo}/releases/latest"; - string fetchedJson = await jsonClient.GetStringAsync(buildInfoUrl); + + string fetchedJson = await jsonClient.GetStringAsync(LatestReleaseUrl); var fetched = JsonHelper.Deserialize(fetchedJson, _serializerContext.GithubReleasesJsonResponse); _buildVer = fetched.Name; @@ -159,7 +160,7 @@ namespace Ryujinx.Ava } catch { - Logger.Error?.Print(LogClass.Application, "Failed to convert the received Ryujinx version from Github!"); + Logger.Error?.Print(LogClass.Application, $"Failed to convert the received {App.FullAppName} version from GitHub!"); await ContentDialogHelper.CreateWarningDialog( LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedGithubMessage], @@ -636,7 +637,7 @@ namespace Ryujinx.Ava taskDialog.Hide(); } - public static bool CanUpdate(bool showWarnings) + public static bool CanUpdate(bool showWarnings = false) { #if !DISABLE_UPDATER if (!NetworkInterface.GetIsNetworkAvailable())