Merge branch 'master' into fix-remember-window-position-on-linux

This commit is contained in:
Evan Husted 2024-11-06 18:32:07 -06:00 committed by GitHub
commit 456e34f20b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
67 changed files with 2979 additions and 280 deletions

254
.github/workflows/canary.yml vendored Normal file
View File

@ -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 }}

View File

@ -4,7 +4,7 @@ on:
workflow_dispatch: workflow_dispatch:
inputs: {} inputs: {}
push: push:
branches: [ master ] branches: [ release ]
paths-ignore: paths-ignore:
- '.github/**' - '.github/**'
- 'docs/**' - 'docs/**'
@ -20,7 +20,7 @@ env:
POWERSHELL_TELEMETRY_OPTOUT: 1 POWERSHELL_TELEMETRY_OPTOUT: 1
DOTNET_CLI_TELEMETRY_OPTOUT: 1 DOTNET_CLI_TELEMETRY_OPTOUT: 1
RYUJINX_BASE_VERSION: "1.2" 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_OWNER: "GreemDev"
RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Ryujinx" RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Ryujinx"
RELEASE: 1 RELEASE: 1

View File

@ -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; 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. 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**. 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). 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
Building the project is for advanced users.
If you wish to build the emulator yourself, follow these steps: If you wish to build the emulator yourself, follow these steps:
### Step 1 ### Step 1

View File

@ -29,14 +29,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec", "s
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio", "src\Ryujinx.Audio\Ryujinx.Audio.csproj", "{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio", "src\Ryujinx.Audio\Ryujinx.Audio.csproj", "{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}"
EndProject 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}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Memory", "src\Ryujinx.Memory\Ryujinx.Memory.csproj", "{A5E6C691-9E22-4263-8F40-42F002CE66BE}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Tests.Memory", "src\Ryujinx.Tests.Memory\Ryujinx.Tests.Memory.csproj", "{D1CC5322-7325-4F6B-9625-194B30BE1296}" 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 EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}"
EndProject EndProject
Project("{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 Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU

Binary file not shown.

View File

@ -46,5 +46,5 @@ then
rcodesign sign --entitlements-xml-path "$ENTITLEMENTS_FILE_PATH" "$APP_BUNDLE_DIRECTORY" rcodesign sign --entitlements-xml-path "$ENTITLEMENTS_FILE_PATH" "$APP_BUNDLE_DIRECTORY"
else else
echo "Usign codesign for ad-hoc signing" echo "Usign codesign for ad-hoc signing"
codesign --entitlements "$ENTITLEMENTS_FILE_PATH" -f --deep -s - "$APP_BUNDLE_DIRECTORY" codesign --entitlements "$ENTITLEMENTS_FILE_PATH" -f -s - "$APP_BUNDLE_DIRECTORY"
fi fi

View File

@ -99,7 +99,7 @@ then
rcodesign sign --entitlements-xml-path "$ENTITLEMENTS_FILE_PATH" "$UNIVERSAL_APP_BUNDLE" rcodesign sign --entitlements-xml-path "$ENTITLEMENTS_FILE_PATH" "$UNIVERSAL_APP_BUNDLE"
else else
echo "Using codesign for ad-hoc signing" 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 fi
echo "Creating archive" echo "Creating archive"

View File

@ -95,7 +95,7 @@ else
echo "Using codesign for ad-hoc signing" echo "Using codesign for ad-hoc signing"
for FILE in "$UNIVERSAL_OUTPUT"/*; do for FILE in "$UNIVERSAL_OUTPUT"/*; do
if [[ $(file "$FILE") == *"Mach-O"* ]]; then if [[ $(file "$FILE") == *"Mach-O"* ]]; then
codesign --entitlements "$ENTITLEMENTS_FILE_PATH" -f --deep -s - "$FILE" codesign --entitlements "$ENTITLEMENTS_FILE_PATH" -f -s - "$FILE"
fi fi
done done
fi fi

View File

@ -81,7 +81,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static short GetCoefficientAtIndex(ReadOnlySpan<short> coefficients, int index) private static short GetCoefficientAtIndex(ReadOnlySpan<short> 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}"); Logger.Error?.Print(LogClass.AudioRenderer, $"Out of bound read for coefficient at index {index}");

View File

@ -72,5 +72,6 @@ namespace Ryujinx.Common.Logging
TamperMachine, TamperMachine,
UI, UI,
Vic, Vic,
XCIFileTrimmer
} }
} }

View File

@ -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;
}
}
}
}

View File

@ -5,7 +5,9 @@ namespace Ryujinx.Common
// DO NOT EDIT, filled by CI // DO NOT EDIT, filled by CI
public static class ReleaseInformation 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%%"; private const string BuildVersion = "%%RYUJINX_BUILD_VERSION%%";
public const string BuildGitHash = "%%RYUJINX_BUILD_GIT_HASH%%"; public const string BuildGitHash = "%%RYUJINX_BUILD_GIT_HASH%%";
@ -24,7 +26,11 @@ namespace Ryujinx.Common
!ReleaseChannelRepo.StartsWith("%%") && !ReleaseChannelRepo.StartsWith("%%") &&
!ConfigFileName.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<AssemblyInformationalVersionAttribute>()?.InformationalVersion; public static string Version => IsValid ? BuildVersion : Assembly.GetEntryAssembly()!.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;
} }

View File

@ -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";
/// <summary>
/// Cartridge Sizes (ByteIdentifier, SizeInGB)
/// </summary>
private static readonly Dictionary<byte, long> _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<byte>(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;
}
}
}

View File

@ -13,6 +13,7 @@ namespace Ryujinx.HLE.Generators
var syntaxReceiver = (ServiceSyntaxReceiver)context.SyntaxReceiver; var syntaxReceiver = (ServiceSyntaxReceiver)context.SyntaxReceiver;
CodeGenerator generator = new CodeGenerator(); CodeGenerator generator = new CodeGenerator();
generator.AppendLine("#nullable enable");
generator.AppendLine("using System;"); generator.AppendLine("using System;");
generator.EnterScope($"namespace Ryujinx.HLE.HOS.Services.Sm"); generator.EnterScope($"namespace Ryujinx.HLE.HOS.Services.Sm");
generator.EnterScope($"partial class IUserInterface"); generator.EnterScope($"partial class IUserInterface");
@ -58,6 +59,7 @@ namespace Ryujinx.HLE.Generators
generator.LeaveScope(); generator.LeaveScope();
generator.LeaveScope(); generator.LeaveScope();
generator.AppendLine("#nullable disable");
context.AddSource($"IUserInterface.g.cs", generator.ToString()); context.AddSource($"IUserInterface.g.cs", generator.ToString());
} }

View File

@ -5,6 +5,7 @@ using Ryujinx.HLE.Exceptions;
using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.HOS.Kernel.Memory;
using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory; 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.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.DebugPad;
using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Keyboard; using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Keyboard;
using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Mouse; using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Mouse;
@ -28,6 +29,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
public DebugPadDevice DebugPad; public DebugPadDevice DebugPad;
public TouchDevice Touchscreen; public TouchDevice Touchscreen;
public MouseDevice Mouse; public MouseDevice Mouse;
public DebugMouseDevice DebugMouse;
public KeyboardDevice Keyboard; public KeyboardDevice Keyboard;
public NpadDevices Npads; public NpadDevices Npads;
@ -44,6 +46,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
CheckTypeSizeOrThrow<RingLifo<DebugPadState>>(0x2c8); CheckTypeSizeOrThrow<RingLifo<DebugPadState>>(0x2c8);
CheckTypeSizeOrThrow<RingLifo<TouchScreenState>>(0x2C38); CheckTypeSizeOrThrow<RingLifo<TouchScreenState>>(0x2C38);
CheckTypeSizeOrThrow<RingLifo<MouseState>>(0x350); CheckTypeSizeOrThrow<RingLifo<MouseState>>(0x350);
CheckTypeSizeOrThrow<RingLifo<DebugMouseState>>(0x350);
CheckTypeSizeOrThrow<RingLifo<KeyboardState>>(0x3D8); CheckTypeSizeOrThrow<RingLifo<KeyboardState>>(0x3D8);
CheckTypeSizeOrThrow<Array10<NpadState>>(0x32000); CheckTypeSizeOrThrow<Array10<NpadState>>(0x32000);
CheckTypeSizeOrThrow<SharedMemory>(Horizon.HidSize); CheckTypeSizeOrThrow<SharedMemory>(Horizon.HidSize);
@ -64,6 +67,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
DebugPad = new DebugPadDevice(_device, true); DebugPad = new DebugPadDevice(_device, true);
Touchscreen = new TouchDevice(_device, true); Touchscreen = new TouchDevice(_device, true);
Mouse = new MouseDevice(_device, false); Mouse = new MouseDevice(_device, false);
DebugMouse = new DebugMouseDevice(_device, false);
Keyboard = new KeyboardDevice(_device, false); Keyboard = new KeyboardDevice(_device, false);
Npads = new NpadDevices(_device, true); Npads = new NpadDevices(_device, true);
} }

View File

@ -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<DebugMouseState> 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);
}
}
}

View File

@ -131,6 +131,26 @@ namespace Ryujinx.HLE.HOS.Services.Hid
return ResultCode.Success; 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)] [CommandCmif(31)]
// ActivateKeyboard(nn::applet::AppletResourceUserId) // ActivateKeyboard(nn::applet::AppletResourceUserId)
public ResultCode ActivateKeyboard(ServiceCtx context) public ResultCode ActivateKeyboard(ServiceCtx context)

View File

@ -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,
}
}

View File

@ -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,
}
}

View File

@ -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;
}
}

View File

@ -1,5 +1,6 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Common; 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.DebugPad;
using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Keyboard; using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Keyboard;
using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Mouse; using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Mouse;
@ -45,6 +46,12 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory
[FieldOffset(0x9A00)] [FieldOffset(0x9A00)]
public Array10<NpadState> Npads; public Array10<NpadState> Npads;
/// <summary>
/// Debug mouse.
/// </summary>
[FieldOffset(0x3DC00)]
public RingLifo<DebugMouseState> DebugMouse;
public static SharedMemory Create() public static SharedMemory Create()
{ {
SharedMemory result = new() SharedMemory result = new()

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
@ -17,7 +17,7 @@
</ItemGroup> </ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="$([MSBuild]::IsOSPlatform('OSX'))"> <Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="$([MSBuild]::IsOSPlatform('OSX'))">
<Exec Command="codesign --entitlements '$(ProjectDir)..\..\distribution\macos\entitlements.xml' -f --deep -s $(SigningCertificate) '$(TargetDir)$(TargetName)'" /> <Exec Command="codesign --entitlements '$(ProjectDir)..\..\distribution\macos\entitlements.xml' -f -s $(SigningCertificate) '$(TargetDir)$(TargetName)'" />
</Target> </Target>
<ItemGroup> <ItemGroup>

View File

@ -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();
}
}
}

View File

@ -23,8 +23,10 @@ namespace Ryujinx.Ava
{ {
internal static string FormatTitle(LocaleKeys? windowTitleKey = null) internal static string FormatTitle(LocaleKeys? windowTitleKey = null)
=> windowTitleKey is null => windowTitleKey is null
? $"Ryujinx {Program.Version}" ? $"{FullAppName} {Program.Version}"
: $"Ryujinx {Program.Version} - {LocaleManager.Instance[windowTitleKey.Value]}"; : $"{FullAppName} {Program.Version} - {LocaleManager.Instance[windowTitleKey.Value]}";
public static readonly string FullAppName = ReleaseInformation.IsCanaryBuild ? "Ryujinx Canary" : "Ryujinx";
public static MainWindow MainWindow => Current! public static MainWindow MainWindow => Current!
.ApplicationLifetime.Cast<IClassicDesktopStyleApplicationLifetime>() .ApplicationLifetime.Cast<IClassicDesktopStyleApplicationLifetime>()

View File

@ -10,7 +10,10 @@
"SettingsTabSystemUseHypervisor": "استخدم مراقب الأجهزة الافتراضية", "SettingsTabSystemUseHypervisor": "استخدم مراقب الأجهزة الافتراضية",
"MenuBarFile": "_ملف", "MenuBarFile": "_ملف",
"MenuBarFileOpenFromFile": "_تحميل تطبيق من ملف", "MenuBarFileOpenFromFile": "_تحميل تطبيق من ملف",
"MenuBarFileOpenFromFileError": "No applications found in selected file.",
"MenuBarFileOpenUnpacked": "تحميل لُعْبَة غير محزومة", "MenuBarFileOpenUnpacked": "تحميل لُعْبَة غير محزومة",
"MenuBarFileLoadDlcFromFolder": "Load DLC From Folder",
"MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder",
"MenuBarFileOpenEmuFolder": "‫فتح مجلد Ryujinx", "MenuBarFileOpenEmuFolder": "‫فتح مجلد Ryujinx",
"MenuBarFileOpenLogsFolder": "فتح مجلد السجلات", "MenuBarFileOpenLogsFolder": "فتح مجلد السجلات",
"MenuBarFileExit": "_خروج", "MenuBarFileExit": "_خروج",
@ -103,6 +106,8 @@
"SettingsTabGeneralHideCursorOnIdle": "عند الخمول", "SettingsTabGeneralHideCursorOnIdle": "عند الخمول",
"SettingsTabGeneralHideCursorAlways": "دائما", "SettingsTabGeneralHideCursorAlways": "دائما",
"SettingsTabGeneralGameDirectories": "مجلدات الألعاب", "SettingsTabGeneralGameDirectories": "مجلدات الألعاب",
"SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories",
"SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically",
"SettingsTabGeneralAdd": "إضافة", "SettingsTabGeneralAdd": "إضافة",
"SettingsTabGeneralRemove": "إزالة", "SettingsTabGeneralRemove": "إزالة",
"SettingsTabSystem": "النظام", "SettingsTabSystem": "النظام",
@ -411,6 +416,7 @@
"GameListContextMenuToggleFavorite": "تعيين كمفضل", "GameListContextMenuToggleFavorite": "تعيين كمفضل",
"GameListContextMenuToggleFavoriteToolTip": "تبديل الحالة المفضلة للعبة", "GameListContextMenuToggleFavoriteToolTip": "تبديل الحالة المفضلة للعبة",
"SettingsTabGeneralTheme": "السمة:", "SettingsTabGeneralTheme": "السمة:",
"SettingsTabGeneralThemeAuto": "Auto",
"SettingsTabGeneralThemeDark": "داكن", "SettingsTabGeneralThemeDark": "داكن",
"SettingsTabGeneralThemeLight": "فاتح", "SettingsTabGeneralThemeLight": "فاتح",
"ControllerSettingsConfigureGeneral": "ضبط", "ControllerSettingsConfigureGeneral": "ضبط",
@ -561,6 +567,9 @@
"AddGameDirBoxTooltip": "أدخل مجلد اللعبة لإضافته إلى القائمة", "AddGameDirBoxTooltip": "أدخل مجلد اللعبة لإضافته إلى القائمة",
"AddGameDirTooltip": "إضافة مجلد اللعبة إلى القائمة", "AddGameDirTooltip": "إضافة مجلد اللعبة إلى القائمة",
"RemoveGameDirTooltip": "إزالة مجلد اللعبة المحدد", "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": "استخدم سمة أفالونيا المخصصة لواجهة المستخدم الرسومية لتغيير مظهر قوائم المحاكي", "CustomThemeCheckTooltip": "استخدم سمة أفالونيا المخصصة لواجهة المستخدم الرسومية لتغيير مظهر قوائم المحاكي",
"CustomThemePathTooltip": "مسار سمة واجهة المستخدم المخصصة", "CustomThemePathTooltip": "مسار سمة واجهة المستخدم المخصصة",
"CustomThemeBrowseTooltip": "تصفح للحصول على سمة واجهة المستخدم المخصصة", "CustomThemeBrowseTooltip": "تصفح للحصول على سمة واجهة المستخدم المخصصة",
@ -606,6 +615,8 @@
"DebugLogTooltip": "طباعة رسائل سجل التصحيح في وحدة التحكم.\n\nاستخدم هذا فقط إذا طلب منك أحد الموظفين تحديدًا ذلك، لأنه سيجعل من الصعب قراءة السجلات وسيؤدي إلى تدهور أداء المحاكي.", "DebugLogTooltip": "طباعة رسائل سجل التصحيح في وحدة التحكم.\n\nاستخدم هذا فقط إذا طلب منك أحد الموظفين تحديدًا ذلك، لأنه سيجعل من الصعب قراءة السجلات وسيؤدي إلى تدهور أداء المحاكي.",
"LoadApplicationFileTooltip": "افتح مستكشف الملفات لاختيار ملف متوافق مع سويتش لتحميله", "LoadApplicationFileTooltip": "افتح مستكشف الملفات لاختيار ملف متوافق مع سويتش لتحميله",
"LoadApplicationFolderTooltip": "افتح مستكشف الملفات لاختيار تطبيق متوافق مع سويتش للتحميل", "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": "فتح مجلد نظام ملفات ريوجينكس", "OpenRyujinxFolderTooltip": "فتح مجلد نظام ملفات ريوجينكس",
"OpenRyujinxLogsTooltip": "يفتح المجلد الذي تتم كتابة السجلات إليه", "OpenRyujinxLogsTooltip": "يفتح المجلد الذي تتم كتابة السجلات إليه",
"ExitTooltip": "الخروج من ريوجينكس", "ExitTooltip": "الخروج من ريوجينكس",
@ -657,6 +668,8 @@
"OpenSetupGuideMessage": "فتح دليل الإعداد", "OpenSetupGuideMessage": "فتح دليل الإعداد",
"NoUpdate": "لا يوجد تحديث", "NoUpdate": "لا يوجد تحديث",
"TitleUpdateVersionLabel": "الإصدار: {0}", "TitleUpdateVersionLabel": "الإصدار: {0}",
"TitleBundledUpdateVersionLabel": "Bundled: Version {0}",
"TitleBundledDlcLabel": "Bundled:",
"RyujinxInfo": "ريوجينكس - معلومات", "RyujinxInfo": "ريوجينكس - معلومات",
"RyujinxConfirm": "ريوجينكس - تأكيد", "RyujinxConfirm": "ريوجينكس - تأكيد",
"FileDialogAllTypes": "كل الأنواع", "FileDialogAllTypes": "كل الأنواع",
@ -714,9 +727,17 @@
"DlcWindowTitle": "إدارة المحتوى القابل للتنزيل لـ {0} ({1})", "DlcWindowTitle": "إدارة المحتوى القابل للتنزيل لـ {0} ({1})",
"ModWindowTitle": "إدارة التعديلات لـ {0} ({1})", "ModWindowTitle": "إدارة التعديلات لـ {0} ({1})",
"UpdateWindowTitle": "مدير تحديث العنوان", "UpdateWindowTitle": "مدير تحديث العنوان",
"UpdateWindowUpdateAddedMessage": "{0} new update(s) added",
"UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.",
"CheatWindowHeading": "الغش متوفر لـ {0} [{1}]", "CheatWindowHeading": "الغش متوفر لـ {0} [{1}]",
"BuildId": "معرف البناء:", "BuildId": "معرف البناء:",
"DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.",
"DlcWindowHeading": "المحتويات القابلة للتنزيل {0}", "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} تعديل", "ModWindowHeading": "{0} تعديل",
"UserProfilesEditProfile": "تعديل المحدد", "UserProfilesEditProfile": "تعديل المحدد",
"Cancel": "إلغاء", "Cancel": "إلغاء",
@ -767,6 +788,7 @@
"GraphicsScalingFilterBilinear": "Bilinear", "GraphicsScalingFilterBilinear": "Bilinear",
"GraphicsScalingFilterNearest": "Nearest", "GraphicsScalingFilterNearest": "Nearest",
"GraphicsScalingFilterFsr": "FSR", "GraphicsScalingFilterFsr": "FSR",
"GraphicsScalingFilterArea": "Area",
"GraphicsScalingFilterLevelLabel": "المستوى", "GraphicsScalingFilterLevelLabel": "المستوى",
"GraphicsScalingFilterLevelTooltip": "اضبط مستوى وضوح FSR 1.0. الأعلى هو أكثر وضوحا.", "GraphicsScalingFilterLevelTooltip": "اضبط مستوى وضوح FSR 1.0. الأعلى هو أكثر وضوحا.",
"SmaaLow": "SMAA منخفض", "SmaaLow": "SMAA منخفض",

View File

@ -10,7 +10,10 @@
"SettingsTabSystemUseHypervisor": "Hypervisor verwenden", "SettingsTabSystemUseHypervisor": "Hypervisor verwenden",
"MenuBarFile": "_Datei", "MenuBarFile": "_Datei",
"MenuBarFileOpenFromFile": "Datei _öffnen", "MenuBarFileOpenFromFile": "Datei _öffnen",
"MenuBarFileOpenFromFileError": "No applications found in selected file.",
"MenuBarFileOpenUnpacked": "_Entpacktes Spiel öffnen", "MenuBarFileOpenUnpacked": "_Entpacktes Spiel öffnen",
"MenuBarFileLoadDlcFromFolder": "Load DLC From Folder",
"MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder",
"MenuBarFileOpenEmuFolder": "Ryujinx-Ordner öffnen", "MenuBarFileOpenEmuFolder": "Ryujinx-Ordner öffnen",
"MenuBarFileOpenLogsFolder": "Logs-Ordner öffnen", "MenuBarFileOpenLogsFolder": "Logs-Ordner öffnen",
"MenuBarFileExit": "_Beenden", "MenuBarFileExit": "_Beenden",
@ -103,6 +106,8 @@
"SettingsTabGeneralHideCursorOnIdle": "Mauszeiger bei Inaktivität ausblenden", "SettingsTabGeneralHideCursorOnIdle": "Mauszeiger bei Inaktivität ausblenden",
"SettingsTabGeneralHideCursorAlways": "Immer", "SettingsTabGeneralHideCursorAlways": "Immer",
"SettingsTabGeneralGameDirectories": "Spielverzeichnisse", "SettingsTabGeneralGameDirectories": "Spielverzeichnisse",
"SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories",
"SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically",
"SettingsTabGeneralAdd": "Hinzufügen", "SettingsTabGeneralAdd": "Hinzufügen",
"SettingsTabGeneralRemove": "Entfernen", "SettingsTabGeneralRemove": "Entfernen",
"SettingsTabSystem": "System", "SettingsTabSystem": "System",
@ -411,6 +416,7 @@
"GameListContextMenuToggleFavorite": "Als Favoriten hinzufügen/entfernen", "GameListContextMenuToggleFavorite": "Als Favoriten hinzufügen/entfernen",
"GameListContextMenuToggleFavoriteToolTip": "Aktiviert den Favoriten-Status des Spiels", "GameListContextMenuToggleFavoriteToolTip": "Aktiviert den Favoriten-Status des Spiels",
"SettingsTabGeneralTheme": "Design:", "SettingsTabGeneralTheme": "Design:",
"SettingsTabGeneralThemeAuto": "Auto",
"SettingsTabGeneralThemeDark": "Dunkel", "SettingsTabGeneralThemeDark": "Dunkel",
"SettingsTabGeneralThemeLight": "Hell", "SettingsTabGeneralThemeLight": "Hell",
"ControllerSettingsConfigureGeneral": "Konfigurieren", "ControllerSettingsConfigureGeneral": "Konfigurieren",
@ -561,6 +567,9 @@
"AddGameDirBoxTooltip": "Gibt das Spielverzeichnis an, das der Liste hinzuzufügt wird", "AddGameDirBoxTooltip": "Gibt das Spielverzeichnis an, das der Liste hinzuzufügt wird",
"AddGameDirTooltip": "Fügt ein neues Spielverzeichnis hinzu", "AddGameDirTooltip": "Fügt ein neues Spielverzeichnis hinzu",
"RemoveGameDirTooltip": "Entfernt das ausgewähltes Spielverzeichnis", "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", "CustomThemeCheckTooltip": "Verwende ein eigenes Design für die Emulator-Benutzeroberfläche",
"CustomThemePathTooltip": "Gibt den Pfad zum Design für die Emulator-Benutzeroberfläche an", "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", "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.", "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", "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", "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", "OpenRyujinxFolderTooltip": "Öffnet den Ordner, der das Ryujinx Dateisystem enthält",
"OpenRyujinxLogsTooltip": "Öffnet den Ordner, in welchem die Logs gespeichert werden", "OpenRyujinxLogsTooltip": "Öffnet den Ordner, in welchem die Logs gespeichert werden",
"ExitTooltip": "Beendet Ryujinx", "ExitTooltip": "Beendet Ryujinx",
@ -657,6 +668,8 @@
"OpenSetupGuideMessage": "Öffne den 'Setup Guide'", "OpenSetupGuideMessage": "Öffne den 'Setup Guide'",
"NoUpdate": "Kein Update", "NoUpdate": "Kein Update",
"TitleUpdateVersionLabel": "Version {0} - {1}", "TitleUpdateVersionLabel": "Version {0} - {1}",
"TitleBundledUpdateVersionLabel": "Bundled: Version {0}",
"TitleBundledDlcLabel": "Bundled:",
"RyujinxInfo": "Ryujinx - Info", "RyujinxInfo": "Ryujinx - Info",
"RyujinxConfirm": "Ryujinx - Bestätigung", "RyujinxConfirm": "Ryujinx - Bestätigung",
"FileDialogAllTypes": "Alle Typen", "FileDialogAllTypes": "Alle Typen",
@ -714,9 +727,17 @@
"DlcWindowTitle": "Spiel-DLC verwalten", "DlcWindowTitle": "Spiel-DLC verwalten",
"ModWindowTitle": "Manage Mods for {0} ({1})", "ModWindowTitle": "Manage Mods for {0} ({1})",
"UpdateWindowTitle": "Spiel-Updates verwalten", "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}]", "CheatWindowHeading": "Cheats verfügbar für {0} [{1}]",
"DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.",
"BuildId": "BuildId:", "BuildId": "BuildId:",
"DlcWindowHeading": "DLC verfügbar für {0} [{1}]", "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)", "ModWindowHeading": "{0} Mod(s)",
"UserProfilesEditProfile": "Profil bearbeiten", "UserProfilesEditProfile": "Profil bearbeiten",
"Cancel": "Abbrechen", "Cancel": "Abbrechen",
@ -767,6 +788,7 @@
"GraphicsScalingFilterBilinear": "Bilinear", "GraphicsScalingFilterBilinear": "Bilinear",
"GraphicsScalingFilterNearest": "Nächstes", "GraphicsScalingFilterNearest": "Nächstes",
"GraphicsScalingFilterFsr": "FSR", "GraphicsScalingFilterFsr": "FSR",
"GraphicsScalingFilterArea": "Area",
"GraphicsScalingFilterLevelLabel": "Stufe", "GraphicsScalingFilterLevelLabel": "Stufe",
"GraphicsScalingFilterLevelTooltip": "FSR 1.0 Schärfelevel festlegen. Höher ist schärfer.", "GraphicsScalingFilterLevelTooltip": "FSR 1.0 Schärfelevel festlegen. Höher ist schärfer.",
"SmaaLow": "SMAA Niedrig", "SmaaLow": "SMAA Niedrig",

View File

@ -10,7 +10,10 @@
"SettingsTabSystemUseHypervisor": "Χρήση Hypervisor", "SettingsTabSystemUseHypervisor": "Χρήση Hypervisor",
"MenuBarFile": "_Αρχείο", "MenuBarFile": "_Αρχείο",
"MenuBarFileOpenFromFile": "_Φόρτωση Αρχείου Εφαρμογής", "MenuBarFileOpenFromFile": "_Φόρτωση Αρχείου Εφαρμογής",
"MenuBarFileOpenFromFileError": "No applications found in selected file.",
"MenuBarFileOpenUnpacked": "Φόρτωση Απακετάριστου _Παιχνιδιού", "MenuBarFileOpenUnpacked": "Φόρτωση Απακετάριστου _Παιχνιδιού",
"MenuBarFileLoadDlcFromFolder": "Load DLC From Folder",
"MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder",
"MenuBarFileOpenEmuFolder": "Άνοιγμα Φακέλου Ryujinx", "MenuBarFileOpenEmuFolder": "Άνοιγμα Φακέλου Ryujinx",
"MenuBarFileOpenLogsFolder": "Άνοιγμα Φακέλου Καταγραφής", "MenuBarFileOpenLogsFolder": "Άνοιγμα Φακέλου Καταγραφής",
"MenuBarFileExit": "_Έξοδος", "MenuBarFileExit": "_Έξοδος",
@ -103,6 +106,8 @@
"SettingsTabGeneralHideCursorOnIdle": "Απόκρυψη Δρομέα στην Αδράνεια", "SettingsTabGeneralHideCursorOnIdle": "Απόκρυψη Δρομέα στην Αδράνεια",
"SettingsTabGeneralHideCursorAlways": "Πάντα", "SettingsTabGeneralHideCursorAlways": "Πάντα",
"SettingsTabGeneralGameDirectories": "Τοποθεσίες παιχνιδιών", "SettingsTabGeneralGameDirectories": "Τοποθεσίες παιχνιδιών",
"SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories",
"SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically",
"SettingsTabGeneralAdd": "Προσθήκη", "SettingsTabGeneralAdd": "Προσθήκη",
"SettingsTabGeneralRemove": "Αφαίρεση", "SettingsTabGeneralRemove": "Αφαίρεση",
"SettingsTabSystem": "Σύστημα", "SettingsTabSystem": "Σύστημα",
@ -411,6 +416,7 @@
"GameListContextMenuToggleFavorite": "Εναλλαγή Αγαπημένου", "GameListContextMenuToggleFavorite": "Εναλλαγή Αγαπημένου",
"GameListContextMenuToggleFavoriteToolTip": "Εναλλαγή της Κατάστασης Αγαπημένο του Παιχνιδιού", "GameListContextMenuToggleFavoriteToolTip": "Εναλλαγή της Κατάστασης Αγαπημένο του Παιχνιδιού",
"SettingsTabGeneralTheme": "Theme:", "SettingsTabGeneralTheme": "Theme:",
"SettingsTabGeneralThemeAuto": "Auto",
"SettingsTabGeneralThemeDark": "Dark", "SettingsTabGeneralThemeDark": "Dark",
"SettingsTabGeneralThemeLight": "Light", "SettingsTabGeneralThemeLight": "Light",
"ControllerSettingsConfigureGeneral": "Παραμέτρων", "ControllerSettingsConfigureGeneral": "Παραμέτρων",
@ -561,6 +567,9 @@
"AddGameDirBoxTooltip": "Εισαγάγετε μία τοποθεσία παιχνιδιών για προσθήκη στη λίστα", "AddGameDirBoxTooltip": "Εισαγάγετε μία τοποθεσία παιχνιδιών για προσθήκη στη λίστα",
"AddGameDirTooltip": "Προσθέστε μία τοποθεσία παιχνιδιών στη λίστα", "AddGameDirTooltip": "Προσθέστε μία τοποθεσία παιχνιδιών στη λίστα",
"RemoveGameDirTooltip": "Αφαιρέστε την επιλεγμένη τοποθεσία παιχνιδιών", "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", "CustomThemeCheckTooltip": "Ενεργοποίηση ή απενεργοποίηση προσαρμοσμένων θεμάτων στο GUI",
"CustomThemePathTooltip": "Διαδρομή προς το προσαρμοσμένο θέμα GUI", "CustomThemePathTooltip": "Διαδρομή προς το προσαρμοσμένο θέμα GUI",
"CustomThemeBrowseTooltip": "Αναζητήστε ένα προσαρμοσμένο θέμα GUI", "CustomThemeBrowseTooltip": "Αναζητήστε ένα προσαρμοσμένο θέμα GUI",
@ -606,6 +615,8 @@
"DebugLogTooltip": "Ενεργοποιεί την εκτύπωση μηνυμάτων αρχείου καταγραφής εντοπισμού σφαλμάτων", "DebugLogTooltip": "Ενεργοποιεί την εκτύπωση μηνυμάτων αρχείου καταγραφής εντοπισμού σφαλμάτων",
"LoadApplicationFileTooltip": "Ανοίξτε έναν επιλογέα αρχείων για να επιλέξετε ένα αρχείο συμβατό με το Switch για φόρτωση", "LoadApplicationFileTooltip": "Ανοίξτε έναν επιλογέα αρχείων για να επιλέξετε ένα αρχείο συμβατό με το Switch για φόρτωση",
"LoadApplicationFolderTooltip": "Ανοίξτε έναν επιλογέα αρχείων για να επιλέξετε μία μη συσκευασμένη εφαρμογή, συμβατή με το 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", "OpenRyujinxFolderTooltip": "Ανοίξτε το φάκελο συστήματος αρχείων Ryujinx",
"OpenRyujinxLogsTooltip": "Ανοίξτε το φάκελο στον οποίο διατηρούνται τα αρχεία καταγραφής", "OpenRyujinxLogsTooltip": "Ανοίξτε το φάκελο στον οποίο διατηρούνται τα αρχεία καταγραφής",
"ExitTooltip": "Έξοδος από το Ryujinx", "ExitTooltip": "Έξοδος από το Ryujinx",
@ -657,6 +668,8 @@
"OpenSetupGuideMessage": "Ανοίξτε τον Οδηγό Εγκατάστασης.", "OpenSetupGuideMessage": "Ανοίξτε τον Οδηγό Εγκατάστασης.",
"NoUpdate": "Καμία Eνημέρωση", "NoUpdate": "Καμία Eνημέρωση",
"TitleUpdateVersionLabel": "Version {0} - {1}", "TitleUpdateVersionLabel": "Version {0} - {1}",
"TitleBundledUpdateVersionLabel": "Bundled: Version {0}",
"TitleBundledDlcLabel": "Bundled:",
"RyujinxInfo": "Ryujinx - Πληροφορίες", "RyujinxInfo": "Ryujinx - Πληροφορίες",
"RyujinxConfirm": "Ryujinx - Επιβεβαίωση", "RyujinxConfirm": "Ryujinx - Επιβεβαίωση",
"FileDialogAllTypes": "Όλοι οι τύποι", "FileDialogAllTypes": "Όλοι οι τύποι",
@ -714,9 +727,17 @@
"DlcWindowTitle": "Downloadable Content Manager", "DlcWindowTitle": "Downloadable Content Manager",
"ModWindowTitle": "Manage Mods for {0} ({1})", "ModWindowTitle": "Manage Mods for {0} ({1})",
"UpdateWindowTitle": "Διαχειριστής Ενημερώσεων Τίτλου", "UpdateWindowTitle": "Διαχειριστής Ενημερώσεων Τίτλου",
"UpdateWindowUpdateAddedMessage": "{0} new update(s) added",
"UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.",
"CheatWindowHeading": "Διαθέσιμα Cheats για {0} [{1}]", "CheatWindowHeading": "Διαθέσιμα Cheats για {0} [{1}]",
"BuildId": "BuildId:", "BuildId": "BuildId:",
"DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.",
"DlcWindowHeading": "{0} Downloadable Content(s) available for {1} ({2})", "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)", "ModWindowHeading": "{0} Mod(s)",
"UserProfilesEditProfile": "Επεξεργασία Επιλεγμένων", "UserProfilesEditProfile": "Επεξεργασία Επιλεγμένων",
"Cancel": "Ακύρωση", "Cancel": "Ακύρωση",
@ -767,6 +788,7 @@
"GraphicsScalingFilterBilinear": "Bilinear", "GraphicsScalingFilterBilinear": "Bilinear",
"GraphicsScalingFilterNearest": "Nearest", "GraphicsScalingFilterNearest": "Nearest",
"GraphicsScalingFilterFsr": "FSR", "GraphicsScalingFilterFsr": "FSR",
"GraphicsScalingFilterArea": "Area",
"GraphicsScalingFilterLevelLabel": "Επίπεδο", "GraphicsScalingFilterLevelLabel": "Επίπεδο",
"GraphicsScalingFilterLevelTooltip": "Set FSR 1.0 sharpening level. Higher is sharper.", "GraphicsScalingFilterLevelTooltip": "Set FSR 1.0 sharpening level. Higher is sharper.",
"SmaaLow": "Χαμηλό SMAA", "SmaaLow": "Χαμηλό SMAA",

View File

@ -33,6 +33,7 @@
"MenuBarToolsManageFileTypes": "Manage file types", "MenuBarToolsManageFileTypes": "Manage file types",
"MenuBarToolsInstallFileTypes": "Install file types", "MenuBarToolsInstallFileTypes": "Install file types",
"MenuBarToolsUninstallFileTypes": "Uninstall file types", "MenuBarToolsUninstallFileTypes": "Uninstall file types",
"MenuBarToolsXCITrimmer": "Trim XCI Files",
"MenuBarView": "_View", "MenuBarView": "_View",
"MenuBarViewWindow": "Window Size", "MenuBarViewWindow": "Window Size",
"MenuBarViewWindow720": "720p", "MenuBarViewWindow720": "720p",
@ -84,8 +85,11 @@
"GameListContextMenuOpenModsDirectoryToolTip": "Opens the directory which contains Application's Mods", "GameListContextMenuOpenModsDirectoryToolTip": "Opens the directory which contains Application's Mods",
"GameListContextMenuOpenSdModsDirectory": "Open Atmosphere Mods Directory", "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.", "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", "StatusBarGamesLoaded": "{0}/{1} Games Loaded",
"StatusBarSystemVersion": "System Version: {0}", "StatusBarSystemVersion": "System Version: {0}",
"StatusBarXCIFileTrimming": "Trimming XCI File '{0}'",
"LinuxVmMaxMapCountDialogTitle": "Low limit for memory mappings detected", "LinuxVmMaxMapCountDialogTitle": "Low limit for memory mappings detected",
"LinuxVmMaxMapCountDialogTextPrimary": "Would you like to increase the value of vm.max_map_count to {0}", "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.", "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", "InputDialogTitle": "Input Dialog",
"InputDialogOk": "OK", "InputDialogOk": "OK",
"InputDialogCancel": "Cancel", "InputDialogCancel": "Cancel",
"InputDialogCancelling": "Cancelling",
"InputDialogClose": "Close",
"InputDialogAddNewProfileTitle": "Choose the Profile Name", "InputDialogAddNewProfileTitle": "Choose the Profile Name",
"InputDialogAddNewProfileHeader": "Please Enter a Profile Name", "InputDialogAddNewProfileHeader": "Please Enter a Profile Name",
"InputDialogAddNewProfileSubtext": "(Max Length: {0})", "InputDialogAddNewProfileSubtext": "(Max Length: {0})",
@ -439,13 +445,13 @@
"DialogNcaExtractionMessage": "Extracting {0} section from {1}...", "DialogNcaExtractionMessage": "Extracting {0} section from {1}...",
"DialogNcaExtractionTitle": "Ryujinx - NCA Section Extractor", "DialogNcaExtractionTitle": "Ryujinx - NCA Section Extractor",
"DialogNcaExtractionMainNcaNotFoundErrorMessage": "Extraction failure. The main NCA was not present in the selected file.", "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.", "DialogNcaExtractionSuccessMessage": "Extraction completed successfully.",
"DialogUpdaterConvertFailedMessage": "Failed to convert the current Ryujinx version.", "DialogUpdaterConvertFailedMessage": "Unable to convert the current Ryujinx version.",
"DialogUpdaterCancelUpdateMessage": "Cancelling Update!", "DialogUpdaterCancelUpdateMessage": "Update canceled!",
"DialogUpdaterAlreadyOnLatestVersionMessage": "You are already using the most updated version of Ryujinx!", "DialogUpdaterAlreadyOnLatestVersionMessage": "You are already using the latest 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.", "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 received Ryujinx version from Github Release.", "DialogUpdaterConvertFailedGithubMessage": "Failed to convert the Ryujinx version received from GitHub.",
"DialogUpdaterDownloadingMessage": "Downloading Update...", "DialogUpdaterDownloadingMessage": "Downloading Update...",
"DialogUpdaterExtractionMessage": "Extracting Update...", "DialogUpdaterExtractionMessage": "Extracting Update...",
"DialogUpdaterRenamingMessage": "Renaming Update...", "DialogUpdaterRenamingMessage": "Renaming Update...",
@ -455,7 +461,7 @@
"DialogUpdaterNoInternetMessage": "You are not connected to the Internet!", "DialogUpdaterNoInternetMessage": "You are not connected to the Internet!",
"DialogUpdaterNoInternetSubMessage": "Please verify that you have a working Internet connection!", "DialogUpdaterNoInternetSubMessage": "Please verify that you have a working Internet connection!",
"DialogUpdaterDirtyBuildMessage": "You Cannot update a Dirty build of Ryujinx!", "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", "DialogRestartRequiredMessage": "Restart Required",
"DialogThemeRestartMessage": "Theme has been saved. A restart is needed to apply the theme.", "DialogThemeRestartMessage": "Theme has been saved. A restart is needed to apply the theme.",
"DialogThemeRestartSubMessage": "Do you want to restart", "DialogThemeRestartSubMessage": "Do you want to restart",
@ -468,6 +474,7 @@
"DialogUninstallFileTypesSuccessMessage": "Successfully uninstalled file types!", "DialogUninstallFileTypesSuccessMessage": "Successfully uninstalled file types!",
"DialogUninstallFileTypesErrorMessage": "Failed to uninstall file types.", "DialogUninstallFileTypesErrorMessage": "Failed to uninstall file types.",
"DialogOpenSettingsWindowLabel": "Open Settings Window", "DialogOpenSettingsWindowLabel": "Open Settings Window",
"DialogOpenXCITrimmerWindowLabel": "XCI Trimmer Window",
"DialogControllerAppletTitle": "Controller Applet", "DialogControllerAppletTitle": "Controller Applet",
"DialogMessageDialogErrorExceptionMessage": "Error displaying Message Dialog: {0}", "DialogMessageDialogErrorExceptionMessage": "Error displaying Message Dialog: {0}",
"DialogSoftwareKeyboardErrorExceptionMessage": "Error displaying Software Keyboard: {0}", "DialogSoftwareKeyboardErrorExceptionMessage": "Error displaying Software Keyboard: {0}",
@ -670,6 +677,12 @@
"TitleUpdateVersionLabel": "Version {0}", "TitleUpdateVersionLabel": "Version {0}",
"TitleBundledUpdateVersionLabel": "Bundled: Version {0}", "TitleBundledUpdateVersionLabel": "Bundled: Version {0}",
"TitleBundledDlcLabel": "Bundled:", "TitleBundledDlcLabel": "Bundled:",
"TitleXCIStatusPartialLabel": "Partial",
"TitleXCIStatusTrimmableLabel": "Untrimmed",
"TitleXCIStatusUntrimmableLabel": "Trimmed",
"TitleXCIStatusFailedLabel": "(Failed)",
"TitleXCICanSaveLabel": "Save {0:n0} Mb",
"TitleXCISavingLabel": "Saved {0:n0} Mb",
"RyujinxInfo": "Ryujinx - Info", "RyujinxInfo": "Ryujinx - Info",
"RyujinxConfirm": "Ryujinx - Confirmation", "RyujinxConfirm": "Ryujinx - Confirmation",
"FileDialogAllTypes": "All types", "FileDialogAllTypes": "All types",
@ -722,17 +735,43 @@
"SelectDlcDialogTitle": "Select DLC files", "SelectDlcDialogTitle": "Select DLC files",
"SelectUpdateDialogTitle": "Select update files", "SelectUpdateDialogTitle": "Select update files",
"SelectModDialogTitle": "Select mod directory", "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", "UserProfileWindowTitle": "User Profiles Manager",
"CheatWindowTitle": "Cheats Manager", "CheatWindowTitle": "Cheats Manager",
"DlcWindowTitle": "Manage Downloadable Content for {0} ({1})", "DlcWindowTitle": "Manage Downloadable Content for {0} ({1})",
"ModWindowTitle": "Manage Mods for {0} ({1})", "ModWindowTitle": "Manage Mods for {0} ({1})",
"UpdateWindowTitle": "Title Update Manager", "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", "UpdateWindowUpdateAddedMessage": "{0} new update(s) added",
"UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.", "UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.",
"CheatWindowHeading": "Cheats Available for {0} [{1}]", "CheatWindowHeading": "Cheats Available for {0} [{1}]",
"BuildId": "BuildId:", "BuildId": "BuildId:",
"DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.", "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", "DlcWindowDlcAddedMessage": "{0} new downloadable content(s) added",
"AutoloadDlcAddedMessage": "{0} new downloadable content(s) added", "AutoloadDlcAddedMessage": "{0} new downloadable content(s) added",
"AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed", "AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed",
@ -740,6 +779,7 @@
"AutoloadUpdateRemovedMessage": "{0} missing update(s) removed", "AutoloadUpdateRemovedMessage": "{0} missing update(s) removed",
"ModWindowHeading": "{0} Mod(s)", "ModWindowHeading": "{0} Mod(s)",
"UserProfilesEditProfile": "Edit Selected", "UserProfilesEditProfile": "Edit Selected",
"Continue": "Continue",
"Cancel": "Cancel", "Cancel": "Cancel",
"Save": "Save", "Save": "Save",
"Discard": "Discard", "Discard": "Discard",

View File

@ -10,7 +10,10 @@
"SettingsTabSystemUseHypervisor": "Usar hipervisor", "SettingsTabSystemUseHypervisor": "Usar hipervisor",
"MenuBarFile": "_Archivo", "MenuBarFile": "_Archivo",
"MenuBarFileOpenFromFile": "_Cargar aplicación desde un archivo", "MenuBarFileOpenFromFile": "_Cargar aplicación desde un archivo",
"MenuBarFileOpenFromFileError": "No applications found in selected file.",
"MenuBarFileOpenUnpacked": "Cargar juego _desempaquetado", "MenuBarFileOpenUnpacked": "Cargar juego _desempaquetado",
"MenuBarFileLoadDlcFromFolder": "Load DLC From Folder",
"MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder",
"MenuBarFileOpenEmuFolder": "Abrir carpeta de Ryujinx", "MenuBarFileOpenEmuFolder": "Abrir carpeta de Ryujinx",
"MenuBarFileOpenLogsFolder": "Abrir carpeta de registros", "MenuBarFileOpenLogsFolder": "Abrir carpeta de registros",
"MenuBarFileExit": "_Salir", "MenuBarFileExit": "_Salir",
@ -103,6 +106,8 @@
"SettingsTabGeneralHideCursorOnIdle": "Ocultar cursor cuando esté inactivo", "SettingsTabGeneralHideCursorOnIdle": "Ocultar cursor cuando esté inactivo",
"SettingsTabGeneralHideCursorAlways": "Siempre", "SettingsTabGeneralHideCursorAlways": "Siempre",
"SettingsTabGeneralGameDirectories": "Carpetas de juegos", "SettingsTabGeneralGameDirectories": "Carpetas de juegos",
"SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories",
"SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically",
"SettingsTabGeneralAdd": "Agregar", "SettingsTabGeneralAdd": "Agregar",
"SettingsTabGeneralRemove": "Quitar", "SettingsTabGeneralRemove": "Quitar",
"SettingsTabSystem": "Sistema", "SettingsTabSystem": "Sistema",
@ -411,6 +416,7 @@
"GameListContextMenuToggleFavorite": "Marcar favorito", "GameListContextMenuToggleFavorite": "Marcar favorito",
"GameListContextMenuToggleFavoriteToolTip": "Marca o desmarca el juego como favorito", "GameListContextMenuToggleFavoriteToolTip": "Marca o desmarca el juego como favorito",
"SettingsTabGeneralTheme": "Tema:", "SettingsTabGeneralTheme": "Tema:",
"SettingsTabGeneralThemeAuto": "Auto",
"SettingsTabGeneralThemeDark": "Oscuro", "SettingsTabGeneralThemeDark": "Oscuro",
"SettingsTabGeneralThemeLight": "Claro", "SettingsTabGeneralThemeLight": "Claro",
"ControllerSettingsConfigureGeneral": "Configurar", "ControllerSettingsConfigureGeneral": "Configurar",
@ -561,6 +567,9 @@
"AddGameDirBoxTooltip": "Elige un directorio de juegos para mostrar en la ventana principal", "AddGameDirBoxTooltip": "Elige un directorio de juegos para mostrar en la ventana principal",
"AddGameDirTooltip": "Agrega un directorio de juegos a la lista", "AddGameDirTooltip": "Agrega un directorio de juegos a la lista",
"RemoveGameDirTooltip": "Quita el directorio seleccionado de 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", "CustomThemeCheckTooltip": "Activa o desactiva los temas personalizados para la interfaz",
"CustomThemePathTooltip": "Carpeta que contiene los temas personalizados para la interfaz", "CustomThemePathTooltip": "Carpeta que contiene los temas personalizados para la interfaz",
"CustomThemeBrowseTooltip": "Busca un tema personalizado 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.", "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", "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", "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", "OpenRyujinxFolderTooltip": "Abre la carpeta de sistema de Ryujinx",
"OpenRyujinxLogsTooltip": "Abre la carpeta en la que se guardan los registros", "OpenRyujinxLogsTooltip": "Abre la carpeta en la que se guardan los registros",
"ExitTooltip": "Cierra Ryujinx", "ExitTooltip": "Cierra Ryujinx",
@ -657,6 +668,8 @@
"OpenSetupGuideMessage": "Abrir la guía de instalación", "OpenSetupGuideMessage": "Abrir la guía de instalación",
"NoUpdate": "No actualizado", "NoUpdate": "No actualizado",
"TitleUpdateVersionLabel": "Versión {0} - {1}", "TitleUpdateVersionLabel": "Versión {0} - {1}",
"TitleBundledUpdateVersionLabel": "Bundled: Version {0}",
"TitleBundledDlcLabel": "Bundled:",
"RyujinxInfo": "Ryujinx - Info", "RyujinxInfo": "Ryujinx - Info",
"RyujinxConfirm": "Ryujinx - Confirmación", "RyujinxConfirm": "Ryujinx - Confirmación",
"FileDialogAllTypes": "Todos los tipos", "FileDialogAllTypes": "Todos los tipos",
@ -714,9 +727,16 @@
"DlcWindowTitle": "Administrar contenido descargable", "DlcWindowTitle": "Administrar contenido descargable",
"ModWindowTitle": "Manage Mods for {0} ({1})", "ModWindowTitle": "Manage Mods for {0} ({1})",
"UpdateWindowTitle": "Administrar actualizaciones", "UpdateWindowTitle": "Administrar actualizaciones",
"UpdateWindowUpdateAddedMessage": "{0} new update(s) added",
"UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.",
"CheatWindowHeading": "Cheats disponibles para {0} [{1}]", "CheatWindowHeading": "Cheats disponibles para {0} [{1}]",
"BuildId": "Id de compilación:", "BuildId": "Id de compilación:",
"DlcWindowHeading": "Contenido descargable disponible para {0} [{1}]", "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)", "ModWindowHeading": "{0} Mod(s)",
"UserProfilesEditProfile": "Editar selección", "UserProfilesEditProfile": "Editar selección",
"Cancel": "Cancelar", "Cancel": "Cancelar",
@ -767,6 +787,7 @@
"GraphicsScalingFilterBilinear": "Bilinear\n", "GraphicsScalingFilterBilinear": "Bilinear\n",
"GraphicsScalingFilterNearest": "Cercano", "GraphicsScalingFilterNearest": "Cercano",
"GraphicsScalingFilterFsr": "FSR", "GraphicsScalingFilterFsr": "FSR",
"GraphicsScalingFilterArea": "Area",
"GraphicsScalingFilterLevelLabel": "Nivel", "GraphicsScalingFilterLevelLabel": "Nivel",
"GraphicsScalingFilterLevelTooltip": "Ajuste el nivel de nitidez FSR 1.0. Mayor es más nítido.", "GraphicsScalingFilterLevelTooltip": "Ajuste el nivel de nitidez FSR 1.0. Mayor es más nítido.",
"SmaaLow": "SMAA Bajo", "SmaaLow": "SMAA Bajo",

View File

@ -100,7 +100,7 @@
"SettingsTabGeneralCheckUpdatesOnLaunch": "Vérifier les mises à jour au démarrage", "SettingsTabGeneralCheckUpdatesOnLaunch": "Vérifier les mises à jour au démarrage",
"SettingsTabGeneralShowConfirmExitDialog": "Afficher le message de \"Confirmation de sortie\"", "SettingsTabGeneralShowConfirmExitDialog": "Afficher le message de \"Confirmation de sortie\"",
"SettingsTabGeneralRememberWindowState": "Mémoriser la taille/position de la fenêtre", "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 :", "SettingsTabGeneralHideCursor": "Masquer le Curseur :",
"SettingsTabGeneralHideCursorNever": "Jamais", "SettingsTabGeneralHideCursorNever": "Jamais",
"SettingsTabGeneralHideCursorOnIdle": "Masquer le curseur si inactif", "SettingsTabGeneralHideCursorOnIdle": "Masquer le curseur si inactif",
@ -151,7 +151,7 @@
"SettingsTabSystemAudioBackendSDL2": "SDL2", "SettingsTabSystemAudioBackendSDL2": "SDL2",
"SettingsTabSystemHacks": "Hacks", "SettingsTabSystemHacks": "Hacks",
"SettingsTabSystemHacksNote": "Cela peut causer des instabilités", "SettingsTabSystemHacksNote": "Cela peut causer des instabilités",
"SettingsTabSystemDramSize": "Taille de la DRAM:", "SettingsTabSystemDramSize": "Taille de la DRAM :",
"SettingsTabSystemDramSize4GiB": "4GiO", "SettingsTabSystemDramSize4GiB": "4GiO",
"SettingsTabSystemDramSize6GiB": "6GiO", "SettingsTabSystemDramSize6GiB": "6GiO",
"SettingsTabSystemDramSize8GiB": "8GiO", "SettingsTabSystemDramSize8GiB": "8GiO",
@ -181,7 +181,7 @@
"SettingsTabGraphicsAspectRatio32x9": "32:9", "SettingsTabGraphicsAspectRatio32x9": "32:9",
"SettingsTabGraphicsAspectRatioStretch": "Étirer pour remplir la fenêtre", "SettingsTabGraphicsAspectRatioStretch": "Étirer pour remplir la fenêtre",
"SettingsTabGraphicsDeveloperOptions": "Options développeur", "SettingsTabGraphicsDeveloperOptions": "Options développeur",
"SettingsTabGraphicsShaderDumpPath": "Chemin du dossier de copie des shaders:", "SettingsTabGraphicsShaderDumpPath": "Chemin du dossier de copie des shaders :",
"SettingsTabLogging": "Journaux", "SettingsTabLogging": "Journaux",
"SettingsTabLoggingLogging": "Journaux", "SettingsTabLoggingLogging": "Journaux",
"SettingsTabLoggingEnableLoggingToFile": "Activer la sauvegarde des journaux vers un fichier", "SettingsTabLoggingEnableLoggingToFile": "Activer la sauvegarde des journaux vers un fichier",
@ -387,7 +387,7 @@
"UserProfilesSelectedUserProfile": "Profil utilisateur sélectionné :", "UserProfilesSelectedUserProfile": "Profil utilisateur sélectionné :",
"UserProfilesSaveProfileName": "Enregistrer le nom du profil", "UserProfilesSaveProfileName": "Enregistrer le nom du profil",
"UserProfilesChangeProfileImage": "Changer l'image du profil", "UserProfilesChangeProfileImage": "Changer l'image du profil",
"UserProfilesAvailableUserProfiles": "Profils utilisateurs disponibles:", "UserProfilesAvailableUserProfiles": "Profils utilisateurs disponibles :",
"UserProfilesAddNewProfile": "Créer un profil", "UserProfilesAddNewProfile": "Créer un profil",
"UserProfilesDelete": "Supprimer", "UserProfilesDelete": "Supprimer",
"UserProfilesClose": "Fermer", "UserProfilesClose": "Fermer",
@ -669,7 +669,7 @@
"NoUpdate": "Aucune mise à jour", "NoUpdate": "Aucune mise à jour",
"TitleUpdateVersionLabel": "Version {0}", "TitleUpdateVersionLabel": "Version {0}",
"TitleBundledUpdateVersionLabel": "Inclus avec le jeu: Version {0}", "TitleBundledUpdateVersionLabel": "Inclus avec le jeu: Version {0}",
"TitleBundledDlcLabel": "Inclus avec le jeu:", "TitleBundledDlcLabel": "Inclus avec le jeu :",
"RyujinxInfo": "Ryujinx - Info", "RyujinxInfo": "Ryujinx - Info",
"RyujinxConfirm": "Ryujinx - Confirmation", "RyujinxConfirm": "Ryujinx - Confirmation",
"FileDialogAllTypes": "Tous les types", "FileDialogAllTypes": "Tous les types",

View File

@ -10,7 +10,10 @@
"SettingsTabSystemUseHypervisor": "השתמש ב Hypervisor", "SettingsTabSystemUseHypervisor": "השתמש ב Hypervisor",
"MenuBarFile": "_קובץ", "MenuBarFile": "_קובץ",
"MenuBarFileOpenFromFile": "_טען יישום מקובץ", "MenuBarFileOpenFromFile": "_טען יישום מקובץ",
"MenuBarFileOpenFromFileError": "No applications found in selected file.",
"MenuBarFileOpenUnpacked": "טען משחק _שאינו ארוז", "MenuBarFileOpenUnpacked": "טען משחק _שאינו ארוז",
"MenuBarFileLoadDlcFromFolder": "Load DLC From Folder",
"MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder",
"MenuBarFileOpenEmuFolder": "פתח את תיקיית ריוג'ינקס", "MenuBarFileOpenEmuFolder": "פתח את תיקיית ריוג'ינקס",
"MenuBarFileOpenLogsFolder": "פתח את תיקיית קבצי הלוג", "MenuBarFileOpenLogsFolder": "פתח את תיקיית קבצי הלוג",
"MenuBarFileExit": "_יציאה", "MenuBarFileExit": "_יציאה",
@ -103,6 +106,8 @@
"SettingsTabGeneralHideCursorOnIdle": "במצב סרק", "SettingsTabGeneralHideCursorOnIdle": "במצב סרק",
"SettingsTabGeneralHideCursorAlways": "תמיד", "SettingsTabGeneralHideCursorAlways": "תמיד",
"SettingsTabGeneralGameDirectories": "תקיות משחקים", "SettingsTabGeneralGameDirectories": "תקיות משחקים",
"SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories",
"SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically",
"SettingsTabGeneralAdd": "הוסף", "SettingsTabGeneralAdd": "הוסף",
"SettingsTabGeneralRemove": "הסר", "SettingsTabGeneralRemove": "הסר",
"SettingsTabSystem": "מערכת", "SettingsTabSystem": "מערכת",
@ -411,6 +416,7 @@
"GameListContextMenuToggleFavorite": "למתג העדפה", "GameListContextMenuToggleFavorite": "למתג העדפה",
"GameListContextMenuToggleFavoriteToolTip": "למתג סטטוס העדפה של משחק", "GameListContextMenuToggleFavoriteToolTip": "למתג סטטוס העדפה של משחק",
"SettingsTabGeneralTheme": "ערכת נושא:", "SettingsTabGeneralTheme": "ערכת נושא:",
"SettingsTabGeneralThemeAuto": "Auto",
"SettingsTabGeneralThemeDark": "כהה", "SettingsTabGeneralThemeDark": "כהה",
"SettingsTabGeneralThemeLight": "בהיר", "SettingsTabGeneralThemeLight": "בהיר",
"ControllerSettingsConfigureGeneral": "הגדר", "ControllerSettingsConfigureGeneral": "הגדר",
@ -561,6 +567,9 @@
"AddGameDirBoxTooltip": "הזן תקיית משחקים כדי להוסיף לרשימה", "AddGameDirBoxTooltip": "הזן תקיית משחקים כדי להוסיף לרשימה",
"AddGameDirTooltip": "הוסף תקיית משחקים לרשימה", "AddGameDirTooltip": "הוסף תקיית משחקים לרשימה",
"RemoveGameDirTooltip": "הסר את תקיית המשחקים שנבחרה", "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": "השתמש בעיצוב מותאם אישית של אבלוניה עבור ה-ממשק הגראפי כדי לשנות את המראה של תפריטי האמולטור", "CustomThemeCheckTooltip": "השתמש בעיצוב מותאם אישית של אבלוניה עבור ה-ממשק הגראפי כדי לשנות את המראה של תפריטי האמולטור",
"CustomThemePathTooltip": "נתיב לערכת נושא לממשק גראפי מותאם אישית", "CustomThemePathTooltip": "נתיב לערכת נושא לממשק גראפי מותאם אישית",
"CustomThemeBrowseTooltip": "חפש עיצוב ממשק גראפי מותאם אישית", "CustomThemeBrowseTooltip": "חפש עיצוב ממשק גראפי מותאם אישית",
@ -606,6 +615,8 @@
"DebugLogTooltip": "מדפיס הודעות יומן ניפוי באגים בשורת הפקודות.", "DebugLogTooltip": "מדפיס הודעות יומן ניפוי באגים בשורת הפקודות.",
"LoadApplicationFileTooltip": "פתח סייר קבצים כדי לבחור קובץ תואם סוויץ' לטעינה", "LoadApplicationFileTooltip": "פתח סייר קבצים כדי לבחור קובץ תואם סוויץ' לטעינה",
"LoadApplicationFolderTooltip": "פתח סייר קבצים כדי לבחור יישום תואם סוויץ', לא ארוז לטעינה.", "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": "פתח את תיקיית מערכת הקבצים ריוג'ינקס", "OpenRyujinxFolderTooltip": "פתח את תיקיית מערכת הקבצים ריוג'ינקס",
"OpenRyujinxLogsTooltip": "פותח את התיקיה שאליה נכתבים רישומים", "OpenRyujinxLogsTooltip": "פותח את התיקיה שאליה נכתבים רישומים",
"ExitTooltip": "צא מריוג'ינקס", "ExitTooltip": "צא מריוג'ינקס",
@ -657,6 +668,8 @@
"OpenSetupGuideMessage": "פתח מדריך התקנה", "OpenSetupGuideMessage": "פתח מדריך התקנה",
"NoUpdate": "אין עדכון", "NoUpdate": "אין עדכון",
"TitleUpdateVersionLabel": "גרסה {0}", "TitleUpdateVersionLabel": "גרסה {0}",
"TitleBundledUpdateVersionLabel": "Bundled: Version {0}",
"TitleBundledDlcLabel": "Bundled:",
"RyujinxInfo": "ריוג'ינקס - מידע", "RyujinxInfo": "ריוג'ינקס - מידע",
"RyujinxConfirm": "ריוג'ינקס - אישור", "RyujinxConfirm": "ריוג'ינקס - אישור",
"FileDialogAllTypes": "כל הסוגים", "FileDialogAllTypes": "כל הסוגים",
@ -714,9 +727,17 @@
"DlcWindowTitle": "נהל הרחבות משחק עבור {0} ({1})", "DlcWindowTitle": "נהל הרחבות משחק עבור {0} ({1})",
"ModWindowTitle": "Manage Mods for {0} ({1})", "ModWindowTitle": "Manage Mods for {0} ({1})",
"UpdateWindowTitle": "נהל עדכוני משחקים", "UpdateWindowTitle": "נהל עדכוני משחקים",
"UpdateWindowUpdateAddedMessage": "{0} new update(s) added",
"UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.",
"CheatWindowHeading": "צ'יטים זמינים עבור {0} [{1}]", "CheatWindowHeading": "צ'יטים זמינים עבור {0} [{1}]",
"BuildId": "מזהה בניה:", "BuildId": "מזהה בניה:",
"DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.",
"DlcWindowHeading": "{0} הרחבות משחק", "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} מוד(ים)", "ModWindowHeading": "{0} מוד(ים)",
"UserProfilesEditProfile": "ערוך נבחר/ים", "UserProfilesEditProfile": "ערוך נבחר/ים",
"Cancel": "בטל", "Cancel": "בטל",
@ -767,6 +788,7 @@
"GraphicsScalingFilterBilinear": "Bilinear", "GraphicsScalingFilterBilinear": "Bilinear",
"GraphicsScalingFilterNearest": "Nearest", "GraphicsScalingFilterNearest": "Nearest",
"GraphicsScalingFilterFsr": "FSR", "GraphicsScalingFilterFsr": "FSR",
"GraphicsScalingFilterArea": "Area",
"GraphicsScalingFilterLevelLabel": "רמה", "GraphicsScalingFilterLevelLabel": "רמה",
"GraphicsScalingFilterLevelTooltip": "Set FSR 1.0 sharpening level. Higher is sharper.", "GraphicsScalingFilterLevelTooltip": "Set FSR 1.0 sharpening level. Higher is sharper.",
"SmaaLow": "SMAA נמוך", "SmaaLow": "SMAA נמוך",

View File

@ -788,12 +788,12 @@
"GraphicsScalingFilterBilinear": "Bilineare", "GraphicsScalingFilterBilinear": "Bilineare",
"GraphicsScalingFilterNearest": "Nearest", "GraphicsScalingFilterNearest": "Nearest",
"GraphicsScalingFilterFsr": "FSR", "GraphicsScalingFilterFsr": "FSR",
"GraphicsScalingFilterArea": "Area",
"GraphicsScalingFilterLevelLabel": "Livello", "GraphicsScalingFilterLevelLabel": "Livello",
"GraphicsScalingFilterLevelTooltip": "Imposta il livello di nitidezza di FSR 1.0. Valori più alti comportano una maggiore nitidezza.", "GraphicsScalingFilterLevelTooltip": "Imposta il livello di nitidezza di FSR 1.0. Valori più alti comportano una maggiore nitidezza.",
"SmaaLow": "SMAA Basso", "SmaaLow": "SMAA Basso",
"SmaaMedium": "SMAA Medio", "SmaaMedium": "SMAA Medio",
"SmaaHigh": "SMAA Alto", "SmaaHigh": "SMAA Alto",
"GraphicsScalingFilterArea": "Area",
"SmaaUltra": "SMAA Ultra", "SmaaUltra": "SMAA Ultra",
"UserEditorTitle": "Modificare L'Utente", "UserEditorTitle": "Modificare L'Utente",
"UserEditorTitleCreate": "Crea Un Utente", "UserEditorTitleCreate": "Crea Un Utente",

View File

@ -10,7 +10,10 @@
"SettingsTabSystemUseHypervisor": "ハイパーバイザーを使用", "SettingsTabSystemUseHypervisor": "ハイパーバイザーを使用",
"MenuBarFile": "ファイル(_F)", "MenuBarFile": "ファイル(_F)",
"MenuBarFileOpenFromFile": "ファイルからアプリケーションをロード(_L)", "MenuBarFileOpenFromFile": "ファイルからアプリケーションをロード(_L)",
"MenuBarFileOpenFromFileError": "No applications found in selected file.",
"MenuBarFileOpenUnpacked": "展開されたゲームをロード", "MenuBarFileOpenUnpacked": "展開されたゲームをロード",
"MenuBarFileLoadDlcFromFolder": "Load DLC From Folder",
"MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder",
"MenuBarFileOpenEmuFolder": "Ryujinx フォルダを開く", "MenuBarFileOpenEmuFolder": "Ryujinx フォルダを開く",
"MenuBarFileOpenLogsFolder": "ログフォルダを開く", "MenuBarFileOpenLogsFolder": "ログフォルダを開く",
"MenuBarFileExit": "終了(_E)", "MenuBarFileExit": "終了(_E)",
@ -103,6 +106,8 @@
"SettingsTabGeneralHideCursorOnIdle": "アイドル時", "SettingsTabGeneralHideCursorOnIdle": "アイドル時",
"SettingsTabGeneralHideCursorAlways": "常時", "SettingsTabGeneralHideCursorAlways": "常時",
"SettingsTabGeneralGameDirectories": "ゲームディレクトリ", "SettingsTabGeneralGameDirectories": "ゲームディレクトリ",
"SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories",
"SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically",
"SettingsTabGeneralAdd": "追加", "SettingsTabGeneralAdd": "追加",
"SettingsTabGeneralRemove": "削除", "SettingsTabGeneralRemove": "削除",
"SettingsTabSystem": "システム", "SettingsTabSystem": "システム",
@ -411,6 +416,7 @@
"GameListContextMenuToggleFavorite": "お気に入りを切り替え", "GameListContextMenuToggleFavorite": "お気に入りを切り替え",
"GameListContextMenuToggleFavoriteToolTip": "ゲームをお気に入りに含めるかどうかを切り替えます", "GameListContextMenuToggleFavoriteToolTip": "ゲームをお気に入りに含めるかどうかを切り替えます",
"SettingsTabGeneralTheme": "テーマ:", "SettingsTabGeneralTheme": "テーマ:",
"SettingsTabGeneralThemeAuto": "Auto",
"SettingsTabGeneralThemeDark": "ダーク", "SettingsTabGeneralThemeDark": "ダーク",
"SettingsTabGeneralThemeLight": "ライト", "SettingsTabGeneralThemeLight": "ライト",
"ControllerSettingsConfigureGeneral": "設定", "ControllerSettingsConfigureGeneral": "設定",
@ -561,6 +567,9 @@
"AddGameDirBoxTooltip": "リストに追加するゲームディレクトリを入力します", "AddGameDirBoxTooltip": "リストに追加するゲームディレクトリを入力します",
"AddGameDirTooltip": "リストにゲームディレクトリを追加します", "AddGameDirTooltip": "リストにゲームディレクトリを追加します",
"RemoveGameDirTooltip": "選択したゲームディレクトリを削除します", "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 テーマを使用します", "CustomThemeCheckTooltip": "エミュレータのメニュー外観を変更するためカスタム Avalonia テーマを使用します",
"CustomThemePathTooltip": "カスタム GUI テーマのパスです", "CustomThemePathTooltip": "カスタム GUI テーマのパスです",
"CustomThemeBrowseTooltip": "カスタム GUI テーマを参照します", "CustomThemeBrowseTooltip": "カスタム GUI テーマを参照します",
@ -606,6 +615,8 @@
"DebugLogTooltip": "デバッグログメッセージをコンソールに出力します.\n\nログが読みづらくなり,エミュレータのパフォーマンスが低下するため,開発者から特別な指示がある場合のみ使用してください.", "DebugLogTooltip": "デバッグログメッセージをコンソールに出力します.\n\nログが読みづらくなり,エミュレータのパフォーマンスが低下するため,開発者から特別な指示がある場合のみ使用してください.",
"LoadApplicationFileTooltip": "ロードする Switch 互換のファイルを選択するためファイルエクスプローラを開きます", "LoadApplicationFileTooltip": "ロードする Switch 互換のファイルを選択するためファイルエクスプローラを開きます",
"LoadApplicationFolderTooltip": "ロードする 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 ファイルシステムフォルダを開きます", "OpenRyujinxFolderTooltip": "Ryujinx ファイルシステムフォルダを開きます",
"OpenRyujinxLogsTooltip": "ログが格納されるフォルダを開きます", "OpenRyujinxLogsTooltip": "ログが格納されるフォルダを開きます",
"ExitTooltip": "Ryujinx を終了します", "ExitTooltip": "Ryujinx を終了します",
@ -657,6 +668,8 @@
"OpenSetupGuideMessage": "セットアップガイドを開く", "OpenSetupGuideMessage": "セットアップガイドを開く",
"NoUpdate": "アップデートなし", "NoUpdate": "アップデートなし",
"TitleUpdateVersionLabel": "バージョン {0} - {1}", "TitleUpdateVersionLabel": "バージョン {0} - {1}",
"TitleBundledUpdateVersionLabel": "Bundled: Version {0}",
"TitleBundledDlcLabel": "Bundled:",
"RyujinxInfo": "Ryujinx - 情報", "RyujinxInfo": "Ryujinx - 情報",
"RyujinxConfirm": "Ryujinx - 確認", "RyujinxConfirm": "Ryujinx - 確認",
"FileDialogAllTypes": "すべての種別", "FileDialogAllTypes": "すべての種別",
@ -714,9 +727,16 @@
"DlcWindowTitle": "DLC 管理", "DlcWindowTitle": "DLC 管理",
"ModWindowTitle": "Manage Mods for {0} ({1})", "ModWindowTitle": "Manage Mods for {0} ({1})",
"UpdateWindowTitle": "アップデート管理", "UpdateWindowTitle": "アップデート管理",
"UpdateWindowUpdateAddedMessage": "{0} new update(s) added",
"UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.",
"CheatWindowHeading": "利用可能なチート {0} [{1}]", "CheatWindowHeading": "利用可能なチート {0} [{1}]",
"BuildId": "ビルドID:", "BuildId": "ビルドID:",
"DlcWindowHeading": "利用可能な DLC {0} [{1}]", "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)", "ModWindowHeading": "{0} Mod(s)",
"UserProfilesEditProfile": "編集", "UserProfilesEditProfile": "編集",
"Cancel": "キャンセル", "Cancel": "キャンセル",
@ -767,6 +787,7 @@
"GraphicsScalingFilterBilinear": "Bilinear", "GraphicsScalingFilterBilinear": "Bilinear",
"GraphicsScalingFilterNearest": "Nearest", "GraphicsScalingFilterNearest": "Nearest",
"GraphicsScalingFilterFsr": "FSR", "GraphicsScalingFilterFsr": "FSR",
"GraphicsScalingFilterArea": "Area",
"GraphicsScalingFilterLevelLabel": "レベル", "GraphicsScalingFilterLevelLabel": "レベル",
"GraphicsScalingFilterLevelTooltip": "FSR 1.0のシャープ化レベルを設定します. 高い値ほどシャープになります.", "GraphicsScalingFilterLevelTooltip": "FSR 1.0のシャープ化レベルを設定します. 高い値ほどシャープになります.",
"SmaaLow": "SMAA Low", "SmaaLow": "SMAA Low",

View File

@ -10,7 +10,10 @@
"SettingsTabSystemUseHypervisor": "하이퍼바이저 사용하기", "SettingsTabSystemUseHypervisor": "하이퍼바이저 사용하기",
"MenuBarFile": "_파일", "MenuBarFile": "_파일",
"MenuBarFileOpenFromFile": "_파일에서 응용 프로그램 불러오기", "MenuBarFileOpenFromFile": "_파일에서 응용 프로그램 불러오기",
"MenuBarFileOpenFromFileError": "No applications found in selected file.",
"MenuBarFileOpenUnpacked": "_압축을 푼 게임 불러오기", "MenuBarFileOpenUnpacked": "_압축을 푼 게임 불러오기",
"MenuBarFileLoadDlcFromFolder": "Load DLC From Folder",
"MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder",
"MenuBarFileOpenEmuFolder": "Ryujinx 폴더 열기", "MenuBarFileOpenEmuFolder": "Ryujinx 폴더 열기",
"MenuBarFileOpenLogsFolder": "로그 폴더 열기", "MenuBarFileOpenLogsFolder": "로그 폴더 열기",
"MenuBarFileExit": "_종료", "MenuBarFileExit": "_종료",
@ -103,6 +106,8 @@
"SettingsTabGeneralHideCursorOnIdle": "유휴 상태", "SettingsTabGeneralHideCursorOnIdle": "유휴 상태",
"SettingsTabGeneralHideCursorAlways": "언제나", "SettingsTabGeneralHideCursorAlways": "언제나",
"SettingsTabGeneralGameDirectories": "게임 디렉터리", "SettingsTabGeneralGameDirectories": "게임 디렉터리",
"SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories",
"SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically",
"SettingsTabGeneralAdd": "추가", "SettingsTabGeneralAdd": "추가",
"SettingsTabGeneralRemove": "제거", "SettingsTabGeneralRemove": "제거",
"SettingsTabSystem": "시스템", "SettingsTabSystem": "시스템",
@ -411,6 +416,7 @@
"GameListContextMenuToggleFavorite": "즐겨찾기 전환", "GameListContextMenuToggleFavorite": "즐겨찾기 전환",
"GameListContextMenuToggleFavoriteToolTip": "게임 즐겨찾기 상태 전환", "GameListContextMenuToggleFavoriteToolTip": "게임 즐겨찾기 상태 전환",
"SettingsTabGeneralTheme": "테마:", "SettingsTabGeneralTheme": "테마:",
"SettingsTabGeneralThemeAuto": "Auto",
"SettingsTabGeneralThemeDark": "어두운 테마", "SettingsTabGeneralThemeDark": "어두운 테마",
"SettingsTabGeneralThemeLight": "밝은 테마", "SettingsTabGeneralThemeLight": "밝은 테마",
"ControllerSettingsConfigureGeneral": "구성", "ControllerSettingsConfigureGeneral": "구성",
@ -561,6 +567,9 @@
"AddGameDirBoxTooltip": "목록에 추가할 게임 디렉터리 입력", "AddGameDirBoxTooltip": "목록에 추가할 게임 디렉터리 입력",
"AddGameDirTooltip": "목록에 게임 디렉터리 추가", "AddGameDirTooltip": "목록에 게임 디렉터리 추가",
"RemoveGameDirTooltip": "선택한 게임 디렉터리 제거", "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 테마를 사용하여 에뮬레이터 메뉴의 모양 변경", "CustomThemeCheckTooltip": "GUI에 사용자 지정 Avalonia 테마를 사용하여 에뮬레이터 메뉴의 모양 변경",
"CustomThemePathTooltip": "사용자 정의 GUI 테마 경로", "CustomThemePathTooltip": "사용자 정의 GUI 테마 경로",
"CustomThemeBrowseTooltip": "사용자 정의 GUI 테마 찾아보기", "CustomThemeBrowseTooltip": "사용자 정의 GUI 테마 찾아보기",
@ -606,6 +615,8 @@
"DebugLogTooltip": "콘솔에 디버그 로그 메시지를 인쇄합니다.\n\n로그를 읽기 어렵게 만들고 에뮬레이터 성능을 악화시키므로 직원이 구체적으로 지시한 경우에만 사용하세요.", "DebugLogTooltip": "콘솔에 디버그 로그 메시지를 인쇄합니다.\n\n로그를 읽기 어렵게 만들고 에뮬레이터 성능을 악화시키므로 직원이 구체적으로 지시한 경우에만 사용하세요.",
"LoadApplicationFileTooltip": "파일 탐색기를 열어 불러올 스위치 호환 파일 선택", "LoadApplicationFileTooltip": "파일 탐색기를 열어 불러올 스위치 호환 파일 선택",
"LoadApplicationFolderTooltip": "파일 탐색기를 열어 불러올 스위치 호환 압축 해제 응용 프로그램 선택", "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 파일 시스템 폴더 열기", "OpenRyujinxFolderTooltip": "Ryujinx 파일 시스템 폴더 열기",
"OpenRyujinxLogsTooltip": "로그가 기록된 폴더 열기", "OpenRyujinxLogsTooltip": "로그가 기록된 폴더 열기",
"ExitTooltip": "Ryujinx 종료", "ExitTooltip": "Ryujinx 종료",
@ -657,6 +668,8 @@
"OpenSetupGuideMessage": "설정 가이드 열기", "OpenSetupGuideMessage": "설정 가이드 열기",
"NoUpdate": "업데이트 없음", "NoUpdate": "업데이트 없음",
"TitleUpdateVersionLabel": "버전 {0}", "TitleUpdateVersionLabel": "버전 {0}",
"TitleBundledUpdateVersionLabel": "Bundled: Version {0}",
"TitleBundledDlcLabel": "Bundled:",
"RyujinxInfo": "Ryujinx - 정보", "RyujinxInfo": "Ryujinx - 정보",
"RyujinxConfirm": "Ryujinx - 확인", "RyujinxConfirm": "Ryujinx - 확인",
"FileDialogAllTypes": "모든 유형", "FileDialogAllTypes": "모든 유형",
@ -714,9 +727,17 @@
"DlcWindowTitle": "{0} ({1})의 다운로드 가능한 콘텐츠 관리", "DlcWindowTitle": "{0} ({1})의 다운로드 가능한 콘텐츠 관리",
"ModWindowTitle": "{0} ({1})의 Mod 관리", "ModWindowTitle": "{0} ({1})의 Mod 관리",
"UpdateWindowTitle": "타이틀 업데이트 관리자", "UpdateWindowTitle": "타이틀 업데이트 관리자",
"UpdateWindowUpdateAddedMessage": "{0} new update(s) added",
"UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.",
"CheatWindowHeading": "{0} [{1}]에 사용할 수 있는 치트", "CheatWindowHeading": "{0} [{1}]에 사용할 수 있는 치트",
"BuildId": "빌드ID :", "BuildId": "빌드ID :",
"DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.",
"DlcWindowHeading": "{0} 내려받기 가능한 콘텐츠", "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)", "ModWindowHeading": "{0} Mod(s)",
"UserProfilesEditProfile": "선택된 항목 편집", "UserProfilesEditProfile": "선택된 항목 편집",
"Cancel": "취소", "Cancel": "취소",
@ -767,6 +788,7 @@
"GraphicsScalingFilterBilinear": "Bilinear", "GraphicsScalingFilterBilinear": "Bilinear",
"GraphicsScalingFilterNearest": "Nearest", "GraphicsScalingFilterNearest": "Nearest",
"GraphicsScalingFilterFsr": "FSR", "GraphicsScalingFilterFsr": "FSR",
"GraphicsScalingFilterArea": "Area",
"GraphicsScalingFilterLevelLabel": "수준", "GraphicsScalingFilterLevelLabel": "수준",
"GraphicsScalingFilterLevelTooltip": "FSR 1.0의 샤프닝 레벨을 설정하세요. 높을수록 더 또렷해집니다.", "GraphicsScalingFilterLevelTooltip": "FSR 1.0의 샤프닝 레벨을 설정하세요. 높을수록 더 또렷해집니다.",
"SmaaLow": "SMAA 낮음", "SmaaLow": "SMAA 낮음",

View File

@ -10,7 +10,10 @@
"SettingsTabSystemUseHypervisor": "Użyj Hipernadzorcy", "SettingsTabSystemUseHypervisor": "Użyj Hipernadzorcy",
"MenuBarFile": "_Plik", "MenuBarFile": "_Plik",
"MenuBarFileOpenFromFile": "_Załaduj aplikację z pliku", "MenuBarFileOpenFromFile": "_Załaduj aplikację z pliku",
"MenuBarFileOpenFromFileError": "No applications found in selected file.",
"MenuBarFileOpenUnpacked": "Załaduj _rozpakowaną grę", "MenuBarFileOpenUnpacked": "Załaduj _rozpakowaną grę",
"MenuBarFileLoadDlcFromFolder": "Load DLC From Folder",
"MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder",
"MenuBarFileOpenEmuFolder": "Otwórz folder Ryujinx", "MenuBarFileOpenEmuFolder": "Otwórz folder Ryujinx",
"MenuBarFileOpenLogsFolder": "Otwórz folder plików dziennika zdarzeń", "MenuBarFileOpenLogsFolder": "Otwórz folder plików dziennika zdarzeń",
"MenuBarFileExit": "_Wyjdź", "MenuBarFileExit": "_Wyjdź",
@ -103,6 +106,8 @@
"SettingsTabGeneralHideCursorOnIdle": "Gdy bezczynny", "SettingsTabGeneralHideCursorOnIdle": "Gdy bezczynny",
"SettingsTabGeneralHideCursorAlways": "Zawsze", "SettingsTabGeneralHideCursorAlways": "Zawsze",
"SettingsTabGeneralGameDirectories": "Katalogi gier", "SettingsTabGeneralGameDirectories": "Katalogi gier",
"SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories",
"SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically",
"SettingsTabGeneralAdd": "Dodaj", "SettingsTabGeneralAdd": "Dodaj",
"SettingsTabGeneralRemove": "Usuń", "SettingsTabGeneralRemove": "Usuń",
"SettingsTabSystem": "System", "SettingsTabSystem": "System",
@ -411,6 +416,7 @@
"GameListContextMenuToggleFavorite": "Przełącz na ulubione", "GameListContextMenuToggleFavorite": "Przełącz na ulubione",
"GameListContextMenuToggleFavoriteToolTip": "Przełącz status Ulubionej Gry", "GameListContextMenuToggleFavoriteToolTip": "Przełącz status Ulubionej Gry",
"SettingsTabGeneralTheme": "Motyw:", "SettingsTabGeneralTheme": "Motyw:",
"SettingsTabGeneralThemeAuto": "Auto",
"SettingsTabGeneralThemeDark": "Ciemny", "SettingsTabGeneralThemeDark": "Ciemny",
"SettingsTabGeneralThemeLight": "Jasny", "SettingsTabGeneralThemeLight": "Jasny",
"ControllerSettingsConfigureGeneral": "Konfiguruj", "ControllerSettingsConfigureGeneral": "Konfiguruj",
@ -561,6 +567,9 @@
"AddGameDirBoxTooltip": "Wprowadź katalog gier aby dodać go do listy", "AddGameDirBoxTooltip": "Wprowadź katalog gier aby dodać go do listy",
"AddGameDirTooltip": "Dodaj katalog gier do listy", "AddGameDirTooltip": "Dodaj katalog gier do listy",
"RemoveGameDirTooltip": "Usuń wybrany katalog gier", "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", "CustomThemeCheckTooltip": "Użyj niestandardowego motywu Avalonia dla GUI, aby zmienić wygląd menu emulatora",
"CustomThemePathTooltip": "Ścieżka do niestandardowego motywu GUI", "CustomThemePathTooltip": "Ścieżka do niestandardowego motywu GUI",
"CustomThemeBrowseTooltip": "Wyszukaj niestandardowy motyw 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.", "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", "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", "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", "OpenRyujinxFolderTooltip": "Otwórz folder systemu plików Ryujinx",
"OpenRyujinxLogsTooltip": "Otwiera folder, w którym zapisywane są logi", "OpenRyujinxLogsTooltip": "Otwiera folder, w którym zapisywane są logi",
"ExitTooltip": "Wyjdź z Ryujinx", "ExitTooltip": "Wyjdź z Ryujinx",
@ -657,6 +668,8 @@
"OpenSetupGuideMessage": "Otwórz Podręcznik Konfiguracji", "OpenSetupGuideMessage": "Otwórz Podręcznik Konfiguracji",
"NoUpdate": "Brak Aktualizacji", "NoUpdate": "Brak Aktualizacji",
"TitleUpdateVersionLabel": "Wersja {0} - {1}", "TitleUpdateVersionLabel": "Wersja {0} - {1}",
"TitleBundledUpdateVersionLabel": "Bundled: Version {0}",
"TitleBundledDlcLabel": "Bundled:",
"RyujinxInfo": "Ryujinx - Info", "RyujinxInfo": "Ryujinx - Info",
"RyujinxConfirm": "Ryujinx - Potwierdzenie", "RyujinxConfirm": "Ryujinx - Potwierdzenie",
"FileDialogAllTypes": "Wszystkie typy", "FileDialogAllTypes": "Wszystkie typy",
@ -714,9 +727,17 @@
"DlcWindowTitle": "Menedżer Zawartości do Pobrania", "DlcWindowTitle": "Menedżer Zawartości do Pobrania",
"ModWindowTitle": "Zarządzaj modami dla {0} ({1})", "ModWindowTitle": "Zarządzaj modami dla {0} ({1})",
"UpdateWindowTitle": "Menedżer Aktualizacji Tytułu", "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}]", "CheatWindowHeading": "Kody Dostępne dla {0} [{1}]",
"BuildId": "Identyfikator wersji:", "BuildId": "Identyfikator wersji:",
"DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.",
"DlcWindowHeading": "{0} Zawartości do Pobrania dostępna dla {1} ({2})", "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)", "ModWindowHeading": "{0} Mod(y/ów)",
"UserProfilesEditProfile": "Edytuj Zaznaczone", "UserProfilesEditProfile": "Edytuj Zaznaczone",
"Cancel": "Anuluj", "Cancel": "Anuluj",
@ -767,6 +788,7 @@
"GraphicsScalingFilterBilinear": "Dwuliniowe", "GraphicsScalingFilterBilinear": "Dwuliniowe",
"GraphicsScalingFilterNearest": "Najbliższe", "GraphicsScalingFilterNearest": "Najbliższe",
"GraphicsScalingFilterFsr": "FSR", "GraphicsScalingFilterFsr": "FSR",
"GraphicsScalingFilterArea": "Area",
"GraphicsScalingFilterLevelLabel": "Poziom", "GraphicsScalingFilterLevelLabel": "Poziom",
"GraphicsScalingFilterLevelTooltip": "Ustaw poziom ostrzeżenia FSR 1.0. Wyższy jest ostrzejszy.", "GraphicsScalingFilterLevelTooltip": "Ustaw poziom ostrzeżenia FSR 1.0. Wyższy jest ostrzejszy.",
"SmaaLow": "SMAA Niskie", "SmaaLow": "SMAA Niskie",

View File

@ -10,7 +10,10 @@
"SettingsTabSystemUseHypervisor": "Использовать Hypervisor", "SettingsTabSystemUseHypervisor": "Использовать Hypervisor",
"MenuBarFile": "_Файл", "MenuBarFile": "_Файл",
"MenuBarFileOpenFromFile": "_Добавить приложение из файла", "MenuBarFileOpenFromFile": "_Добавить приложение из файла",
"MenuBarFileOpenFromFileError": "No applications found in selected file.",
"MenuBarFileOpenUnpacked": "Добавить _распакованную игру", "MenuBarFileOpenUnpacked": "Добавить _распакованную игру",
"MenuBarFileLoadDlcFromFolder": "Load DLC From Folder",
"MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder",
"MenuBarFileOpenEmuFolder": "Открыть папку Ryujinx", "MenuBarFileOpenEmuFolder": "Открыть папку Ryujinx",
"MenuBarFileOpenLogsFolder": "Открыть папку с логами", "MenuBarFileOpenLogsFolder": "Открыть папку с логами",
"MenuBarFileExit": "_Выход", "MenuBarFileExit": "_Выход",
@ -103,6 +106,8 @@
"SettingsTabGeneralHideCursorOnIdle": "В простое", "SettingsTabGeneralHideCursorOnIdle": "В простое",
"SettingsTabGeneralHideCursorAlways": "Всегда", "SettingsTabGeneralHideCursorAlways": "Всегда",
"SettingsTabGeneralGameDirectories": "Папки с играми", "SettingsTabGeneralGameDirectories": "Папки с играми",
"SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories",
"SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically",
"SettingsTabGeneralAdd": "Добавить", "SettingsTabGeneralAdd": "Добавить",
"SettingsTabGeneralRemove": "Удалить", "SettingsTabGeneralRemove": "Удалить",
"SettingsTabSystem": "Система", "SettingsTabSystem": "Система",
@ -411,6 +416,7 @@
"GameListContextMenuToggleFavorite": "Добавить в избранное", "GameListContextMenuToggleFavorite": "Добавить в избранное",
"GameListContextMenuToggleFavoriteToolTip": "Добавляет игру в избранное и помечает звездочкой", "GameListContextMenuToggleFavoriteToolTip": "Добавляет игру в избранное и помечает звездочкой",
"SettingsTabGeneralTheme": "Тема:", "SettingsTabGeneralTheme": "Тема:",
"SettingsTabGeneralThemeAuto": "Auto",
"SettingsTabGeneralThemeDark": "Темная", "SettingsTabGeneralThemeDark": "Темная",
"SettingsTabGeneralThemeLight": "Светлая", "SettingsTabGeneralThemeLight": "Светлая",
"ControllerSettingsConfigureGeneral": "Настройка", "ControllerSettingsConfigureGeneral": "Настройка",
@ -561,6 +567,9 @@
"AddGameDirBoxTooltip": "Введите путь к папке с играми для добавления ее в список выше", "AddGameDirBoxTooltip": "Введите путь к папке с играми для добавления ее в список выше",
"AddGameDirTooltip": "Добавить папку с играми в список", "AddGameDirTooltip": "Добавить папку с играми в список",
"RemoveGameDirTooltip": "Удалить выбранную папку игры", "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": "Включить или отключить пользовательские темы", "CustomThemeCheckTooltip": "Включить или отключить пользовательские темы",
"CustomThemePathTooltip": "Путь к пользовательской теме для интерфейса", "CustomThemePathTooltip": "Путь к пользовательской теме для интерфейса",
"CustomThemeBrowseTooltip": "Просмотр пользовательской темы интерфейса", "CustomThemeBrowseTooltip": "Просмотр пользовательской темы интерфейса",
@ -606,6 +615,8 @@
"DebugLogTooltip": "Выводит журнал сообщений отладки в консоли.\n\nИспользуйте только в случае просьбы разработчика, так как включение этой функции затруднит чтение журналов и ухудшит работу эмулятора.", "DebugLogTooltip": "Выводит журнал сообщений отладки в консоли.\n\nИспользуйте только в случае просьбы разработчика, так как включение этой функции затруднит чтение журналов и ухудшит работу эмулятора.",
"LoadApplicationFileTooltip": "Открывает файловый менеджер для выбора файла, совместимого с Nintendo Switch.", "LoadApplicationFileTooltip": "Открывает файловый менеджер для выбора файла, совместимого с Nintendo Switch.",
"LoadApplicationFolderTooltip": "Открывает файловый менеджер для выбора распакованного приложения, совместимого с 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. ", "OpenRyujinxFolderTooltip": "Открывает папку с файлами Ryujinx. ",
"OpenRyujinxLogsTooltip": "Открывает папку в которую записываются логи", "OpenRyujinxLogsTooltip": "Открывает папку в которую записываются логи",
"ExitTooltip": "Выйти из Ryujinx", "ExitTooltip": "Выйти из Ryujinx",
@ -657,6 +668,8 @@
"OpenSetupGuideMessage": "Открыть руководство по установке", "OpenSetupGuideMessage": "Открыть руководство по установке",
"NoUpdate": "Без обновлений", "NoUpdate": "Без обновлений",
"TitleUpdateVersionLabel": "Version {0} - {1}", "TitleUpdateVersionLabel": "Version {0} - {1}",
"TitleBundledUpdateVersionLabel": "Bundled: Version {0}",
"TitleBundledDlcLabel": "Bundled:",
"RyujinxInfo": "Ryujinx - Информация", "RyujinxInfo": "Ryujinx - Информация",
"RyujinxConfirm": "Ryujinx - Подтверждение", "RyujinxConfirm": "Ryujinx - Подтверждение",
"FileDialogAllTypes": "Все типы", "FileDialogAllTypes": "Все типы",
@ -714,9 +727,17 @@
"DlcWindowTitle": "Управление DLC для {0} ({1})", "DlcWindowTitle": "Управление DLC для {0} ({1})",
"ModWindowTitle": "Управление модами для {0} ({1})", "ModWindowTitle": "Управление модами для {0} ({1})",
"UpdateWindowTitle": "Менеджер обновлений игр", "UpdateWindowTitle": "Менеджер обновлений игр",
"UpdateWindowUpdateAddedMessage": "{0} new update(s) added",
"UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.",
"CheatWindowHeading": "Доступные читы для {0} [{1}]", "CheatWindowHeading": "Доступные читы для {0} [{1}]",
"BuildId": "ID версии:", "BuildId": "ID версии:",
"DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.",
"DlcWindowHeading": "{0} DLC", "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} ", "ModWindowHeading": "Моды для {0} ",
"UserProfilesEditProfile": "Изменить выбранные", "UserProfilesEditProfile": "Изменить выбранные",
"Cancel": "Отмена", "Cancel": "Отмена",
@ -767,6 +788,7 @@
"GraphicsScalingFilterBilinear": "Билинейная", "GraphicsScalingFilterBilinear": "Билинейная",
"GraphicsScalingFilterNearest": "Ступенчатая", "GraphicsScalingFilterNearest": "Ступенчатая",
"GraphicsScalingFilterFsr": "FSR", "GraphicsScalingFilterFsr": "FSR",
"GraphicsScalingFilterArea": "Area",
"GraphicsScalingFilterLevelLabel": "Уровень", "GraphicsScalingFilterLevelLabel": "Уровень",
"GraphicsScalingFilterLevelTooltip": "Выбор режима работы FSR 1.0. Выше - четче.", "GraphicsScalingFilterLevelTooltip": "Выбор режима работы FSR 1.0. Выше - четче.",
"SmaaLow": "SMAA Низкое", "SmaaLow": "SMAA Низкое",

View File

@ -107,6 +107,7 @@
"SettingsTabGeneralHideCursorAlways": "ตลอดเวลา", "SettingsTabGeneralHideCursorAlways": "ตลอดเวลา",
"SettingsTabGeneralGameDirectories": "ไดเรกทอรี่ของเกม", "SettingsTabGeneralGameDirectories": "ไดเรกทอรี่ของเกม",
"SettingsTabGeneralAutoloadDirectories": "โหลดไดเรกทอรี DLC/ไฟล์อัปเดต อัตโนมัติ", "SettingsTabGeneralAutoloadDirectories": "โหลดไดเรกทอรี DLC/ไฟล์อัปเดต อัตโนมัติ",
"SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically",
"SettingsTabGeneralAdd": "เพิ่ม", "SettingsTabGeneralAdd": "เพิ่ม",
"SettingsTabGeneralRemove": "เอาออก", "SettingsTabGeneralRemove": "เอาออก",
"SettingsTabSystem": "ระบบ", "SettingsTabSystem": "ระบบ",
@ -734,8 +735,9 @@
"DlcWindowHeading": "{0} DLC ที่สามารถดาวน์โหลดได้", "DlcWindowHeading": "{0} DLC ที่สามารถดาวน์โหลดได้",
"DlcWindowDlcAddedMessage": "{0} DLC ใหม่ที่เพิ่มเข้ามา", "DlcWindowDlcAddedMessage": "{0} DLC ใหม่ที่เพิ่มเข้ามา",
"AutoloadDlcAddedMessage": "{0} ใหม่ที่เพิ่มเข้ามา", "AutoloadDlcAddedMessage": "{0} ใหม่ที่เพิ่มเข้ามา",
"AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed",
"AutoloadUpdateAddedMessage": "{0} อัพเดตใหม่ที่เพิ่มเข้ามา", "AutoloadUpdateAddedMessage": "{0} อัพเดตใหม่ที่เพิ่มเข้ามา",
"AutoloadDlcAndUpdateAddedMessage": "{0} DLC ใหม่ที่เพิ่มเข้ามาและ {1} อัพเดตใหม่ที่เพิ่มเข้ามา", "AutoloadUpdateRemovedMessage": "{0} missing update(s) removed",
"ModWindowHeading": "{0} ม็อด", "ModWindowHeading": "{0} ม็อด",
"UserProfilesEditProfile": "แก้ไขที่เลือกแล้ว", "UserProfilesEditProfile": "แก้ไขที่เลือกแล้ว",
"Cancel": "ยกเลิก", "Cancel": "ยกเลิก",

View File

@ -10,7 +10,10 @@
"SettingsTabSystemUseHypervisor": "Hypervisor Kullan", "SettingsTabSystemUseHypervisor": "Hypervisor Kullan",
"MenuBarFile": "_Dosya", "MenuBarFile": "_Dosya",
"MenuBarFileOpenFromFile": "_Dosyadan Uygulama Aç", "MenuBarFileOpenFromFile": "_Dosyadan Uygulama Aç",
"MenuBarFileOpenFromFileError": "No applications found in selected file.",
"MenuBarFileOpenUnpacked": "_Sıkıştırılmamış Oyun Aç", "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ç", "MenuBarFileOpenEmuFolder": "Ryujinx Klasörünü aç",
"MenuBarFileOpenLogsFolder": "Logs Klasörünü aç", "MenuBarFileOpenLogsFolder": "Logs Klasörünü aç",
"MenuBarFileExit": "_Çıkış", "MenuBarFileExit": "_Çıkış",
@ -103,6 +106,8 @@
"SettingsTabGeneralHideCursorOnIdle": "Hareketsiz Durumda", "SettingsTabGeneralHideCursorOnIdle": "Hareketsiz Durumda",
"SettingsTabGeneralHideCursorAlways": "Her Zaman", "SettingsTabGeneralHideCursorAlways": "Her Zaman",
"SettingsTabGeneralGameDirectories": "Oyun Dizinleri", "SettingsTabGeneralGameDirectories": "Oyun Dizinleri",
"SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories",
"SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically",
"SettingsTabGeneralAdd": "Ekle", "SettingsTabGeneralAdd": "Ekle",
"SettingsTabGeneralRemove": "Kaldır", "SettingsTabGeneralRemove": "Kaldır",
"SettingsTabSystem": "Sistem", "SettingsTabSystem": "Sistem",
@ -411,6 +416,7 @@
"GameListContextMenuToggleFavorite": "Favori Ayarla", "GameListContextMenuToggleFavorite": "Favori Ayarla",
"GameListContextMenuToggleFavoriteToolTip": "Oyunu Favorilere Ekle/Çıkar", "GameListContextMenuToggleFavoriteToolTip": "Oyunu Favorilere Ekle/Çıkar",
"SettingsTabGeneralTheme": "Tema:", "SettingsTabGeneralTheme": "Tema:",
"SettingsTabGeneralThemeAuto": "Auto",
"SettingsTabGeneralThemeDark": "Karanlık", "SettingsTabGeneralThemeDark": "Karanlık",
"SettingsTabGeneralThemeLight": "Aydınlık", "SettingsTabGeneralThemeLight": "Aydınlık",
"ControllerSettingsConfigureGeneral": "Ayarla", "ControllerSettingsConfigureGeneral": "Ayarla",
@ -561,6 +567,9 @@
"AddGameDirBoxTooltip": "Listeye eklemek için oyun dizini seçin", "AddGameDirBoxTooltip": "Listeye eklemek için oyun dizini seçin",
"AddGameDirTooltip": "Listeye oyun dizini ekle", "AddGameDirTooltip": "Listeye oyun dizini ekle",
"RemoveGameDirTooltip": "Seçili oyun dizinini kaldır", "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", "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", "CustomThemePathTooltip": "Özel arayüz temasının yolu",
"CustomThemeBrowseTooltip": "Özel arayüz teması için göz at", "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.", "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", "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", "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", "OpenRyujinxFolderTooltip": "Ryujinx dosya sistem klasörünü açar",
"OpenRyujinxLogsTooltip": "Log dosyalarının bulunduğu klasörü açar", "OpenRyujinxLogsTooltip": "Log dosyalarının bulunduğu klasörü açar",
"ExitTooltip": "Ryujinx'ten çıkış yapmayı sağlar", "ExitTooltip": "Ryujinx'ten çıkış yapmayı sağlar",
@ -657,6 +668,8 @@
"OpenSetupGuideMessage": "Kurulum Kılavuzunu Aç", "OpenSetupGuideMessage": "Kurulum Kılavuzunu Aç",
"NoUpdate": "Güncelleme Yok", "NoUpdate": "Güncelleme Yok",
"TitleUpdateVersionLabel": "Sürüm {0} - {1}", "TitleUpdateVersionLabel": "Sürüm {0} - {1}",
"TitleBundledUpdateVersionLabel": "Bundled: Version {0}",
"TitleBundledDlcLabel": "Bundled:",
"RyujinxInfo": "Ryujinx - Bilgi", "RyujinxInfo": "Ryujinx - Bilgi",
"RyujinxConfirm": "Ryujinx - Doğrulama", "RyujinxConfirm": "Ryujinx - Doğrulama",
"FileDialogAllTypes": "Tüm türler", "FileDialogAllTypes": "Tüm türler",
@ -714,9 +727,17 @@
"DlcWindowTitle": "Oyun DLC'lerini Yönet", "DlcWindowTitle": "Oyun DLC'lerini Yönet",
"ModWindowTitle": "Manage Mods for {0} ({1})", "ModWindowTitle": "Manage Mods for {0} ({1})",
"UpdateWindowTitle": "Oyun Güncellemelerini Yönet", "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}]", "CheatWindowHeading": "{0} için Hile mevcut [{1}]",
"BuildId": "BuildId:", "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)", "ModWindowHeading": "{0} Mod(lar)",
"UserProfilesEditProfile": "Seçiliyi Düzenle", "UserProfilesEditProfile": "Seçiliyi Düzenle",
"Cancel": "İptal", "Cancel": "İptal",
@ -767,6 +788,7 @@
"GraphicsScalingFilterBilinear": "Bilinear", "GraphicsScalingFilterBilinear": "Bilinear",
"GraphicsScalingFilterNearest": "Nearest", "GraphicsScalingFilterNearest": "Nearest",
"GraphicsScalingFilterFsr": "FSR", "GraphicsScalingFilterFsr": "FSR",
"GraphicsScalingFilterArea": "Area",
"GraphicsScalingFilterLevelLabel": "Seviye", "GraphicsScalingFilterLevelLabel": "Seviye",
"GraphicsScalingFilterLevelTooltip": "Set FSR 1.0 sharpening level. Higher is sharper.", "GraphicsScalingFilterLevelTooltip": "Set FSR 1.0 sharpening level. Higher is sharper.",
"SmaaLow": "Düşük SMAA", "SmaaLow": "Düşük SMAA",

View File

@ -10,7 +10,10 @@
"SettingsTabSystemUseHypervisor": "Використовувати гіпервізор", "SettingsTabSystemUseHypervisor": "Використовувати гіпервізор",
"MenuBarFile": "_Файл", "MenuBarFile": "_Файл",
"MenuBarFileOpenFromFile": "_Завантажити програму з файлу", "MenuBarFileOpenFromFile": "_Завантажити програму з файлу",
"MenuBarFileOpenFromFileError": "No applications found in selected file.",
"MenuBarFileOpenUnpacked": "Завантажити _розпаковану гру", "MenuBarFileOpenUnpacked": "Завантажити _розпаковану гру",
"MenuBarFileLoadDlcFromFolder": "Load DLC From Folder",
"MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder",
"MenuBarFileOpenEmuFolder": "Відкрити теку Ryujinx", "MenuBarFileOpenEmuFolder": "Відкрити теку Ryujinx",
"MenuBarFileOpenLogsFolder": "Відкрити теку журналів змін", "MenuBarFileOpenLogsFolder": "Відкрити теку журналів змін",
"MenuBarFileExit": "_Вихід", "MenuBarFileExit": "_Вихід",
@ -103,6 +106,8 @@
"SettingsTabGeneralHideCursorOnIdle": "Сховати у режимі очікування", "SettingsTabGeneralHideCursorOnIdle": "Сховати у режимі очікування",
"SettingsTabGeneralHideCursorAlways": "Завжди", "SettingsTabGeneralHideCursorAlways": "Завжди",
"SettingsTabGeneralGameDirectories": "Тека ігор", "SettingsTabGeneralGameDirectories": "Тека ігор",
"SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories",
"SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically",
"SettingsTabGeneralAdd": "Додати", "SettingsTabGeneralAdd": "Додати",
"SettingsTabGeneralRemove": "Видалити", "SettingsTabGeneralRemove": "Видалити",
"SettingsTabSystem": "Система", "SettingsTabSystem": "Система",
@ -411,6 +416,7 @@
"GameListContextMenuToggleFavorite": "Перемкнути вибране", "GameListContextMenuToggleFavorite": "Перемкнути вибране",
"GameListContextMenuToggleFavoriteToolTip": "Перемкнути улюблений статус гри", "GameListContextMenuToggleFavoriteToolTip": "Перемкнути улюблений статус гри",
"SettingsTabGeneralTheme": "Тема:", "SettingsTabGeneralTheme": "Тема:",
"SettingsTabGeneralThemeAuto": "Auto",
"SettingsTabGeneralThemeDark": "Темна", "SettingsTabGeneralThemeDark": "Темна",
"SettingsTabGeneralThemeLight": "Світла", "SettingsTabGeneralThemeLight": "Світла",
"ControllerSettingsConfigureGeneral": "Налаштування", "ControllerSettingsConfigureGeneral": "Налаштування",
@ -561,6 +567,9 @@
"AddGameDirBoxTooltip": "Введіть каталог ігор, щоб додати до списку", "AddGameDirBoxTooltip": "Введіть каталог ігор, щоб додати до списку",
"AddGameDirTooltip": "Додати каталог гри до списку", "AddGameDirTooltip": "Додати каталог гри до списку",
"RemoveGameDirTooltip": "Видалити вибраний каталог гри", "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 для графічного інтерфейсу, щоб змінити вигляд меню емулятора", "CustomThemeCheckTooltip": "Використовуйте користувацьку тему Avalonia для графічного інтерфейсу, щоб змінити вигляд меню емулятора",
"CustomThemePathTooltip": "Шлях до користувацької теми графічного інтерфейсу", "CustomThemePathTooltip": "Шлях до користувацької теми графічного інтерфейсу",
"CustomThemeBrowseTooltip": "Огляд користувацької теми графічного інтерфейсу", "CustomThemeBrowseTooltip": "Огляд користувацької теми графічного інтерфейсу",
@ -606,6 +615,8 @@
"DebugLogTooltip": "Друкує повідомлення журналу налагодження на консолі.\n\nВикористовуйте це лише за спеціальною вказівкою співробітника, оскільки це ускладнить читання журналів і погіршить роботу емулятора.", "DebugLogTooltip": "Друкує повідомлення журналу налагодження на консолі.\n\nВикористовуйте це лише за спеціальною вказівкою співробітника, оскільки це ускладнить читання журналів і погіршить роботу емулятора.",
"LoadApplicationFileTooltip": "Відкриває файловий провідник, щоб вибрати для завантаження сумісний файл Switch", "LoadApplicationFileTooltip": "Відкриває файловий провідник, щоб вибрати для завантаження сумісний файл Switch",
"LoadApplicationFolderTooltip": "Відкриває файловий провідник, щоб вибрати сумісну з комутатором розпаковану програму для завантаження", "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", "OpenRyujinxFolderTooltip": "Відкриває папку файлової системи Ryujinx",
"OpenRyujinxLogsTooltip": "Відкриває папку, куди записуються журнали", "OpenRyujinxLogsTooltip": "Відкриває папку, куди записуються журнали",
"ExitTooltip": "Виходить з Ryujinx", "ExitTooltip": "Виходить з Ryujinx",
@ -657,6 +668,8 @@
"OpenSetupGuideMessage": "Відкрити посібник із налаштування", "OpenSetupGuideMessage": "Відкрити посібник із налаштування",
"NoUpdate": "Немає оновлень", "NoUpdate": "Немає оновлень",
"TitleUpdateVersionLabel": "Версія {0} - {1}", "TitleUpdateVersionLabel": "Версія {0} - {1}",
"TitleBundledUpdateVersionLabel": "Bundled: Version {0}",
"TitleBundledDlcLabel": "Bundled:",
"RyujinxInfo": "Ryujin x - Інформація", "RyujinxInfo": "Ryujin x - Інформація",
"RyujinxConfirm": "Ryujinx - Підтвердження", "RyujinxConfirm": "Ryujinx - Підтвердження",
"FileDialogAllTypes": "Всі типи", "FileDialogAllTypes": "Всі типи",
@ -714,9 +727,17 @@
"DlcWindowTitle": "Менеджер вмісту для завантаження", "DlcWindowTitle": "Менеджер вмісту для завантаження",
"ModWindowTitle": "Керувати модами для {0} ({1})", "ModWindowTitle": "Керувати модами для {0} ({1})",
"UpdateWindowTitle": "Менеджер оновлення назв", "UpdateWindowTitle": "Менеджер оновлення назв",
"UpdateWindowUpdateAddedMessage": "{0} new update(s) added",
"UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.",
"CheatWindowHeading": "Коди доступні для {0} [{1}]", "CheatWindowHeading": "Коди доступні для {0} [{1}]",
"BuildId": "ID збірки:", "BuildId": "ID збірки:",
"DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.",
"DlcWindowHeading": "Вміст для завантаження, доступний для {1} ({2}): {0}", "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} мод(ів)", "ModWindowHeading": "{0} мод(ів)",
"UserProfilesEditProfile": "Редагувати вибране", "UserProfilesEditProfile": "Редагувати вибране",
"Cancel": "Скасувати", "Cancel": "Скасувати",
@ -767,6 +788,7 @@
"GraphicsScalingFilterBilinear": "Білінійний", "GraphicsScalingFilterBilinear": "Білінійний",
"GraphicsScalingFilterNearest": "Найближчий", "GraphicsScalingFilterNearest": "Найближчий",
"GraphicsScalingFilterFsr": "FSR", "GraphicsScalingFilterFsr": "FSR",
"GraphicsScalingFilterArea": "Area",
"GraphicsScalingFilterLevelLabel": "Рівень", "GraphicsScalingFilterLevelLabel": "Рівень",
"GraphicsScalingFilterLevelTooltip": "Встановити рівень різкості в FSR 1.0. Чим вище - тим різкіше.", "GraphicsScalingFilterLevelTooltip": "Встановити рівень різкості в FSR 1.0. Чим вище - тим різкіше.",
"SmaaLow": "SMAA Низький", "SmaaLow": "SMAA Низький",

View File

@ -107,6 +107,7 @@
"SettingsTabGeneralHideCursorAlways": "始终隐藏", "SettingsTabGeneralHideCursorAlways": "始终隐藏",
"SettingsTabGeneralGameDirectories": "游戏目录", "SettingsTabGeneralGameDirectories": "游戏目录",
"SettingsTabGeneralAutoloadDirectories": "自动加载DLC/游戏更新目录", "SettingsTabGeneralAutoloadDirectories": "自动加载DLC/游戏更新目录",
"SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically",
"SettingsTabGeneralAdd": "添加", "SettingsTabGeneralAdd": "添加",
"SettingsTabGeneralRemove": "删除", "SettingsTabGeneralRemove": "删除",
"SettingsTabSystem": "系统", "SettingsTabSystem": "系统",
@ -734,8 +735,9 @@
"DlcWindowHeading": "{0} 个 DLC", "DlcWindowHeading": "{0} 个 DLC",
"DlcWindowDlcAddedMessage": "{0} 个DLC被添加", "DlcWindowDlcAddedMessage": "{0} 个DLC被添加",
"AutoloadDlcAddedMessage": "{0} 个DLC被添加", "AutoloadDlcAddedMessage": "{0} 个DLC被添加",
"AutoloadDlcRemovedMessage": "{0} missing downloadable content(s) removed",
"AutoloadUpdateAddedMessage": "{0} 个游戏更新被添加", "AutoloadUpdateAddedMessage": "{0} 个游戏更新被添加",
"AutoloadDlcAndUpdateAddedMessage": "{0} 个DLC和{1} 个游戏更新被添加", "AutoloadUpdateRemovedMessage": "{0} missing update(s) removed",
"ModWindowHeading": "{0} Mod(s)", "ModWindowHeading": "{0} Mod(s)",
"UserProfilesEditProfile": "编辑所选", "UserProfilesEditProfile": "编辑所选",
"Cancel": "取消", "Cancel": "取消",

View File

@ -10,7 +10,10 @@
"SettingsTabSystemUseHypervisor": "使用 Hypervisor", "SettingsTabSystemUseHypervisor": "使用 Hypervisor",
"MenuBarFile": "檔案(_F)", "MenuBarFile": "檔案(_F)",
"MenuBarFileOpenFromFile": "從檔案載入應用程式(_L)", "MenuBarFileOpenFromFile": "從檔案載入應用程式(_L)",
"MenuBarFileOpenFromFileError": "No applications found in selected file.",
"MenuBarFileOpenUnpacked": "載入未封裝的遊戲(_U)", "MenuBarFileOpenUnpacked": "載入未封裝的遊戲(_U)",
"MenuBarFileLoadDlcFromFolder": "Load DLC From Folder",
"MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder",
"MenuBarFileOpenEmuFolder": "開啟 Ryujinx 資料夾", "MenuBarFileOpenEmuFolder": "開啟 Ryujinx 資料夾",
"MenuBarFileOpenLogsFolder": "開啟日誌資料夾", "MenuBarFileOpenLogsFolder": "開啟日誌資料夾",
"MenuBarFileExit": "結束(_E)", "MenuBarFileExit": "結束(_E)",
@ -103,6 +106,8 @@
"SettingsTabGeneralHideCursorOnIdle": "閒置時", "SettingsTabGeneralHideCursorOnIdle": "閒置時",
"SettingsTabGeneralHideCursorAlways": "總是", "SettingsTabGeneralHideCursorAlways": "總是",
"SettingsTabGeneralGameDirectories": "遊戲資料夾", "SettingsTabGeneralGameDirectories": "遊戲資料夾",
"SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories",
"SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically",
"SettingsTabGeneralAdd": "新增", "SettingsTabGeneralAdd": "新增",
"SettingsTabGeneralRemove": "刪除", "SettingsTabGeneralRemove": "刪除",
"SettingsTabSystem": "系統", "SettingsTabSystem": "系統",
@ -411,6 +416,7 @@
"GameListContextMenuToggleFavorite": "加入/移除為我的最愛", "GameListContextMenuToggleFavorite": "加入/移除為我的最愛",
"GameListContextMenuToggleFavoriteToolTip": "切換遊戲的我的最愛狀態", "GameListContextMenuToggleFavoriteToolTip": "切換遊戲的我的最愛狀態",
"SettingsTabGeneralTheme": "佈景主題:", "SettingsTabGeneralTheme": "佈景主題:",
"SettingsTabGeneralThemeAuto": "Auto",
"SettingsTabGeneralThemeDark": "深色", "SettingsTabGeneralThemeDark": "深色",
"SettingsTabGeneralThemeLight": "淺色", "SettingsTabGeneralThemeLight": "淺色",
"ControllerSettingsConfigureGeneral": "配置", "ControllerSettingsConfigureGeneral": "配置",
@ -561,6 +567,9 @@
"AddGameDirBoxTooltip": "輸入要新增到清單中的遊戲資料夾", "AddGameDirBoxTooltip": "輸入要新增到清單中的遊戲資料夾",
"AddGameDirTooltip": "新增遊戲資料夾到清單中", "AddGameDirTooltip": "新增遊戲資料夾到清單中",
"RemoveGameDirTooltip": "移除選取的遊戲資料夾", "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 佈景主題,變更模擬器功能表的外觀", "CustomThemeCheckTooltip": "為圖形使用者介面使用自訂 Avalonia 佈景主題,變更模擬器功能表的外觀",
"CustomThemePathTooltip": "自訂 GUI 佈景主題的路徑", "CustomThemePathTooltip": "自訂 GUI 佈景主題的路徑",
"CustomThemeBrowseTooltip": "瀏覽自訂 GUI 佈景主題", "CustomThemeBrowseTooltip": "瀏覽自訂 GUI 佈景主題",
@ -606,6 +615,8 @@
"DebugLogTooltip": "在控制台中輸出偵錯日誌訊息。\n\n只有在人員特別指示的情況下才能使用因為這會導致日誌難以閱讀並降低模擬器效能。", "DebugLogTooltip": "在控制台中輸出偵錯日誌訊息。\n\n只有在人員特別指示的情況下才能使用因為這會導致日誌難以閱讀並降低模擬器效能。",
"LoadApplicationFileTooltip": "開啟檔案總管,選擇與 Switch 相容的檔案來載入", "LoadApplicationFileTooltip": "開啟檔案總管,選擇與 Switch 相容的檔案來載入",
"LoadApplicationFolderTooltip": "開啟檔案總管,選擇與 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 檔案系統資料夾", "OpenRyujinxFolderTooltip": "開啟 Ryujinx 檔案系統資料夾",
"OpenRyujinxLogsTooltip": "開啟日誌被寫入的資料夾", "OpenRyujinxLogsTooltip": "開啟日誌被寫入的資料夾",
"ExitTooltip": "結束 Ryujinx", "ExitTooltip": "結束 Ryujinx",
@ -657,6 +668,8 @@
"OpenSetupGuideMessage": "開啟設定指南", "OpenSetupGuideMessage": "開啟設定指南",
"NoUpdate": "沒有更新", "NoUpdate": "沒有更新",
"TitleUpdateVersionLabel": "版本 {0}", "TitleUpdateVersionLabel": "版本 {0}",
"TitleBundledUpdateVersionLabel": "Bundled: Version {0}",
"TitleBundledDlcLabel": "Bundled:",
"RyujinxInfo": "Ryujinx - 資訊", "RyujinxInfo": "Ryujinx - 資訊",
"RyujinxConfirm": "Ryujinx - 確認", "RyujinxConfirm": "Ryujinx - 確認",
"FileDialogAllTypes": "全部類型", "FileDialogAllTypes": "全部類型",
@ -714,9 +727,17 @@
"DlcWindowTitle": "管理 {0} 的可下載內容 ({1})", "DlcWindowTitle": "管理 {0} 的可下載內容 ({1})",
"ModWindowTitle": "管理 {0} 的模組 ({1})", "ModWindowTitle": "管理 {0} 的模組 ({1})",
"UpdateWindowTitle": "遊戲更新管理員", "UpdateWindowTitle": "遊戲更新管理員",
"UpdateWindowUpdateAddedMessage": "{0} new update(s) added",
"UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.",
"CheatWindowHeading": "可用於 {0} [{1}] 的密技", "CheatWindowHeading": "可用於 {0} [{1}] 的密技",
"BuildId": "組建識別碼:", "BuildId": "組建識別碼:",
"DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.",
"DlcWindowHeading": "{0} 個可下載內容", "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} 模組", "ModWindowHeading": "{0} 模組",
"UserProfilesEditProfile": "編輯所選", "UserProfilesEditProfile": "編輯所選",
"Cancel": "取消", "Cancel": "取消",
@ -767,6 +788,7 @@
"GraphicsScalingFilterBilinear": "雙線性 (Bilinear)", "GraphicsScalingFilterBilinear": "雙線性 (Bilinear)",
"GraphicsScalingFilterNearest": "近鄰性 (Nearest)", "GraphicsScalingFilterNearest": "近鄰性 (Nearest)",
"GraphicsScalingFilterFsr": "FSR", "GraphicsScalingFilterFsr": "FSR",
"GraphicsScalingFilterArea": "Area",
"GraphicsScalingFilterLevelLabel": "日誌等級", "GraphicsScalingFilterLevelLabel": "日誌等級",
"GraphicsScalingFilterLevelTooltip": "設定 FSR 1.0 銳化等級。越高越清晰。", "GraphicsScalingFilterLevelTooltip": "設定 FSR 1.0 銳化等級。越高越清晰。",
"SmaaLow": "低階 SMAA", "SmaaLow": "低階 SMAA",

View File

@ -43,6 +43,10 @@
</StackPanel> </StackPanel>
</Border> </Border>
</Design.PreviewWith> </Design.PreviewWith>
<Style Selector="DropDownButton">
<Setter Property="FontSize"
Value="12" />
</Style>
<Style Selector="Border.small"> <Style Selector="Border.small">
<Setter Property="Width" <Setter Property="Width"
Value="100" /> Value="100" />
@ -231,6 +235,14 @@
<Setter Property="MinWidth" <Setter Property="MinWidth"
Value="80" /> Value="80" />
</Style> </Style>
<Style Selector="ProgressBar:horizontal">
<Setter Property="MinWidth" Value="0"/>
<Setter Property="MinHeight" Value="0"/>
</Style>
<Style Selector="ProgressBar:vertical">
<Setter Property="MinWidth" Value="0"/>
<Setter Property="MinHeight" Value="0"/>
</Style>
<Style Selector="ProgressBar /template/ Border#ProgressBarTrack"> <Style Selector="ProgressBar /template/ Border#ProgressBarTrack">
<Setter Property="IsVisible" <Setter Property="IsVisible"
Value="False" /> Value="False" />
@ -389,7 +401,7 @@
<x:Double x:Key="ControlContentThemeFontSize">13</x:Double> <x:Double x:Key="ControlContentThemeFontSize">13</x:Double>
<x:Double x:Key="MenuItemHeight">26</x:Double> <x:Double x:Key="MenuItemHeight">26</x:Double>
<x:Double x:Key="TabItemMinHeight">28</x:Double> <x:Double x:Key="TabItemMinHeight">28</x:Double>
<x:Double x:Key="ContentDialogMaxWidth">600</x:Double> <x:Double x:Key="ContentDialogMaxWidth">700</x:Double>
<x:Double x:Key="ContentDialogMaxHeight">756</x:Double> <x:Double x:Key="ContentDialogMaxHeight">756</x:Double>
</Styles.Resources> </Styles.Resources>
</Styles> </Styles>

View File

@ -2,19 +2,38 @@
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.Markup.Xaml.MarkupExtensions; using Avalonia.Markup.Xaml.MarkupExtensions;
using Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings; using Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings;
using Gommon;
using System; using System;
// ReSharper disable VirtualMemberNeverOverridden.Global
// ReSharper disable MemberCanBeProtected.Global
// ReSharper disable MemberCanBePrivate.Global
#nullable enable
namespace Ryujinx.Ava.Common.Markup namespace Ryujinx.Ava.Common.Markup
{ {
internal abstract class BasicMarkupExtension : MarkupExtension internal abstract class BasicMarkupExtension<T> : MarkupExtension
{ {
protected abstract ClrPropertyInfo PropertyInfo { get; } public virtual string Name => "Item";
public virtual Action<object, T?>? Setter => null;
public override object ProvideValue(IServiceProvider serviceProvider) => protected abstract T? GetValue();
new CompiledBindingExtension(
new CompiledBindingPathBuilder() protected virtual void ConfigureBindingExtension(CompiledBindingExtension _) { }
.Property(PropertyInfo, PropertyInfoAccessorFactory.CreateInpcPropertyAccessor)
.Build() private ClrPropertyInfo PropertyInfo =>
).ProvideValue(serviceProvider); new(Name,
_ => GetValue(),
Setter as Action<object, object?>,
typeof(T));
public override object ProvideValue(IServiceProvider serviceProvider)
=> new CompiledBindingExtension(
new CompiledBindingPathBuilder()
.Property(PropertyInfo, PropertyInfoAccessorFactory.CreateInpcPropertyAccessor)
.Build()
)
.Apply(ConfigureBindingExtension)
.ProvideValue(serviceProvider);
} }
} }

View File

@ -1,51 +1,24 @@
using Avalonia.Data.Core;
using Avalonia.Markup.Xaml;
using Avalonia.Markup.Xaml.MarkupExtensions; using Avalonia.Markup.Xaml.MarkupExtensions;
using Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings;
using Projektanker.Icons.Avalonia; using Projektanker.Icons.Avalonia;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using System;
namespace Ryujinx.Ava.Common.Markup namespace Ryujinx.Ava.Common.Markup
{ {
internal class IconExtension(string iconString) : BasicMarkupExtension internal class IconExtension(string iconString) : BasicMarkupExtension<Icon>
{ {
protected override ClrPropertyInfo PropertyInfo protected override Icon GetValue() => new() { Value = iconString };
=> new(
"Item",
_ => new Icon { Value = iconString },
null,
typeof(Icon)
);
} }
internal class SpinningIconExtension(string iconString) : BasicMarkupExtension internal class SpinningIconExtension(string iconString) : BasicMarkupExtension<Icon>
{ {
protected override ClrPropertyInfo PropertyInfo protected override Icon GetValue() => new() { Value = iconString, Animation = IconAnimation.Spin };
=> new(
"Item",
_ => new Icon { Value = iconString, Animation = IconAnimation.Spin },
null,
typeof(Icon)
);
} }
internal class LocaleExtension(LocaleKeys key) : MarkupExtension internal class LocaleExtension(LocaleKeys key) : BasicMarkupExtension<string>
{ {
private ClrPropertyInfo PropertyInfo protected override string GetValue() => LocaleManager.Instance[key];
=> new(
"Item",
_ => LocaleManager.Instance[key],
null,
typeof(string)
);
public override object ProvideValue(IServiceProvider serviceProvider) => protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension)
new CompiledBindingExtension( => bindingExtension.Source = LocaleManager.Instance;
new CompiledBindingPathBuilder()
.Property(PropertyInfo, PropertyInfoAccessorFactory.CreateInpcPropertyAccessor)
.Build()
) { Source = LocaleManager.Instance }
.ProvideValue(serviceProvider);
} }
} }

View File

@ -0,0 +1,24 @@
using Avalonia.Threading;
using Ryujinx.Ava.UI.ViewModels;
namespace Ryujinx.Ava.Common
{
internal class XCIFileTrimmerMainWindowLog : Ryujinx.Common.Logging.XCIFileTrimmerLog
{
private readonly MainWindowViewModel _viewModel;
public XCIFileTrimmerMainWindowLog(MainWindowViewModel viewModel)
{
_viewModel = viewModel;
}
public override void Progress(long current, long total, string text, bool complete)
{
Dispatcher.UIThread.Post(() =>
{
_viewModel.StatusBarProgressMaximum = (int)(total);
_viewModel.StatusBarProgressValue = (int)(current);
});
}
}
}

View File

@ -0,0 +1,23 @@
using Avalonia.Threading;
using Ryujinx.Ava.UI.ViewModels;
namespace Ryujinx.Ava.Common
{
internal class XCIFileTrimmerWindowLog : Ryujinx.Common.Logging.XCIFileTrimmerLog
{
private readonly XCITrimmerViewModel _viewModel;
public XCIFileTrimmerWindowLog(XCITrimmerViewModel viewModel)
{
_viewModel = viewModel;
}
public override void Progress(long current, long total, string text, bool complete)
{
Dispatcher.UIThread.Post(() =>
{
_viewModel.SetProgress((int)(current), (int)(total));
});
}
}
}

View File

@ -23,21 +23,15 @@ namespace Ryujinx.Ava.Input
public bool IsConnected => true; public bool IsConnected => true;
public GamepadFeaturesFlag Features => GamepadFeaturesFlag.None; public GamepadFeaturesFlag Features => GamepadFeaturesFlag.None;
private class ButtonMappingEntry private class ButtonMappingEntry(GamepadButtonInputId to, Key from)
{ {
public readonly Key From; public readonly GamepadButtonInputId To = to;
public readonly GamepadButtonInputId To; public readonly Key From = from;
public ButtonMappingEntry(GamepadButtonInputId to, Key from)
{
To = to;
From = from;
}
} }
public AvaloniaKeyboard(AvaloniaKeyboardDriver driver, string id, string name) public AvaloniaKeyboard(AvaloniaKeyboardDriver driver, string id, string name)
{ {
_buttonsUserMapping = new List<ButtonMappingEntry>(); _buttonsUserMapping = [];
_driver = driver; _driver = driver;
Id = id; Id = id;

View File

@ -14,7 +14,7 @@
</PropertyGroup> </PropertyGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="$([MSBuild]::IsOSPlatform('OSX'))"> <Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="$([MSBuild]::IsOSPlatform('OSX'))">
<Exec Command="codesign --entitlements '$(ProjectDir)..\..\distribution\macos\entitlements.xml' -f --deep -s $(SigningCertificate) '$(TargetDir)$(TargetName)'" /> <Exec Command="codesign --entitlements '$(ProjectDir)..\..\distribution\macos\entitlements.xml' -f -s $(SigningCertificate) '$(TargetDir)$(TargetName)'" />
</Target> </Target>
<PropertyGroup Condition="'$(RuntimeIdentifier)' != ''"> <PropertyGroup Condition="'$(RuntimeIdentifier)' != ''">

View File

@ -127,11 +127,11 @@ namespace Ryujinx.Ava.UI.Applet
try try
{ {
_parent.ViewModel.AppHost.NpadManager.BlockInputUpdates(); _parent.ViewModel.AppHost.NpadManager.BlockInputUpdates();
var response = await SwkbdAppletDialog.ShowInputDialog(LocaleManager.Instance[LocaleKeys.SoftwareKeyboard], args); (UserResult result, string userInput) = await SwkbdAppletDialog.ShowInputDialog(LocaleManager.Instance[LocaleKeys.SoftwareKeyboard], args);
if (response.Result == UserResult.Ok) if (result == UserResult.Ok)
{ {
inputText = response.Input; inputText = userInput;
okPressed = true; okPressed = true;
} }
} }

View File

@ -69,6 +69,12 @@
Header="{ext:Locale GameListContextMenuOpenSdModsDirectory}" Header="{ext:Locale GameListContextMenuOpenSdModsDirectory}"
Icon="{ext:Icon mdi-folder-file}" Icon="{ext:Icon mdi-folder-file}"
ToolTip.Tip="{ext:Locale GameListContextMenuOpenSdModsDirectoryToolTip}" /> ToolTip.Tip="{ext:Locale GameListContextMenuOpenSdModsDirectoryToolTip}" />
<Separator />
<MenuItem
Click="TrimXCI_Click"
Header="{ext:Locale GameListContextMenuTrimXCI}"
IsEnabled="{Binding TrimXCIEnabled}"
ToolTip.Tip="{ext:Locale GameListContextMenuTrimXCIToolTip}" />
<Separator /> <Separator />
<MenuItem Header="{ext:Locale GameListContextMenuCacheManagement}" Icon="{ext:Icon mdi-cached}"> <MenuItem Header="{ext:Locale GameListContextMenuCacheManagement}" Icon="{ext:Icon mdi-cached}">
<MenuItem <MenuItem

View File

@ -2,6 +2,7 @@ using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.Threading;
using LibHac.Fs; using LibHac.Fs;
using LibHac.Tools.FsSystem.NcaUtils; using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Ava.Common; using Ryujinx.Ava.Common;
@ -17,6 +18,8 @@ using SkiaSharp;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Path = System.IO.Path; using Path = System.IO.Path;
namespace Ryujinx.Ava.UI.Controls namespace Ryujinx.Ava.UI.Controls
@ -323,5 +326,15 @@ namespace Ryujinx.Ava.UI.Controls
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
await viewModel.LoadApplication(viewModel.SelectedApplication); await viewModel.LoadApplication(viewModel.SelectedApplication);
} }
public async void TrimXCI_Click(object sender, RoutedEventArgs args)
{
var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel;
if (viewModel?.SelectedApplication != null)
{
await viewModel.TrimXCIFile(viewModel.SelectedApplication.Path);
}
}
} }
} }

View File

@ -0,0 +1,62 @@
using Avalonia.Collections;
using System.Collections.Generic;
namespace Ryujinx.Ava.UI.Helpers
{
public static class AvaloniaListExtensions
{
/// <summary>
/// Adds or Replaces an item in an AvaloniaList irrespective of whether the item already exists
/// </summary>
/// <typeparam name="T">The type of the element in the AvaoloniaList</typeparam>
/// <param name="list">The list containing the item to replace</param>
/// <param name="item">The item to replace</param>
/// <param name="addIfNotFound">True to add the item if its not found</param>
/// <returns>True if the item was found and replaced, false if it was addded</returns>
/// <remarks>
/// The indexes on the AvaloniaList will only replace if the item does not match,
/// this causes the items to not be replaced if the Equality is customised on the
/// items. This method will instead find, remove and add the item to ensure it is
/// replaced correctly.
/// </remarks>
public static bool ReplaceWith<T>(this AvaloniaList<T> list, T item, bool addIfNotFound = true)
{
var index = list.IndexOf(item);
if (index != -1)
{
list.RemoveAt(index);
list.Insert(index, item);
return true;
}
else
{
list.Add(item);
return false;
}
}
/// <summary>
/// Adds or Replaces items in an AvaloniaList from another list irrespective of whether the item already exists
/// </summary>
/// <typeparam name="T">The type of the element in the AvaoloniaList</typeparam>
/// <param name="list">The list containing the item to replace</param>
/// <param name="sourceList">The list of items to be actually added to `list`</param>
/// <param name="matchingList">The items to use as matching records to search for in the `sourceList', if not found this item will be added instead</params>
public static void AddOrReplaceMatching<T>(this AvaloniaList<T> list, IList<T> sourceList, IList<T> matchingList)
{
foreach (var match in matchingList)
{
var index = sourceList.IndexOf(match);
if (index != -1)
{
list.ReplaceWith(sourceList[index]);
}
else
{
list.ReplaceWith(match);
}
}
}
}
}

View File

@ -0,0 +1,48 @@
using Avalonia;
using Avalonia.Data;
using Avalonia.Data.Converters;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.UI.Common.Models;
using System;
using System.Globalization;
namespace Ryujinx.Ava.UI.Helpers
{
internal class XCITrimmerFileSpaceSavingsConverter : IValueConverter
{
private const long _bytesPerMB = 1024 * 1024;
public static XCITrimmerFileSpaceSavingsConverter Instance = new();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is UnsetValueType)
{
return BindingOperations.DoNothing;
}
if (!targetType.IsAssignableFrom(typeof(string)))
{
return null;
}
if (value is not XCITrimmerFileModel app)
{
return null;
}
if (app.CurrentSavingsB < app.PotentialSavingsB)
{
return LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.TitleXCICanSaveLabel, (app.PotentialSavingsB - app.CurrentSavingsB) / _bytesPerMB);
}
else
{
return LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.TitleXCISavingLabel, app.CurrentSavingsB / _bytesPerMB);
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
}

View File

@ -0,0 +1,46 @@
using Avalonia;
using Avalonia.Data;
using Avalonia.Data.Converters;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.UI.Common.Models;
using System;
using System.Globalization;
using static Ryujinx.Common.Utilities.XCIFileTrimmer;
namespace Ryujinx.Ava.UI.Helpers
{
internal class XCITrimmerFileStatusConverter : IValueConverter
{
public static XCITrimmerFileStatusConverter Instance = new();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is UnsetValueType)
{
return BindingOperations.DoNothing;
}
if (!targetType.IsAssignableFrom(typeof(string)))
{
return null;
}
if (value is not XCITrimmerFileModel app)
{
return null;
}
return app.PercentageProgress != null ? String.Empty :
app.ProcessingOutcome != OperationOutcome.Successful && app.ProcessingOutcome != OperationOutcome.Undetermined ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusFailedLabel] :
app.Trimmable & app.Untrimmable ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusPartialLabel] :
app.Trimmable ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusTrimmableLabel] :
app.Untrimmable ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusUntrimmableLabel] :
String.Empty;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
}

View File

@ -0,0 +1,42 @@
using Avalonia;
using Avalonia.Data;
using Avalonia.Data.Converters;
using Ryujinx.UI.Common.Models;
using System;
using System.Globalization;
using static Ryujinx.Common.Utilities.XCIFileTrimmer;
namespace Ryujinx.Ava.UI.Helpers
{
internal class XCITrimmerFileStatusDetailConverter : IValueConverter
{
public static XCITrimmerFileStatusDetailConverter Instance = new();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is UnsetValueType)
{
return BindingOperations.DoNothing;
}
if (!targetType.IsAssignableFrom(typeof(string)))
{
return null;
}
if (value is not XCITrimmerFileModel app)
{
return null;
}
return app.PercentageProgress != null ? null :
app.ProcessingOutcome != OperationOutcome.Successful && app.ProcessingOutcome != OperationOutcome.Undetermined ? app.ProcessingOutcome.ToLocalisedText() :
null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
}

View File

@ -0,0 +1,36 @@
using Ryujinx.Ava.Common.Locale;
using static Ryujinx.Common.Utilities.XCIFileTrimmer;
namespace Ryujinx.Ava.UI.Helpers
{
public static class XCIFileTrimmerOperationOutcomeExtensions
{
public static string ToLocalisedText(this OperationOutcome operationOutcome)
{
switch (operationOutcome)
{
case OperationOutcome.NoTrimNecessary:
return LocaleManager.Instance[LocaleKeys.TrimXCIFileNoTrimNecessary];
case OperationOutcome.NoUntrimPossible:
return LocaleManager.Instance[LocaleKeys.TrimXCIFileNoUntrimPossible];
case OperationOutcome.ReadOnlyFileCannotFix:
return LocaleManager.Instance[LocaleKeys.TrimXCIFileReadOnlyFileCannotFix];
case OperationOutcome.FreeSpaceCheckFailed:
return LocaleManager.Instance[LocaleKeys.TrimXCIFileFreeSpaceCheckFailed];
case OperationOutcome.InvalidXCIFile:
return LocaleManager.Instance[LocaleKeys.TrimXCIFileInvalidXCIFile];
case OperationOutcome.FileIOWriteError:
return LocaleManager.Instance[LocaleKeys.TrimXCIFileFileIOWriteError];
case OperationOutcome.FileSizeChanged:
return LocaleManager.Instance[LocaleKeys.TrimXCIFileFileSizeChanged];
case OperationOutcome.Cancelled:
return LocaleManager.Instance[LocaleKeys.TrimXCIFileCancelled];
case OperationOutcome.Undetermined:
return LocaleManager.Instance[LocaleKeys.TrimXCIFileFileUndertermined];
case OperationOutcome.Successful:
default:
return null;
}
}
}
}

View File

@ -22,6 +22,7 @@ using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities;
using Ryujinx.Cpu; using Ryujinx.Cpu;
using Ryujinx.HLE; using Ryujinx.HLE;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
@ -84,6 +85,8 @@ namespace Ryujinx.Ava.UI.ViewModels
private bool _isAppletMenuActive; private bool _isAppletMenuActive;
private int _statusBarProgressMaximum; private int _statusBarProgressMaximum;
private int _statusBarProgressValue; private int _statusBarProgressValue;
private string _statusBarProgressStatusText;
private bool _statusBarProgressStatusVisible;
private bool _isPaused; private bool _isPaused;
private bool _showContent = true; private bool _showContent = true;
private bool _isLoadingIndeterminate = true; private bool _isLoadingIndeterminate = true;
@ -391,6 +394,8 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool OpenDeviceSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.DeviceSaveDataSize > 0; public bool OpenDeviceSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.DeviceSaveDataSize > 0;
public bool TrimXCIEnabled => Ryujinx.Common.Utilities.XCIFileTrimmer.CanTrim(SelectedApplication.Path, new Common.XCIFileTrimmerMainWindowLog(this));
public bool OpenBcatSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0; public bool OpenBcatSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0;
public bool CreateShortcutEnabled => !ReleaseInformation.IsFlatHubBuild; public bool CreateShortcutEnabled => !ReleaseInformation.IsFlatHubBuild;
@ -505,6 +510,28 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public bool StatusBarProgressStatusVisible
{
get => _statusBarProgressStatusVisible;
set
{
_statusBarProgressStatusVisible = value;
OnPropertyChanged();
}
}
public string StatusBarProgressStatusText
{
get => _statusBarProgressStatusText;
set
{
_statusBarProgressStatusText = value;
OnPropertyChanged();
}
}
public string FifoStatusText public string FifoStatusText
{ {
get => _fifoStatusText; get => _fifoStatusText;
@ -1776,6 +1803,7 @@ namespace Ryujinx.Ava.UI.ViewModels
if (WindowState is not WindowState.Normal) if (WindowState is not WindowState.Normal)
{ {
WindowState = WindowState.Normal; WindowState = WindowState.Normal;
Window.TitleBar.ExtendsContentIntoTitleBar = !ConfigurationState.Instance.ShowTitleBar;
if (IsGameRunning) if (IsGameRunning)
{ {
@ -1785,6 +1813,7 @@ namespace Ryujinx.Ava.UI.ViewModels
else else
{ {
WindowState = WindowState.FullScreen; WindowState = WindowState.FullScreen;
Window.TitleBar.ExtendsContentIntoTitleBar = true;
if (IsGameRunning) if (IsGameRunning)
{ {
@ -1832,6 +1861,98 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
} }
public async void ProcessTrimResult(String filename, Ryujinx.Common.Utilities.XCIFileTrimmer.OperationOutcome operationOutcome)
{
string notifyUser = operationOutcome.ToLocalisedText();
if (notifyUser != null)
{
await ContentDialogHelper.CreateWarningDialog(
LocaleManager.Instance[LocaleKeys.TrimXCIFileFailedPrimaryText],
notifyUser
);
}
else
{
switch (operationOutcome)
{
case Ryujinx.Common.Utilities.XCIFileTrimmer.OperationOutcome.Successful:
if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
if (desktop.MainWindow is MainWindow mainWindow)
mainWindow.LoadApplications();
}
break;
}
}
}
public async Task TrimXCIFile(string filename)
{
if (filename == null)
{
return;
}
var trimmer = new XCIFileTrimmer(filename, new Common.XCIFileTrimmerMainWindowLog(this));
if (trimmer.CanBeTrimmed)
{
var savings = (double)trimmer.DiskSpaceSavingsB / 1024.0 / 1024.0;
var currentFileSize = (double)trimmer.FileSizeB / 1024.0 / 1024.0;
var cartDataSize = (double)trimmer.DataSizeB / 1024.0 / 1024.0;
string secondaryText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.TrimXCIFileDialogSecondaryText, currentFileSize, cartDataSize, savings);
var result = await ContentDialogHelper.CreateConfirmationDialog(
LocaleManager.Instance[LocaleKeys.TrimXCIFileDialogPrimaryText],
secondaryText,
LocaleManager.Instance[LocaleKeys.Continue],
LocaleManager.Instance[LocaleKeys.Cancel],
LocaleManager.Instance[LocaleKeys.TrimXCIFileDialogTitle]
);
if (result == UserResult.Yes)
{
Thread XCIFileTrimThread = new(() =>
{
Dispatcher.UIThread.Post(() =>
{
StatusBarProgressStatusText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarXCIFileTrimming, Path.GetFileName(filename));
StatusBarProgressStatusVisible = true;
StatusBarProgressMaximum = 1;
StatusBarProgressValue = 0;
StatusBarVisible = true;
});
try
{
XCIFileTrimmer.OperationOutcome operationOutcome = trimmer.Trim();
Dispatcher.UIThread.Post(() =>
{
ProcessTrimResult(filename, operationOutcome);
});
}
finally
{
Dispatcher.UIThread.Post(() =>
{
StatusBarProgressStatusVisible = false;
StatusBarProgressStatusText = string.Empty;
StatusBarVisible = false;
});
}
})
{
Name = "GUI.XCIFileTrimmerThread",
IsBackground = true,
};
XCIFileTrimThread.Start();
}
}
}
#endregion #endregion
} }
} }

View File

@ -0,0 +1,541 @@
using Avalonia.Collections;
using DynamicData;
using Gommon;
using Avalonia.Threading;
using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Common.Utilities;
using Ryujinx.UI.App.Common;
using Ryujinx.UI.Common.Models;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using static Ryujinx.Common.Utilities.XCIFileTrimmer;
namespace Ryujinx.Ava.UI.ViewModels
{
public class XCITrimmerViewModel : BaseModel
{
private const long _bytesPerMB = 1024 * 1024;
private enum ProcessingMode
{
Trimming,
Untrimming
}
public enum SortField
{
Name,
Saved
}
private const string _FileExtXCI = "XCI";
private readonly Ryujinx.Common.Logging.XCIFileTrimmerLog _logger;
private readonly ApplicationLibrary _applicationLibrary;
private Optional<XCITrimmerFileModel> _processingApplication = null;
private AvaloniaList<XCITrimmerFileModel> _allXCIFiles = new();
private AvaloniaList<XCITrimmerFileModel> _selectedXCIFiles = new();
private AvaloniaList<XCITrimmerFileModel> _displayedXCIFiles = new();
private MainWindowViewModel _mainWindowViewModel;
private CancellationTokenSource _cancellationTokenSource;
private string _search;
private ProcessingMode _processingMode;
private SortField _sortField = SortField.Name;
private bool _sortAscending = true;
public XCITrimmerViewModel(MainWindowViewModel mainWindowViewModel)
{
_logger = new XCIFileTrimmerWindowLog(this);
_mainWindowViewModel = mainWindowViewModel;
_applicationLibrary = _mainWindowViewModel.ApplicationLibrary;
LoadXCIApplications();
}
private void LoadXCIApplications()
{
var apps = _applicationLibrary.Applications.Items
.Where(app => app.FileExtension == _FileExtXCI);
foreach (var xciApp in apps)
AddOrUpdateXCITrimmerFile(CreateXCITrimmerFile(xciApp.Path));
ApplicationsChanged();
}
private XCITrimmerFileModel CreateXCITrimmerFile(
string path,
OperationOutcome operationOutcome = OperationOutcome.Undetermined)
{
var xciApp = _applicationLibrary.Applications.Items.First(app => app.FileExtension == _FileExtXCI && app.Path == path);
return XCITrimmerFileModel.FromApplicationData(xciApp, _logger) with { ProcessingOutcome = operationOutcome };
}
private bool AddOrUpdateXCITrimmerFile(XCITrimmerFileModel xci, bool suppressChanged = true, bool autoSelect = true)
{
bool replaced = _allXCIFiles.ReplaceWith(xci);
_displayedXCIFiles.ReplaceWith(xci, Filter(xci));
_selectedXCIFiles.ReplaceWith(xci, xci.Trimmable && autoSelect);
if (!suppressChanged)
ApplicationsChanged();
return replaced;
}
private void FilteringChanged()
{
OnPropertyChanged(nameof(Search));
SortAndFilter();
}
private void SortingChanged()
{
OnPropertyChanged(nameof(IsSortedByName));
OnPropertyChanged(nameof(IsSortedBySaved));
OnPropertyChanged(nameof(SortingAscending));
OnPropertyChanged(nameof(SortingField));
OnPropertyChanged(nameof(SortingFieldName));
SortAndFilter();
}
private void DisplayedChanged()
{
OnPropertyChanged(nameof(Status));
OnPropertyChanged(nameof(DisplayedXCIFiles));
OnPropertyChanged(nameof(SelectedDisplayedXCIFiles));
}
private void ApplicationsChanged()
{
OnPropertyChanged(nameof(AllXCIFiles));
OnPropertyChanged(nameof(Status));
OnPropertyChanged(nameof(PotentialSavings));
OnPropertyChanged(nameof(ActualSavings));
OnPropertyChanged(nameof(CanTrim));
OnPropertyChanged(nameof(CanUntrim));
DisplayedChanged();
SortAndFilter();
}
private void SelectionChanged(bool displayedChanged = true)
{
OnPropertyChanged(nameof(Status));
OnPropertyChanged(nameof(CanTrim));
OnPropertyChanged(nameof(CanUntrim));
OnPropertyChanged(nameof(SelectedXCIFiles));
if (displayedChanged)
OnPropertyChanged(nameof(SelectedDisplayedXCIFiles));
}
private void ProcessingChanged()
{
OnPropertyChanged(nameof(Processing));
OnPropertyChanged(nameof(Cancel));
OnPropertyChanged(nameof(Status));
OnPropertyChanged(nameof(CanTrim));
OnPropertyChanged(nameof(CanUntrim));
}
private IEnumerable<XCITrimmerFileModel> GetSelectedDisplayedXCIFiles()
{
return _displayedXCIFiles.Where(xci => _selectedXCIFiles.Contains(xci));
}
private void PerformOperation(ProcessingMode processingMode)
{
if (Processing)
{
return;
}
_processingMode = processingMode;
Processing = true;
var cancellationToken = _cancellationTokenSource.Token;
Thread XCIFileTrimThread = new(() =>
{
var toProcess = Sort(SelectedXCIFiles
.Where(xci =>
(processingMode == ProcessingMode.Untrimming && xci.Untrimmable) ||
(processingMode == ProcessingMode.Trimming && xci.Trimmable)
)).ToList();
var viewsSaved = DisplayedXCIFiles.ToList();
Dispatcher.UIThread.Post(() =>
{
_selectedXCIFiles.Clear();
_displayedXCIFiles.Clear();
_displayedXCIFiles.AddRange(toProcess);
});
try
{
foreach (var xciApp in toProcess)
{
if (cancellationToken.IsCancellationRequested)
break;
var trimmer = new XCIFileTrimmer(xciApp.Path, _logger);
Dispatcher.UIThread.Post(() =>
{
ProcessingApplication = xciApp;
});
var outcome = OperationOutcome.Undetermined;
try
{
if (cancellationToken.IsCancellationRequested)
break;
switch (processingMode)
{
case ProcessingMode.Trimming:
outcome = trimmer.Trim(cancellationToken);
break;
case ProcessingMode.Untrimming:
outcome = trimmer.Untrim(cancellationToken);
break;
}
if (outcome == OperationOutcome.Cancelled)
outcome = OperationOutcome.Undetermined;
}
finally
{
Dispatcher.UIThread.Post(() =>
{
ProcessingApplication = CreateXCITrimmerFile(xciApp.Path);
AddOrUpdateXCITrimmerFile(ProcessingApplication, false, false);
ProcessingApplication = null;
});
}
}
}
finally
{
Dispatcher.UIThread.Post(() =>
{
_displayedXCIFiles.AddOrReplaceMatching(_allXCIFiles, viewsSaved);
_selectedXCIFiles.AddOrReplaceMatching(_allXCIFiles, toProcess);
Processing = false;
ApplicationsChanged();
});
}
})
{
Name = "GUI.XCIFilesTrimmerThread",
IsBackground = true,
};
XCIFileTrimThread.Start();
}
private bool Filter<T>(T arg)
{
if (arg is XCITrimmerFileModel content)
{
return string.IsNullOrWhiteSpace(_search)
|| content.Name.ToLower().Contains(_search.ToLower())
|| content.Path.ToLower().Contains(_search.ToLower());
}
return false;
}
private class CompareXCITrimmerFiles : IComparer<XCITrimmerFileModel>
{
private XCITrimmerViewModel _viewModel;
public CompareXCITrimmerFiles(XCITrimmerViewModel ViewModel)
{
_viewModel = ViewModel;
}
public int Compare(XCITrimmerFileModel x, XCITrimmerFileModel y)
{
int result = 0;
switch (_viewModel.SortingField)
{
case SortField.Name:
result = x.Name.CompareTo(y.Name);
break;
case SortField.Saved:
result = x.PotentialSavingsB.CompareTo(y.PotentialSavingsB);
break;
}
if (!_viewModel.SortingAscending)
result = -result;
if (result == 0)
result = x.Path.CompareTo(y.Path);
return result;
}
}
private IOrderedEnumerable<XCITrimmerFileModel> Sort(IEnumerable<XCITrimmerFileModel> list)
{
return list
.OrderBy(xci => xci, new CompareXCITrimmerFiles(this))
.ThenBy(it => it.Path);
}
public void TrimSelected()
{
PerformOperation(ProcessingMode.Trimming);
}
public void UntrimSelected()
{
PerformOperation(ProcessingMode.Untrimming);
}
public void SetProgress(int current, int maximum)
{
if (_processingApplication != null)
{
int percentageProgress = 100 * current / maximum;
if (!ProcessingApplication.HasValue || (ProcessingApplication.Value.PercentageProgress != percentageProgress))
ProcessingApplication = ProcessingApplication.Value with { PercentageProgress = percentageProgress };
}
}
public void SelectDisplayed()
{
SelectedXCIFiles.AddRange(DisplayedXCIFiles);
SelectionChanged();
}
public void DeselectDisplayed()
{
SelectedXCIFiles.RemoveMany(DisplayedXCIFiles);
SelectionChanged();
}
public void Select(XCITrimmerFileModel model)
{
bool selectionChanged = !SelectedXCIFiles.Contains(model);
bool displayedSelectionChanged = !SelectedDisplayedXCIFiles.Contains(model);
SelectedXCIFiles.ReplaceOrAdd(model, model);
if (selectionChanged)
SelectionChanged(displayedSelectionChanged);
}
public void Deselect(XCITrimmerFileModel model)
{
bool displayedSelectionChanged = !SelectedDisplayedXCIFiles.Contains(model);
if (SelectedXCIFiles.Remove(model))
SelectionChanged(displayedSelectionChanged);
}
public void SortAndFilter()
{
if (Processing)
return;
Sort(AllXCIFiles)
.AsObservableChangeSet()
.Filter(Filter)
.Bind(out var view).AsObservableList();
_displayedXCIFiles.Clear();
_displayedXCIFiles.AddRange(view);
DisplayedChanged();
}
public Optional<XCITrimmerFileModel> ProcessingApplication
{
get => _processingApplication;
set
{
if (!value.HasValue && _processingApplication.HasValue)
value = _processingApplication.Value with { PercentageProgress = null };
if (value.HasValue)
_displayedXCIFiles.ReplaceWith(value.Value);
_processingApplication = value;
OnPropertyChanged();
}
}
public bool Processing
{
get => _cancellationTokenSource != null;
private set
{
if (value && !Processing)
{
_cancellationTokenSource = new CancellationTokenSource();
}
else if (!value && Processing)
{
_cancellationTokenSource.Dispose();
_cancellationTokenSource = null;
}
ProcessingChanged();
}
}
public bool Cancel
{
get => _cancellationTokenSource != null && _cancellationTokenSource.IsCancellationRequested;
set
{
if (value)
{
if (!Processing)
return;
_cancellationTokenSource.Cancel();
}
ProcessingChanged();
}
}
public string Status
{
get
{
if (Processing)
{
return _processingMode switch
{
ProcessingMode.Trimming => string.Format(LocaleManager.Instance[LocaleKeys.XCITrimmerTitleStatusTrimming], DisplayedXCIFiles.Count),
ProcessingMode.Untrimming => string.Format(LocaleManager.Instance[LocaleKeys.XCITrimmerTitleStatusUntrimming], DisplayedXCIFiles.Count),
_ => string.Empty
};
}
else
{
return string.IsNullOrEmpty(Search) ?
string.Format(LocaleManager.Instance[LocaleKeys.XCITrimmerTitleStatusCount], SelectedXCIFiles.Count, AllXCIFiles.Count) :
string.Format(LocaleManager.Instance[LocaleKeys.XCITrimmerTitleStatusCountWithFilter], SelectedXCIFiles.Count, AllXCIFiles.Count, DisplayedXCIFiles.Count);
}
}
}
public string Search
{
get => _search;
set
{
_search = value;
FilteringChanged();
}
}
public SortField SortingField
{
get => _sortField;
set
{
_sortField = value;
SortingChanged();
}
}
public string SortingFieldName
{
get
{
return SortingField switch
{
SortField.Name => LocaleManager.Instance[LocaleKeys.XCITrimmerSortName],
SortField.Saved => LocaleManager.Instance[LocaleKeys.XCITrimmerSortSaved],
_ => string.Empty,
};
}
}
public bool SortingAscending
{
get => _sortAscending;
set
{
_sortAscending = value;
SortingChanged();
}
}
public bool IsSortedByName
{
get => _sortField == SortField.Name;
}
public bool IsSortedBySaved
{
get => _sortField == SortField.Saved;
}
public AvaloniaList<XCITrimmerFileModel> SelectedXCIFiles
{
get => _selectedXCIFiles;
set
{
_selectedXCIFiles = value;
SelectionChanged();
}
}
public AvaloniaList<XCITrimmerFileModel> AllXCIFiles
{
get => _allXCIFiles;
}
public AvaloniaList<XCITrimmerFileModel> DisplayedXCIFiles
{
get => _displayedXCIFiles;
}
public string PotentialSavings
{
get
{
return string.Format(LocaleManager.Instance[LocaleKeys.XCITrimmerSavingsMb], AllXCIFiles.Sum(xci => xci.PotentialSavingsB / _bytesPerMB));
}
}
public string ActualSavings
{
get
{
return string.Format(LocaleManager.Instance[LocaleKeys.XCITrimmerSavingsMb], AllXCIFiles.Sum(xci => xci.CurrentSavingsB / _bytesPerMB));
}
}
public IEnumerable<XCITrimmerFileModel> SelectedDisplayedXCIFiles
{
get
{
return GetSelectedDisplayedXCIFiles().ToList();
}
}
public bool CanTrim
{
get
{
return !Processing && _selectedXCIFiles.Any(xci => xci.Trimmable);
}
}
public bool CanUntrim
{
get
{
return !Processing && _selectedXCIFiles.Any(xci => xci.Untrimmable);
}
}
}
}

View File

@ -33,7 +33,7 @@ namespace Ryujinx.Ava.UI.Views.Input
{ {
base.OnPointerReleased(e); base.OnPointerReleased(e);
if (_currentAssigner != null && _currentAssigner.ToggledButton != null && !_currentAssigner.ToggledButton.IsPointerOver) if (_currentAssigner is { ToggledButton.IsPointerOver: false })
{ {
_currentAssigner.Cancel(); _currentAssigner.Cancel();
} }
@ -41,143 +41,146 @@ namespace Ryujinx.Ava.UI.Views.Input
private void Button_IsCheckedChanged(object sender, RoutedEventArgs e) private void Button_IsCheckedChanged(object sender, RoutedEventArgs e)
{ {
if (sender is ToggleButton button) if (sender is not ToggleButton button)
return;
if (button.IsChecked is true)
{ {
if ((bool)button.IsChecked) if (_currentAssigner != null && button == _currentAssigner.ToggledButton)
{ {
if (_currentAssigner != null && button == _currentAssigner.ToggledButton) return;
{ }
if (_currentAssigner == null)
{
_currentAssigner = new ButtonKeyAssigner(button);
Focus(NavigationMethod.Pointer);
PointerPressed += MouseClick;
if (DataContext is not KeyboardInputViewModel viewModel)
return; return;
}
if (_currentAssigner == null) IKeyboard keyboard =
(IKeyboard)viewModel.ParentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
IButtonAssigner assigner =
new KeyboardKeyAssigner((IKeyboard)viewModel.ParentModel.SelectedGamepad);
_currentAssigner.ButtonAssigned += (_, e) =>
{ {
_currentAssigner = new ButtonKeyAssigner(button); if (e.ButtonValue.HasValue)
Focus(NavigationMethod.Pointer);
PointerPressed += MouseClick;
var viewModel = (DataContext as KeyboardInputViewModel);
IKeyboard keyboard = (IKeyboard)viewModel.ParentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
IButtonAssigner assigner = CreateButtonAssigner();
_currentAssigner.ButtonAssigned += (sender, e) =>
{ {
if (e.ButtonValue.HasValue) var buttonValue = e.ButtonValue.Value;
viewModel.ParentModel.IsModified = true;
switch (button.Name)
{ {
var buttonValue = e.ButtonValue.Value; case "ButtonZl":
viewModel.ParentModel.IsModified = true; viewModel.Config.ButtonZl = buttonValue.AsHidType<Key>();
break;
switch (button.Name) case "ButtonL":
{ viewModel.Config.ButtonL = buttonValue.AsHidType<Key>();
case "ButtonZl": break;
viewModel.Config.ButtonZl = buttonValue.AsHidType<Key>(); case "ButtonMinus":
break; viewModel.Config.ButtonMinus = buttonValue.AsHidType<Key>();
case "ButtonL": break;
viewModel.Config.ButtonL = buttonValue.AsHidType<Key>(); case "LeftStickButton":
break; viewModel.Config.LeftStickButton = buttonValue.AsHidType<Key>();
case "ButtonMinus": break;
viewModel.Config.ButtonMinus = buttonValue.AsHidType<Key>(); case "LeftStickUp":
break; viewModel.Config.LeftStickUp = buttonValue.AsHidType<Key>();
case "LeftStickButton": break;
viewModel.Config.LeftStickButton = buttonValue.AsHidType<Key>(); case "LeftStickDown":
break; viewModel.Config.LeftStickDown = buttonValue.AsHidType<Key>();
case "LeftStickUp": break;
viewModel.Config.LeftStickUp = buttonValue.AsHidType<Key>(); case "LeftStickRight":
break; viewModel.Config.LeftStickRight = buttonValue.AsHidType<Key>();
case "LeftStickDown": break;
viewModel.Config.LeftStickDown = buttonValue.AsHidType<Key>(); case "LeftStickLeft":
break; viewModel.Config.LeftStickLeft = buttonValue.AsHidType<Key>();
case "LeftStickRight": break;
viewModel.Config.LeftStickRight = buttonValue.AsHidType<Key>(); case "DpadUp":
break; viewModel.Config.DpadUp = buttonValue.AsHidType<Key>();
case "LeftStickLeft": break;
viewModel.Config.LeftStickLeft = buttonValue.AsHidType<Key>(); case "DpadDown":
break; viewModel.Config.DpadDown = buttonValue.AsHidType<Key>();
case "DpadUp": break;
viewModel.Config.DpadUp = buttonValue.AsHidType<Key>(); case "DpadLeft":
break; viewModel.Config.DpadLeft = buttonValue.AsHidType<Key>();
case "DpadDown": break;
viewModel.Config.DpadDown = buttonValue.AsHidType<Key>(); case "DpadRight":
break; viewModel.Config.DpadRight = buttonValue.AsHidType<Key>();
case "DpadLeft": break;
viewModel.Config.DpadLeft = buttonValue.AsHidType<Key>(); case "LeftButtonSr":
break; viewModel.Config.LeftButtonSr = buttonValue.AsHidType<Key>();
case "DpadRight": break;
viewModel.Config.DpadRight = buttonValue.AsHidType<Key>(); case "LeftButtonSl":
break; viewModel.Config.LeftButtonSl = buttonValue.AsHidType<Key>();
case "LeftButtonSr": break;
viewModel.Config.LeftButtonSr = buttonValue.AsHidType<Key>(); case "RightButtonSr":
break; viewModel.Config.RightButtonSr = buttonValue.AsHidType<Key>();
case "LeftButtonSl": break;
viewModel.Config.LeftButtonSl = buttonValue.AsHidType<Key>(); case "RightButtonSl":
break; viewModel.Config.RightButtonSl = buttonValue.AsHidType<Key>();
case "RightButtonSr": break;
viewModel.Config.RightButtonSr = buttonValue.AsHidType<Key>(); case "ButtonZr":
break; viewModel.Config.ButtonZr = buttonValue.AsHidType<Key>();
case "RightButtonSl": break;
viewModel.Config.RightButtonSl = buttonValue.AsHidType<Key>(); case "ButtonR":
break; viewModel.Config.ButtonR = buttonValue.AsHidType<Key>();
case "ButtonZr": break;
viewModel.Config.ButtonZr = buttonValue.AsHidType<Key>(); case "ButtonPlus":
break; viewModel.Config.ButtonPlus = buttonValue.AsHidType<Key>();
case "ButtonR": break;
viewModel.Config.ButtonR = buttonValue.AsHidType<Key>(); case "ButtonA":
break; viewModel.Config.ButtonA = buttonValue.AsHidType<Key>();
case "ButtonPlus": break;
viewModel.Config.ButtonPlus = buttonValue.AsHidType<Key>(); case "ButtonB":
break; viewModel.Config.ButtonB = buttonValue.AsHidType<Key>();
case "ButtonA": break;
viewModel.Config.ButtonA = buttonValue.AsHidType<Key>(); case "ButtonX":
break; viewModel.Config.ButtonX = buttonValue.AsHidType<Key>();
case "ButtonB": break;
viewModel.Config.ButtonB = buttonValue.AsHidType<Key>(); case "ButtonY":
break; viewModel.Config.ButtonY = buttonValue.AsHidType<Key>();
case "ButtonX": break;
viewModel.Config.ButtonX = buttonValue.AsHidType<Key>(); case "RightStickButton":
break; viewModel.Config.RightStickButton = buttonValue.AsHidType<Key>();
case "ButtonY": break;
viewModel.Config.ButtonY = buttonValue.AsHidType<Key>(); case "RightStickUp":
break; viewModel.Config.RightStickUp = buttonValue.AsHidType<Key>();
case "RightStickButton": break;
viewModel.Config.RightStickButton = buttonValue.AsHidType<Key>(); case "RightStickDown":
break; viewModel.Config.RightStickDown = buttonValue.AsHidType<Key>();
case "RightStickUp": break;
viewModel.Config.RightStickUp = buttonValue.AsHidType<Key>(); case "RightStickRight":
break; viewModel.Config.RightStickRight = buttonValue.AsHidType<Key>();
case "RightStickDown": break;
viewModel.Config.RightStickDown = buttonValue.AsHidType<Key>(); case "RightStickLeft":
break; viewModel.Config.RightStickLeft = buttonValue.AsHidType<Key>();
case "RightStickRight": break;
viewModel.Config.RightStickRight = buttonValue.AsHidType<Key>();
break;
case "RightStickLeft":
viewModel.Config.RightStickLeft = buttonValue.AsHidType<Key>();
break;
}
} }
};
_currentAssigner.GetInputAndAssign(assigner, keyboard);
}
else
{
if (_currentAssigner != null)
{
_currentAssigner.Cancel();
_currentAssigner = null;
button.IsChecked = false;
} }
} };
_currentAssigner.GetInputAndAssign(assigner, keyboard);
} }
else else
{ {
_currentAssigner?.Cancel(); if (_currentAssigner != null)
_currentAssigner = null; {
_currentAssigner.Cancel();
_currentAssigner = null;
button.IsChecked = false;
}
} }
} }
else
{
_currentAssigner?.Cancel();
_currentAssigner = null;
}
} }
private void MouseClick(object sender, PointerPressedEventArgs e) private void MouseClick(object sender, PointerPressedEventArgs e)
@ -189,15 +192,6 @@ namespace Ryujinx.Ava.UI.Views.Input
PointerPressed -= MouseClick; PointerPressed -= MouseClick;
} }
private IButtonAssigner CreateButtonAssigner()
{
IButtonAssigner assigner;
assigner = new KeyboardKeyAssigner((IKeyboard)(DataContext as KeyboardInputViewModel).ParentModel.SelectedGamepad);
return assigner;
}
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{ {
base.OnDetachedFromVisualTree(e); base.OnDetachedFromVisualTree(e);

View File

@ -12,13 +12,13 @@
<viewModels:MainWindowViewModel /> <viewModels:MainWindowViewModel />
</Design.DataContext> </Design.DataContext>
<DockPanel HorizontalAlignment="Stretch"> <DockPanel HorizontalAlignment="Stretch">
<Border Name="RyuLogo" Padding="7, 0, 0, 0" VerticalAlignment="Center" HorizontalAlignment="Center"> <Image
<Image Name="RyuLogo"
ToolTip.Tip="{Binding Title}" Margin="7,0"
Height="25" Height="25"
Width="25" Width="25"
Source="resm:Ryujinx.UI.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.UI.Common" /> ToolTip.Tip="{Binding Title}"
</Border> Source="resm:Ryujinx.UI.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.UI.Common" />
<Menu <Menu
Name="Menu" Name="Menu"
Height="35" Height="35"
@ -268,11 +268,13 @@
<MenuItem Header="{ext:Locale MenuBarToolsInstallFileTypes}" Click="InstallFileTypes_Click"/> <MenuItem Header="{ext:Locale MenuBarToolsInstallFileTypes}" Click="InstallFileTypes_Click"/>
<MenuItem Header="{ext:Locale MenuBarToolsUninstallFileTypes}" Click="UninstallFileTypes_Click"/> <MenuItem Header="{ext:Locale MenuBarToolsUninstallFileTypes}" Click="UninstallFileTypes_Click"/>
</MenuItem> </MenuItem>
<Separator />
<MenuItem Header="{ext:Locale MenuBarToolsXCITrimmer}" Click="OpenXCITrimmerWindow" Icon="{ext:Icon fa-solid fa-scissors}" />
</MenuItem> </MenuItem>
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarView}"> <MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarView}">
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarViewWindow}"> <MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarViewWindow}">
<MenuItem Header="{ext:Locale MenuBarViewWindow720}" Tag="720 1280" Click="ChangeWindowSize_Click" /> <MenuItem Header="{ext:Locale MenuBarViewWindow720}" Tag="1280 720" Click="ChangeWindowSize_Click" />
<MenuItem Header="{ext:Locale MenuBarViewWindow1080}" Tag="1080 1920" Click="ChangeWindowSize_Click" /> <MenuItem Header="{ext:Locale MenuBarViewWindow1080}" Tag="1920 1080" Click="ChangeWindowSize_Click" />
</MenuItem> </MenuItem>
</MenuItem> </MenuItem>
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarHelp}"> <MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarHelp}">

View File

@ -184,8 +184,10 @@ namespace Ryujinx.Ava.UI.Views.Main
if (sender is not MenuItem { Tag: string resolution }) if (sender is not MenuItem { Tag: string resolution })
return; return;
(int height, int width) = resolution.Split(' ') (int width, int height) = resolution.Split(' ', 2)
.Into(parts => (int.Parse(parts[0]), int.Parse(parts[1]))); .Into(parts =>
(int.Parse(parts[0]), int.Parse(parts[1]))
);
await Dispatcher.UIThread.InvokeAsync(() => await Dispatcher.UIThread.InvokeAsync(() =>
{ {
@ -200,9 +202,11 @@ namespace Ryujinx.Ava.UI.Views.Main
public async void CheckForUpdates(object sender, RoutedEventArgs e) public async void CheckForUpdates(object sender, RoutedEventArgs e)
{ {
if (Updater.CanUpdate(true)) if (Updater.CanUpdate(true))
await Updater.BeginParse(Window, true); await Window.BeginUpdateAsync(true);
} }
public async void OpenXCITrimmerWindow(object sender, RoutedEventArgs e) => await XCITrimmerWindow.Show(ViewModel);
public async void OpenAboutWindow(object sender, RoutedEventArgs e) => await AboutWindow.Show(); public async void OpenAboutWindow(object sender, RoutedEventArgs e) => await AboutWindow.Show();
public void CloseWindow(object sender, RoutedEventArgs e) => Window.Close(); public void CloseWindow(object sender, RoutedEventArgs e) => Window.Close();

View File

@ -29,7 +29,7 @@
Margin="5" Margin="5"
VerticalAlignment="Center" VerticalAlignment="Center"
IsVisible="{Binding EnableNonGameRunningControls}"> IsVisible="{Binding EnableNonGameRunningControls}">
<Grid Margin="0" ColumnDefinitions="Auto,Auto,*"> <Grid Margin="0" ColumnDefinitions="Auto,Auto,Auto,*">
<Button <Button
Width="25" Width="25"
Height="25" Height="25"
@ -50,9 +50,18 @@
VerticalAlignment="Center" VerticalAlignment="Center"
IsVisible="{Binding EnableNonGameRunningControls}" IsVisible="{Binding EnableNonGameRunningControls}"
Text="{ext:Locale StatusBarGamesLoaded}" /> Text="{ext:Locale StatusBarGamesLoaded}" />
<TextBlock
Name="StatusBarProgressStatus"
Grid.Column="2"
MinWidth="200"
Margin="10,0,5,0"
VerticalAlignment="Center"
IsVisible="{Binding StatusBarProgressStatusVisible}"
Text="{Binding StatusBarProgressStatusText}" />
<ProgressBar <ProgressBar
Name="LoadProgressBar" Name="LoadProgressBar"
Grid.Column="2" Grid.Column="3"
MinWidth="200"
Height="6" Height="6"
VerticalAlignment="Center" VerticalAlignment="Center"
Foreground="{DynamicResource SystemAccentColorLight2}" Foreground="{DynamicResource SystemAccentColorLight2}"

View File

@ -63,8 +63,7 @@ namespace Ryujinx.Ava.UI.Views.User
private async void Import_OnClick(object sender, RoutedEventArgs e) private async void Import_OnClick(object sender, RoutedEventArgs e)
{ {
var window = this.GetVisualRoot() as Window; var result = await ((Window)this.GetVisualRoot()!).StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
var result = await window.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{ {
AllowMultiple = false, AllowMultiple = false,
FileTypeFilter = new List<FilePickerFileType> FileTypeFilter = new List<FilePickerFileType>

View File

@ -28,6 +28,7 @@ using Ryujinx.UI.Common.Configuration;
using Ryujinx.UI.Common.Helper; using Ryujinx.UI.Common.Helper;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq; using System.Reactive.Linq;
using System.Runtime.Versioning; using System.Runtime.Versioning;
using System.Threading; using System.Threading;
@ -349,12 +350,12 @@ namespace Ryujinx.Ava.UI.Windows
await Dispatcher.UIThread.InvokeAsync(async () => await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys)); await Dispatcher.UIThread.InvokeAsync(async () => await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys));
} }
if (ConfigurationState.Instance.CheckUpdatesOnStart && Updater.CanUpdate(false)) if (ConfigurationState.Instance.CheckUpdatesOnStart && Updater.CanUpdate())
{ {
await Updater.BeginParse(this, false).ContinueWith(task => await this.BeginUpdateAsync()
{ .ContinueWith(
Logger.Error?.Print(LogClass.Application, $"Updater Error: {task.Exception}"); task => Logger.Error?.Print(LogClass.Application, $"Updater Error: {task.Exception}"),
}, TaskContinuationOptions.OnlyOnFaulted); TaskContinuationOptions.OnlyOnFaulted);
} }
} }
@ -394,30 +395,17 @@ namespace Ryujinx.Ava.UI.Windows
Arrange(new Rect(savedPoint.X, savedPoint.Y, ViewModel.WindowWidth, ViewModel.WindowHeight)); Arrange(new Rect(savedPoint.X, savedPoint.Y, ViewModel.WindowWidth, ViewModel.WindowHeight));
if (CheckScreenBounds(savedPoint)) if (Screens.All.Any(screen => screen.Bounds.Contains(savedPoint)))
{ {
Position = savedPoint; Position = savedPoint;
} }
else else
{ {
Logger.Warning?.Print(LogClass.Application, "Failed to find valid start-up coordinates. Defaulting to primary monitor center.");
WindowStartupLocation = WindowStartupLocation.CenterScreen; WindowStartupLocation = WindowStartupLocation.CenterScreen;
} }
} }
private bool CheckScreenBounds(PixelPoint configPoint)
{
for (int i = 0; i < Screens.ScreenCount; i++)
{
if (Screens.All[i].Bounds.Contains(configPoint))
{
return true;
}
}
Logger.Warning?.Print(LogClass.Application, "Failed to find valid start-up coordinates. Defaulting to primary monitor center.");
return false;
}
private void SaveWindowSizePosition() private void SaveWindowSizePosition()
{ {
ConfigurationState.Instance.UI.WindowStartup.WindowMaximized.Value = WindowState == WindowState.Maximized; ConfigurationState.Instance.UI.WindowStartup.WindowMaximized.Value = WindowState == WindowState.Maximized;
@ -509,8 +497,7 @@ namespace Ryujinx.Ava.UI.Windows
private void VolumeStatus_CheckedChanged(object sender, RoutedEventArgs e) private void VolumeStatus_CheckedChanged(object sender, RoutedEventArgs e)
{ {
var volumeSplitButton = sender as ToggleSplitButton; if (ViewModel.IsGameRunning && sender is ToggleSplitButton volumeSplitButton)
if (ViewModel.IsGameRunning)
{ {
if (!volumeSplitButton.IsChecked) if (!volumeSplitButton.IsChecked)
{ {

View File

@ -0,0 +1,354 @@
<UserControl
x:Class="Ryujinx.Ava.UI.Windows.XCITrimmerWindow"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
xmlns:models="clr-namespace:Ryujinx.UI.Common.Models;assembly=Ryujinx.UI.Common"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
Width="700"
Height="600"
x:DataType="viewModels:XCITrimmerViewModel"
Focusable="True"
mc:Ignorable="d">
<UserControl.Resources>
<helpers:XCITrimmerFileStatusConverter x:Key="StatusLabel" />
<helpers:XCITrimmerFileStatusDetailConverter x:Key="StatusDetailLabel" />
<helpers:XCITrimmerFileSpaceSavingsConverter x:Key="SpaceSavingsLabel" />
</UserControl.Resources>
<Grid Margin="20 0 20 0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Panel
Margin="10 10 10 10"
Grid.Row="0">
<TextBlock Text="{Binding Status}" />
</Panel>
<Panel
Margin="0 0 10 10"
IsVisible="{Binding !Processing}"
Grid.Row="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel
Grid.Column="0"
Orientation="Horizontal">
<TextBlock
Margin="10,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="{ext:Locale CommonSort}" />
<DropDownButton
Width="150"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Content="{Binding SortingFieldName}">
<DropDownButton.Flyout>
<Flyout Placement="Bottom">
<StackPanel
Margin="0"
HorizontalAlignment="Stretch"
Orientation="Vertical">
<StackPanel>
<RadioButton
Checked="Sort_Checked"
Content="{ext:Locale XCITrimmerSortName}"
GroupName="Sort"
IsChecked="{Binding IsSortedByName, Mode=OneTime}"
Tag="Name" />
<RadioButton
Checked="Sort_Checked"
Content="{ext:Locale XCITrimmerSortSaved}"
GroupName="Sort"
IsChecked="{Binding IsSortedBySaved, Mode=OneTime}"
Tag="Saved" />
</StackPanel>
<Border
Width="60"
Height="2"
Margin="5"
HorizontalAlignment="Stretch"
BorderBrush="White"
BorderThickness="0,1,0,0">
<Separator Height="0" HorizontalAlignment="Stretch" />
</Border>
<RadioButton
Checked="Order_Checked"
Content="{ext:Locale OrderAscending}"
GroupName="Order"
IsChecked="{Binding SortingAscending, Mode=OneTime}"
Tag="Ascending" />
<RadioButton
Checked="Order_Checked"
Content="{ext:Locale OrderDescending}"
GroupName="Order"
IsChecked="{Binding !SortingAscending, Mode=OneTime}"
Tag="Descending" />
</StackPanel>
</Flyout>
</DropDownButton.Flyout>
</DropDownButton>
</StackPanel>
<TextBox
Grid.Column="1"
MinHeight="29"
MaxHeight="29"
Margin="5 0 5 0"
HorizontalAlignment="Stretch"
Watermark="{ext:Locale Search}"
Text="{Binding Search}" />
<StackPanel
Grid.Column="2"
Orientation="Horizontal">
<Button
Name="SelectDisplayedButton"
MinWidth="90"
Margin="5"
Command="{Binding SelectDisplayed}">
<TextBlock Text="{ext:Locale XCITrimmerSelectDisplayed}" />
</Button>
<Button
Name="DeselectDisplayedButton"
MinWidth="90"
Margin="5"
Command="{Binding DeselectDisplayed}">
<TextBlock Text="{ext:Locale XCITrimmerDeselectDisplayed}" />
</Button>
</StackPanel>
</Grid>
</Panel>
<Border
Grid.Row="2"
Margin="0 0 0 10"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
BorderBrush="{DynamicResource AppListHoverBackgroundColor}"
BorderThickness="1"
CornerRadius="5"
Padding="2.5">
<ListBox
AutoScrollToSelectedItem="{Binding Processing}"
SelectedItem="{Binding ProcessingApplication.Value}"
SelectionMode="Multiple, Toggle"
Background="Transparent"
SelectionChanged="OnSelectionChanged"
SelectedItems="{Binding SelectedDisplayedXCIFiles, Mode=OneWay}"
ItemsSource="{Binding DisplayedXCIFiles}"
IsEnabled="{Binding !Processing}">
<ListBox.DataTemplates>
<DataTemplate
DataType="models:XCITrimmerFileModel">
<Panel Margin="10">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="65*" />
<ColumnDefinition Width="35*" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
Margin="10 0 10 0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
MaxLines="2"
TextWrapping="Wrap"
TextTrimming="CharacterEllipsis"
Text="{Binding Name}">
</TextBlock>
<Grid Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="45*" />
<ColumnDefinition Width="55*" />
</Grid.ColumnDefinitions>
<ProgressBar
Height="10"
Margin="10 0 10 0"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
CornerRadius="5"
IsVisible="{Binding $parent[UserControl].((viewModels:XCITrimmerViewModel)DataContext).Processing}"
Maximum="100"
Minimum="0"
Value="{Binding PercentageProgress}" />
<TextBlock
Grid.Column="0"
Margin="10 0 10 0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
MaxLines="1"
Text="{Binding ., Converter={StaticResource StatusLabel}}">
<ToolTip.Tip>
<StackPanel
IsVisible="{Binding IsFailed}">
<TextBlock
Classes="h1"
Text="{ext:Locale XCITrimmerTitleStatusFailed}" />
<TextBlock
Text="{Binding ., Converter={StaticResource StatusDetailLabel}}"
MaxLines="5"
MaxWidth="200"
MaxHeight="100"
TextTrimming="None"
TextWrapping="Wrap"/>
</StackPanel>
</ToolTip.Tip>
</TextBlock>
<TextBlock
Grid.Column="1"
Margin="10 0 10 0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
MaxLines="1"
Text="{Binding ., Converter={StaticResource SpaceSavingsLabel}}">>
</TextBlock>
</Grid>
</Grid>
</Panel>
</DataTemplate>
</ListBox.DataTemplates>
<ListBox.Styles>
<Style Selector="ListBoxItem">
<Setter Property="Background" Value="Transparent" />
</Style>
</ListBox.Styles>
</ListBox>
</Border>
<Border
Grid.Row="3"
Margin="0 0 0 10"
HorizontalAlignment="Stretch"
BorderBrush="{DynamicResource AppListHoverBackgroundColor}"
BorderThickness="1"
CornerRadius="5"
Padding="2.5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock
Grid.Column="0"
Grid.Row="0"
Classes="h1"
Margin="5"
HorizontalAlignment="Right"
VerticalAlignment="Center"
MaxLines="1"
Text="{ext:Locale XCITrimmerPotentialSavings}" />
<TextBlock
Grid.Column="0"
Grid.Row="1"
Classes="h1"
Margin="5"
HorizontalAlignment="Right"
VerticalAlignment="Center"
MaxLines="1"
Text="{ext:Locale XCITrimmerActualSavings}" />
<TextBlock
Grid.Column="1"
Grid.Row="0"
Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
MaxLines="1"
Text="{Binding PotentialSavings}" />
<TextBlock
Grid.Column="1"
Grid.Row="1"
Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
MaxLines="1"
Text="{Binding ActualSavings}" />
</Grid>
</Border>
<Panel
Grid.Row="4"
HorizontalAlignment="Stretch">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel
Grid.Column="0"
Orientation="Horizontal"
Spacing="10"
HorizontalAlignment="Left">
<Button
Name="TrimButton"
MinWidth="90"
Margin="5"
Click="Trim"
IsEnabled="{Binding CanTrim}">
<TextBlock Text="Trim" />
</Button>
<Button
Name="UntrimButton"
MinWidth="90"
Margin="5"
Click="Untrim"
IsEnabled="{Binding CanUntrim}">
<TextBlock Text="Untrim" />
</Button>
</StackPanel>
<StackPanel
Grid.Column="1"
Orientation="Horizontal"
Spacing="10"
HorizontalAlignment="Right">
<Button
Name="CancellingButton"
MinWidth="90"
Margin="5"
Click="Cancel"
IsEnabled="False">
<Button.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="Processing" />
<Binding Path="Cancel" />
</MultiBinding>
</Button.IsVisible>
<TextBlock Text="{ext:Locale InputDialogCancelling}" />
</Button>
<Button
Name="CancelButton"
MinWidth="90"
Margin="5"
Click="Cancel">
<Button.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="Processing" />
<Binding Path="!Cancel" />
</MultiBinding>
</Button.IsVisible>
<TextBlock Text="{ext:Locale InputDialogCancel}" />
</Button>
<Button
Name="CloseButton"
MinWidth="90"
Margin="5"
Click="Close"
IsVisible="{Binding !Processing}">
<TextBlock Text="{ext:Locale InputDialogClose}" />
</Button>
</StackPanel>
</Grid>
</Panel>
</Grid>
</UserControl>

View File

@ -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<Grid>().Name("DialogSpace").Child().OfType<Border>());
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<XCITrimmerViewModel.SortField>(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);
}
}
}
}
}

View File

@ -32,6 +32,8 @@ namespace Ryujinx.Ava
internal static class Updater internal static class Updater
{ {
private const string GitHubApiUrl = "https://api.github.com"; 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 GithubReleasesJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
private static readonly string _homeDir = AppDomain.CurrentDomain.BaseDirectory; private static readonly string _homeDir = AppDomain.CurrentDomain.BaseDirectory;
@ -46,9 +48,9 @@ namespace Ryujinx.Ava
private static bool _updateSuccessful; private static bool _updateSuccessful;
private static bool _running; private static bool _running;
private static readonly string[] _windowsDependencyDirs = Array.Empty<string>(); 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) if (_running)
{ {
@ -97,8 +99,7 @@ namespace Ryujinx.Ava
{ {
using HttpClient jsonClient = ConstructHttpClient(); using HttpClient jsonClient = ConstructHttpClient();
string buildInfoUrl = $"{GitHubApiUrl}/repos/{ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelRepo}/releases/latest"; string fetchedJson = await jsonClient.GetStringAsync(LatestReleaseUrl);
string fetchedJson = await jsonClient.GetStringAsync(buildInfoUrl);
var fetched = JsonHelper.Deserialize(fetchedJson, _serializerContext.GithubReleasesJsonResponse); var fetched = JsonHelper.Deserialize(fetchedJson, _serializerContext.GithubReleasesJsonResponse);
_buildVer = fetched.Name; _buildVer = fetched.Name;
@ -159,7 +160,7 @@ namespace Ryujinx.Ava
} }
catch 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( await ContentDialogHelper.CreateWarningDialog(
LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedGithubMessage], LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedGithubMessage],
@ -636,7 +637,7 @@ namespace Ryujinx.Ava
taskDialog.Hide(); taskDialog.Hide();
} }
public static bool CanUpdate(bool showWarnings) public static bool CanUpdate(bool showWarnings = false)
{ {
#if !DISABLE_UPDATER #if !DISABLE_UPDATER
if (!NetworkInterface.GetIsNetworkAvailable()) if (!NetworkInterface.GetIsNetworkAvailable())