Compare commits
3 Commits
refactor/a
...
52ae6a0b26
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52ae6a0b26 | ||
|
|
1d80749526 | ||
|
|
fa4102a803 |
23
.github/workflows/build.yml
vendored
23
.github/workflows/build.yml
vendored
@@ -64,9 +64,14 @@ jobs:
|
||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -o ./publish -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx --self-contained
|
||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
|
||||
|
||||
- name: Publish Ryujinx.Headless.SDL2
|
||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Headless.SDL2 --self-contained
|
||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
|
||||
|
||||
- name: Set executable bit
|
||||
run: |
|
||||
chmod +x ./publish/Ryujinx ./publish/Ryujinx.sh
|
||||
chmod +x ./publish_sdl2_headless/Ryujinx.Headless.SDL2 ./publish_sdl2_headless/Ryujinx.sh
|
||||
if: github.event_name == 'pull_request' && matrix.platform.os == 'ubuntu-latest'
|
||||
|
||||
- name: Build AppImage
|
||||
@@ -114,6 +119,13 @@ jobs:
|
||||
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}-AppImage
|
||||
path: publish_appimage
|
||||
|
||||
- name: Upload Ryujinx.Headless.SDL2 artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: nogui-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}
|
||||
path: publish_sdl2_headless
|
||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
|
||||
|
||||
build_macos:
|
||||
name: macOS Universal (${{ matrix.configuration }})
|
||||
runs-on: ubuntu-latest
|
||||
@@ -159,9 +171,20 @@ jobs:
|
||||
run: |
|
||||
./distribution/macos/create_macos_build_ava.sh . publish_tmp publish ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
|
||||
|
||||
- name: Publish macOS Ryujinx.Headless.SDL2
|
||||
run: |
|
||||
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
|
||||
|
||||
- name: Upload Ryujinx artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
|
||||
path: "publish/*.tar.gz"
|
||||
if: github.event_name == 'pull_request'
|
||||
|
||||
- name: Upload Ryujinx.Headless.SDL2 artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: nogui-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
|
||||
path: "publish_headless/*.tar.gz"
|
||||
if: github.event_name == 'pull_request'
|
||||
|
||||
20
.github/workflows/canary.yml
vendored
20
.github/workflows/canary.yml
vendored
@@ -104,6 +104,7 @@ jobs:
|
||||
- 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
|
||||
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --self-contained
|
||||
|
||||
- name: Packing Windows builds
|
||||
if: matrix.platform.os == 'windows-latest'
|
||||
@@ -112,6 +113,11 @@ jobs:
|
||||
rm publish/libarmeilleure-jitsupport.dylib
|
||||
7z a ../release_output/ryujinx-canary-${{ 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/nogui-ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish
|
||||
popd
|
||||
shell: bash
|
||||
|
||||
- name: Packing Linux builds
|
||||
@@ -122,6 +128,12 @@ jobs:
|
||||
chmod +x publish/Ryujinx.sh publish/Ryujinx
|
||||
tar -czvf ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish
|
||||
popd
|
||||
|
||||
pushd publish_sdl2_headless
|
||||
rm publish/libarmeilleure-jitsupport.dylib
|
||||
chmod +x publish/Ryujinx.sh publish/Ryujinx.Headless.SDL2
|
||||
tar -czvf ../release_output/nogui-ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish
|
||||
popd
|
||||
shell: bash
|
||||
|
||||
#- name: Build AppImage (Linux)
|
||||
@@ -167,7 +179,7 @@ jobs:
|
||||
with:
|
||||
name: ${{ steps.version_info.outputs.build_version }}
|
||||
artifacts: "release_output/*.tar.gz,release_output/*.zip"
|
||||
#artifacts: "release_output/*.tar.gz,release_output/*.zip,release_output/*AppImage*"
|
||||
#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
|
||||
@@ -226,11 +238,15 @@ jobs:
|
||||
run: |
|
||||
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish_ava ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 1
|
||||
|
||||
- name: Publish macOS Ryujinx.Headless.SDL2
|
||||
run: |
|
||||
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 1
|
||||
|
||||
- name: Pushing new release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
name: "Canary ${{ steps.version_info.outputs.build_version }}"
|
||||
artifacts: "publish_ava/*.tar.gz"
|
||||
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
|
||||
|
||||
5
.github/workflows/nightly_pr_comment.yml
vendored
5
.github/workflows/nightly_pr_comment.yml
vendored
@@ -38,15 +38,20 @@ jobs:
|
||||
return core.error(`No artifacts found`);
|
||||
}
|
||||
let body = `Download the artifacts for this pull request:\n`;
|
||||
let hidden_headless_artifacts = `\n\n <details><summary>GUI-less</summary>\n`;
|
||||
let hidden_debug_artifacts = `\n\n <details><summary>Only for Developers</summary>\n`;
|
||||
for (const art of artifacts) {
|
||||
if(art.name.includes('Debug')) {
|
||||
hidden_debug_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
|
||||
} else if(art.name.includes('nogui-ryujinx')) {
|
||||
hidden_headless_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
|
||||
} else {
|
||||
body += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
|
||||
}
|
||||
}
|
||||
hidden_headless_artifacts += `\n</details>`;
|
||||
hidden_debug_artifacts += `\n</details>`;
|
||||
body += hidden_headless_artifacts;
|
||||
body += hidden_debug_artifacts;
|
||||
|
||||
const {data: comments} = await github.rest.issues.listComments({repo, owner, issue_number});
|
||||
|
||||
17
.github/workflows/release.yml
vendored
17
.github/workflows/release.yml
vendored
@@ -103,6 +103,7 @@ jobs:
|
||||
- name: Publish
|
||||
run: |
|
||||
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained
|
||||
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --self-contained
|
||||
|
||||
- name: Packing Windows builds
|
||||
if: matrix.platform.os == 'windows-latest'
|
||||
@@ -111,6 +112,11 @@ jobs:
|
||||
rm 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 libarmeilleure-jitsupport.dylib
|
||||
7z a ../release_output/nogui-ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
|
||||
popd
|
||||
shell: bash
|
||||
|
||||
- name: Build AppImage (Linux)
|
||||
@@ -157,6 +163,11 @@ jobs:
|
||||
chmod +x Ryujinx.sh Ryujinx
|
||||
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
|
||||
popd
|
||||
|
||||
pushd publish_sdl2_headless
|
||||
chmod +x Ryujinx.sh Ryujinx.Headless.SDL2
|
||||
tar -czvf ../release_output/nogui-ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
|
||||
popd
|
||||
shell: bash
|
||||
|
||||
- name: Pushing new release
|
||||
@@ -222,11 +233,15 @@ jobs:
|
||||
run: |
|
||||
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0
|
||||
|
||||
- name: Publish macOS Ryujinx.Headless.SDL2
|
||||
run: |
|
||||
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0
|
||||
|
||||
- name: Pushing new release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
name: ${{ steps.version_info.outputs.build_version }}
|
||||
artifacts: "publish/*.tar.gz"
|
||||
artifacts: "publish/*.tar.gz, publish_headless/*.tar.gz"
|
||||
tag: ${{ steps.version_info.outputs.build_version }}
|
||||
body: "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}"
|
||||
omitBodyDuringUpdate: true
|
||||
|
||||
@@ -57,6 +57,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.SDL2.Common", "src\
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL2", "src\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj", "{D99A395A-8569-4DB0-B336-900647890052}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Headless.SDL2", "src\Ryujinx.Headless.SDL2\Ryujinx.Headless.SDL2.csproj", "{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec.FFmpeg", "src\Ryujinx.Graphics.Nvdec.FFmpeg\Ryujinx.Graphics.Nvdec.FFmpeg.csproj", "{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "src\Ryujinx\Ryujinx.csproj", "{7C1B2721-13DA-4B62-B046-C626605ECCE6}"
|
||||
@@ -202,6 +204,10 @@ Global
|
||||
{D99A395A-8569-4DB0-B336-900647890052}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
||||
@@ -4,7 +4,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
|
||||
@@ -158,16 +157,21 @@ namespace Ryujinx.Common.Logging
|
||||
_time.Restart();
|
||||
}
|
||||
|
||||
private static ILogTarget GetTarget(string targetName)
|
||||
=> _logTargets.FirstOrDefault(target => target.Name.Equals(targetName));
|
||||
private static ILogTarget GetTarget(string targetName)
|
||||
{
|
||||
foreach (var target in _logTargets)
|
||||
{
|
||||
if (target.Name.Equals(targetName))
|
||||
{
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void AddTarget(ILogTarget target)
|
||||
{
|
||||
if (_logTargets.Any(t => t.Name == target.Name))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_logTargets.Add(target);
|
||||
|
||||
Updated += target.Log;
|
||||
|
||||
@@ -27,7 +27,11 @@ namespace Ryujinx.Common.Logging.Targets
|
||||
|
||||
private readonly int _overflowTimeout;
|
||||
|
||||
string ILogTarget.Name => _target.Name;
|
||||
string ILogTarget.Name { get => _target.Name; }
|
||||
|
||||
public AsyncLogTargetWrapper(ILogTarget target)
|
||||
: this(target, -1)
|
||||
{ }
|
||||
|
||||
public AsyncLogTargetWrapper(ILogTarget target, int queueLimit = -1, AsyncLogTargetOverflowAction overflowAction = AsyncLogTargetOverflowAction.Block)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using Gommon;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Utilities;
|
||||
@@ -7,13 +6,12 @@ using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Account.Acc
|
||||
{
|
||||
public class AccountSaveDataManager
|
||||
class AccountSaveDataManager
|
||||
{
|
||||
private static readonly string _profilesJsonPath = Path.Join(AppDataManager.BaseDirPath, "system", "Profiles.json");
|
||||
private readonly string _profilesJsonPath = Path.Join(AppDataManager.BaseDirPath, "system", "Profiles.json");
|
||||
|
||||
private static readonly ProfilesJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||
|
||||
@@ -51,16 +49,6 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
|
||||
}
|
||||
}
|
||||
|
||||
public static Optional<UserProfile> GetLastUsedUser()
|
||||
{
|
||||
ProfilesJson profilesJson = JsonHelper.DeserializeFromFile(_profilesJsonPath, _serializerContext.ProfilesJson);
|
||||
|
||||
return profilesJson.Profiles
|
||||
.FindFirst(profile => profile.AccountState == AccountState.Open)
|
||||
.Convert(profileJson => new UserProfile(new UserId(profileJson.UserId), profileJson.Name,
|
||||
profileJson.Image, profileJson.LastModifiedTimestamp));
|
||||
}
|
||||
|
||||
public void Save(ConcurrentDictionary<string, UserProfile> profiles)
|
||||
{
|
||||
ProfilesJson profilesJson = new()
|
||||
|
||||
@@ -2,7 +2,7 @@ using Ryujinx.HLE.UI;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Headless
|
||||
namespace Ryujinx.Headless.SDL2
|
||||
{
|
||||
/// <summary>
|
||||
/// Headless text processing class, right now there is no way to forward the input to it.
|
||||
@@ -1,6 +1,6 @@
|
||||
using Ryujinx.HLE.UI;
|
||||
|
||||
namespace Ryujinx.Headless
|
||||
namespace Ryujinx.Headless.SDL2
|
||||
{
|
||||
internal class HeadlessHostUiTheme : IHostUITheme
|
||||
{
|
||||
@@ -7,7 +7,7 @@ using Ryujinx.Input.HLE;
|
||||
using System;
|
||||
using static SDL2.SDL;
|
||||
|
||||
namespace Ryujinx.Headless
|
||||
namespace Ryujinx.Headless.SDL2.OpenGL
|
||||
{
|
||||
class OpenGLWindow : WindowBase
|
||||
{
|
||||
@@ -1,168 +1,13 @@
|
||||
using CommandLine;
|
||||
using Gommon;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.HLE;
|
||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||
using Ryujinx.HLE.HOS.SystemState;
|
||||
using Ryujinx.UI.Common.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Ryujinx.Headless
|
||||
namespace Ryujinx.Headless.SDL2
|
||||
{
|
||||
public class Options
|
||||
{
|
||||
public void InheritMainConfig(string[] originalArgs, ConfigurationState configurationState, out bool needsProfileSet)
|
||||
{
|
||||
needsProfileSet = NeedsOverride(nameof(UserProfile));
|
||||
|
||||
if (NeedsOverride(nameof(IsFullscreen)))
|
||||
IsFullscreen = configurationState.UI.StartFullscreen;
|
||||
|
||||
if (NeedsOverride(nameof(EnableKeyboard)))
|
||||
EnableKeyboard = configurationState.Hid.EnableKeyboard;
|
||||
|
||||
if (NeedsOverride(nameof(EnableMouse)))
|
||||
EnableMouse = configurationState.Hid.EnableMouse;
|
||||
|
||||
if (NeedsOverride(nameof(HideCursorMode)))
|
||||
HideCursorMode = configurationState.HideCursor;
|
||||
|
||||
if (NeedsOverride(nameof(DisablePTC)))
|
||||
DisablePTC = !configurationState.System.EnablePtc;
|
||||
|
||||
if (NeedsOverride(nameof(EnableInternetAccess)))
|
||||
EnableInternetAccess = configurationState.System.EnableInternetAccess;
|
||||
|
||||
if (NeedsOverride(nameof(DisableFsIntegrityChecks)))
|
||||
DisableFsIntegrityChecks = configurationState.System.EnableFsIntegrityChecks;
|
||||
|
||||
if (NeedsOverride(nameof(FsGlobalAccessLogMode)))
|
||||
FsGlobalAccessLogMode = configurationState.System.FsGlobalAccessLogMode;
|
||||
|
||||
if (NeedsOverride(nameof(VSyncMode)))
|
||||
VSyncMode = configurationState.Graphics.VSyncMode;
|
||||
|
||||
if (NeedsOverride(nameof(CustomVSyncInterval)))
|
||||
CustomVSyncInterval = configurationState.Graphics.CustomVSyncInterval;
|
||||
|
||||
if (NeedsOverride(nameof(DisableShaderCache)))
|
||||
DisableShaderCache = !configurationState.Graphics.EnableShaderCache;
|
||||
|
||||
if (NeedsOverride(nameof(EnableTextureRecompression)))
|
||||
EnableTextureRecompression = configurationState.Graphics.EnableTextureRecompression;
|
||||
|
||||
if (NeedsOverride(nameof(DisableDockedMode)))
|
||||
DisableDockedMode = !configurationState.System.EnableDockedMode;
|
||||
|
||||
if (NeedsOverride(nameof(SystemLanguage)))
|
||||
SystemLanguage = (SystemLanguage)(int)configurationState.System.Language.Value;
|
||||
|
||||
if (NeedsOverride(nameof(SystemRegion)))
|
||||
SystemRegion = (RegionCode)(int)configurationState.System.Region.Value;
|
||||
|
||||
if (NeedsOverride(nameof(SystemTimeZone)))
|
||||
SystemTimeZone = configurationState.System.TimeZone;
|
||||
|
||||
if (NeedsOverride(nameof(SystemTimeOffset)))
|
||||
SystemTimeOffset = configurationState.System.SystemTimeOffset;
|
||||
|
||||
if (NeedsOverride(nameof(MemoryManagerMode)))
|
||||
MemoryManagerMode = configurationState.System.MemoryManagerMode;
|
||||
|
||||
if (NeedsOverride(nameof(AudioVolume)))
|
||||
AudioVolume = configurationState.System.AudioVolume;
|
||||
|
||||
if (NeedsOverride(nameof(UseHypervisor)) && OperatingSystem.IsMacOS())
|
||||
UseHypervisor = configurationState.System.UseHypervisor;
|
||||
|
||||
if (NeedsOverride(nameof(MultiplayerLanInterfaceId)))
|
||||
MultiplayerLanInterfaceId = configurationState.Multiplayer.LanInterfaceId;
|
||||
|
||||
if (NeedsOverride(nameof(DisableFileLog)))
|
||||
DisableFileLog = !configurationState.Logger.EnableFileLog;
|
||||
|
||||
if (NeedsOverride(nameof(LoggingEnableDebug)))
|
||||
LoggingEnableDebug = configurationState.Logger.EnableDebug;
|
||||
|
||||
if (NeedsOverride(nameof(LoggingDisableStub)))
|
||||
LoggingDisableStub = !configurationState.Logger.EnableStub;
|
||||
|
||||
if (NeedsOverride(nameof(LoggingDisableInfo)))
|
||||
LoggingDisableInfo = !configurationState.Logger.EnableInfo;
|
||||
|
||||
if (NeedsOverride(nameof(LoggingDisableWarning)))
|
||||
LoggingDisableWarning = !configurationState.Logger.EnableWarn;
|
||||
|
||||
if (NeedsOverride(nameof(LoggingDisableError)))
|
||||
LoggingDisableError = !configurationState.Logger.EnableError;
|
||||
|
||||
if (NeedsOverride(nameof(LoggingEnableTrace)))
|
||||
LoggingEnableTrace = configurationState.Logger.EnableTrace;
|
||||
|
||||
if (NeedsOverride(nameof(LoggingDisableGuest)))
|
||||
LoggingDisableGuest = !configurationState.Logger.EnableGuest;
|
||||
|
||||
if (NeedsOverride(nameof(LoggingEnableFsAccessLog)))
|
||||
LoggingEnableFsAccessLog = configurationState.Logger.EnableFsAccessLog;
|
||||
|
||||
if (NeedsOverride(nameof(LoggingGraphicsDebugLevel)))
|
||||
LoggingGraphicsDebugLevel = configurationState.Logger.GraphicsDebugLevel;
|
||||
|
||||
if (NeedsOverride(nameof(ResScale)))
|
||||
ResScale = configurationState.Graphics.ResScale;
|
||||
|
||||
if (NeedsOverride(nameof(MaxAnisotropy)))
|
||||
MaxAnisotropy = configurationState.Graphics.MaxAnisotropy;
|
||||
|
||||
if (NeedsOverride(nameof(AspectRatio)))
|
||||
AspectRatio = configurationState.Graphics.AspectRatio;
|
||||
|
||||
if (NeedsOverride(nameof(BackendThreading)))
|
||||
BackendThreading = configurationState.Graphics.BackendThreading;
|
||||
|
||||
if (NeedsOverride(nameof(DisableMacroHLE)))
|
||||
DisableMacroHLE = !configurationState.Graphics.EnableMacroHLE;
|
||||
|
||||
if (NeedsOverride(nameof(GraphicsShadersDumpPath)))
|
||||
GraphicsShadersDumpPath = configurationState.Graphics.ShadersDumpPath;
|
||||
|
||||
if (NeedsOverride(nameof(GraphicsBackend)))
|
||||
GraphicsBackend = configurationState.Graphics.GraphicsBackend;
|
||||
|
||||
if (NeedsOverride(nameof(AntiAliasing)))
|
||||
AntiAliasing = configurationState.Graphics.AntiAliasing;
|
||||
|
||||
if (NeedsOverride(nameof(ScalingFilter)))
|
||||
ScalingFilter = configurationState.Graphics.ScalingFilter;
|
||||
|
||||
if (NeedsOverride(nameof(ScalingFilterLevel)))
|
||||
ScalingFilterLevel = configurationState.Graphics.ScalingFilterLevel;
|
||||
|
||||
if (NeedsOverride(nameof(DramSize)))
|
||||
DramSize = configurationState.System.DramSize;
|
||||
|
||||
if (NeedsOverride(nameof(IgnoreMissingServices)))
|
||||
IgnoreMissingServices = configurationState.System.IgnoreMissingServices;
|
||||
|
||||
if (NeedsOverride(nameof(IgnoreControllerApplet)))
|
||||
IgnoreControllerApplet = configurationState.IgnoreApplet;
|
||||
|
||||
return;
|
||||
|
||||
bool NeedsOverride(string argKey) => originalArgs.None(arg => arg.TrimStart('-').EqualsIgnoreCase(OptionName(argKey)));
|
||||
|
||||
string OptionName(string propertyName) =>
|
||||
typeof(Options)!.GetProperty(propertyName)!.GetCustomAttribute<OptionAttribute>()!.LongName;
|
||||
}
|
||||
|
||||
// General
|
||||
|
||||
[Option("use-main-config", Required = false, Default = false, HelpText = "Use the settings from what was configured via the UI.")]
|
||||
public bool InheritConfig { get; set; }
|
||||
|
||||
[Option("root-data-dir", Required = false, HelpText = "Set the custom folder path for Ryujinx data.")]
|
||||
public string BaseDataDir { get; set; }
|
||||
@@ -327,7 +172,7 @@ namespace Ryujinx.Headless
|
||||
public bool LoggingDisableWarning { get; set; }
|
||||
|
||||
[Option("disable-error-logs", Required = false, HelpText = "Disables printing error log messages.")]
|
||||
public bool LoggingDisableError { get; set; }
|
||||
public bool LoggingEnableError { get; set; }
|
||||
|
||||
[Option("enable-trace-logs", Required = false, Default = false, HelpText = "Enables printing trace log messages.")]
|
||||
public bool LoggingEnableTrace { get; set; }
|
||||
@@ -1,9 +1,13 @@
|
||||
using CommandLine;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava;
|
||||
using LibHac.Tools.FsSystem;
|
||||
using Ryujinx.Audio.Backends.SDL2;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
||||
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
||||
using Ryujinx.Common.GraphicsDriver;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Logging.Targets;
|
||||
@@ -11,9 +15,14 @@ using Ryujinx.Common.SystemInterop;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.Cpu;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.GAL.Multithreading;
|
||||
using Ryujinx.Graphics.Gpu;
|
||||
using Ryujinx.Graphics.Gpu.Shader;
|
||||
using Ryujinx.Graphics.OpenGL;
|
||||
using Ryujinx.Graphics.Vulkan;
|
||||
using Ryujinx.Graphics.Vulkan.MoltenVK;
|
||||
using Ryujinx.Headless.SDL2.OpenGL;
|
||||
using Ryujinx.Headless.SDL2.Vulkan;
|
||||
using Ryujinx.HLE;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
using Ryujinx.HLE.HOS;
|
||||
@@ -22,16 +31,22 @@ using Ryujinx.Input;
|
||||
using Ryujinx.Input.HLE;
|
||||
using Ryujinx.Input.SDL2;
|
||||
using Ryujinx.SDL2.Common;
|
||||
using Ryujinx.UI.Common.Configuration;
|
||||
using Silk.NET.Vulkan;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
|
||||
using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
|
||||
using Key = Ryujinx.Common.Configuration.Hid.Key;
|
||||
|
||||
namespace Ryujinx.Headless
|
||||
namespace Ryujinx.Headless.SDL2
|
||||
{
|
||||
public partial class HeadlessRyujinx
|
||||
class Program
|
||||
{
|
||||
public static string Version { get; private set; }
|
||||
|
||||
private static VirtualFileSystem _virtualFileSystem;
|
||||
private static ContentManager _contentManager;
|
||||
private static AccountManager _accountManager;
|
||||
@@ -41,18 +56,20 @@ namespace Ryujinx.Headless
|
||||
private static Switch _emulationContext;
|
||||
private static WindowBase _window;
|
||||
private static WindowsMultimediaTimerResolution _windowsMultimediaTimerResolution;
|
||||
private static List<InputConfig> _inputConfiguration = [];
|
||||
private static List<InputConfig> _inputConfiguration;
|
||||
private static bool _enableKeyboard;
|
||||
private static bool _enableMouse;
|
||||
|
||||
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||
|
||||
public static void Entrypoint(string[] args)
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Version = ReleaseInformation.Version;
|
||||
|
||||
// Make process DPI aware for proper window sizing on high-res screens.
|
||||
ForceDpiAware.Windows();
|
||||
|
||||
Console.Title = $"Ryujinx Console {Program.Version} (Headless)";
|
||||
Console.Title = $"Ryujinx Console {Version} (Headless SDL2)";
|
||||
|
||||
if (OperatingSystem.IsMacOS() || OperatingSystem.IsLinux())
|
||||
{
|
||||
@@ -80,7 +97,7 @@ namespace Ryujinx.Headless
|
||||
}
|
||||
|
||||
Parser.Default.ParseArguments<Options>(args)
|
||||
.WithParsed(options => Load(args, options))
|
||||
.WithParsed(Load)
|
||||
.WithNotParsed(errors =>
|
||||
{
|
||||
Logger.Error?.PrintMsg(LogClass.Application, "Error parsing command-line arguments:");
|
||||
@@ -88,81 +105,239 @@ namespace Ryujinx.Headless
|
||||
errors.ForEach(err => Logger.Error?.PrintMsg(LogClass.Application, $" - {err.Tag}"));
|
||||
});
|
||||
}
|
||||
|
||||
public static void ReloadConfig(string customConfigPath = null)
|
||||
|
||||
private static InputConfig HandlePlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index)
|
||||
{
|
||||
string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName);
|
||||
string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName);
|
||||
|
||||
string configurationPath = null;
|
||||
|
||||
// Now load the configuration as the other subsystems are now registered
|
||||
if (customConfigPath != null && File.Exists(customConfigPath))
|
||||
if (inputId == null)
|
||||
{
|
||||
configurationPath = customConfigPath;
|
||||
}
|
||||
else if (File.Exists(localConfigurationPath))
|
||||
{
|
||||
configurationPath = localConfigurationPath;
|
||||
}
|
||||
else if (File.Exists(appDataConfigurationPath))
|
||||
{
|
||||
configurationPath = appDataConfigurationPath;
|
||||
}
|
||||
|
||||
if (configurationPath == null)
|
||||
{
|
||||
// No configuration, we load the default values and save it to disk
|
||||
configurationPath = appDataConfigurationPath;
|
||||
Logger.Notice.Print(LogClass.Application, $"No configuration file found. Saving default configuration to: {configurationPath}");
|
||||
|
||||
ConfigurationState.Instance.LoadDefault();
|
||||
ConfigurationState.Instance.ToFileFormat().SaveConfig(configurationPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Notice.Print(LogClass.Application, $"Loading configuration from: {configurationPath}");
|
||||
|
||||
if (ConfigurationFileFormat.TryLoad(configurationPath, out ConfigurationFileFormat configurationFileFormat))
|
||||
if (index == PlayerIndex.Player1)
|
||||
{
|
||||
ConfigurationState.Instance.Load(configurationFileFormat, configurationPath);
|
||||
Logger.Info?.Print(LogClass.Application, $"{index} not configured, defaulting to default keyboard.");
|
||||
|
||||
// Default to keyboard
|
||||
inputId = "0";
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Warning?.PrintMsg(LogClass.Application, $"Failed to load config! Loading the default config instead.\nFailed config location: {configurationPath}");
|
||||
Logger.Info?.Print(LogClass.Application, $"{index} not configured");
|
||||
|
||||
ConfigurationState.Instance.LoadDefault();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
IGamepad gamepad = _inputManager.KeyboardDriver.GetGamepad(inputId);
|
||||
|
||||
bool isKeyboard = true;
|
||||
|
||||
if (gamepad == null)
|
||||
{
|
||||
gamepad = _inputManager.GamepadDriver.GetGamepad(inputId);
|
||||
isKeyboard = false;
|
||||
|
||||
if (gamepad == null)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"{index} gamepad not found (\"{inputId}\")");
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
string gamepadName = gamepad.Name;
|
||||
|
||||
gamepad.Dispose();
|
||||
|
||||
InputConfig config;
|
||||
|
||||
if (inputProfileName == null || inputProfileName.Equals("default"))
|
||||
{
|
||||
if (isKeyboard)
|
||||
{
|
||||
config = new StandardKeyboardInputConfig
|
||||
{
|
||||
Version = InputConfig.CurrentVersion,
|
||||
Backend = InputBackendType.WindowKeyboard,
|
||||
Id = null,
|
||||
ControllerType = ControllerType.JoyconPair,
|
||||
LeftJoycon = new LeftJoyconCommonConfig<Key>
|
||||
{
|
||||
DpadUp = Key.Up,
|
||||
DpadDown = Key.Down,
|
||||
DpadLeft = Key.Left,
|
||||
DpadRight = Key.Right,
|
||||
ButtonMinus = Key.Minus,
|
||||
ButtonL = Key.E,
|
||||
ButtonZl = Key.Q,
|
||||
ButtonSl = Key.Unbound,
|
||||
ButtonSr = Key.Unbound,
|
||||
},
|
||||
|
||||
LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
|
||||
{
|
||||
StickUp = Key.W,
|
||||
StickDown = Key.S,
|
||||
StickLeft = Key.A,
|
||||
StickRight = Key.D,
|
||||
StickButton = Key.F,
|
||||
},
|
||||
|
||||
RightJoycon = new RightJoyconCommonConfig<Key>
|
||||
{
|
||||
ButtonA = Key.Z,
|
||||
ButtonB = Key.X,
|
||||
ButtonX = Key.C,
|
||||
ButtonY = Key.V,
|
||||
ButtonPlus = Key.Plus,
|
||||
ButtonR = Key.U,
|
||||
ButtonZr = Key.O,
|
||||
ButtonSl = Key.Unbound,
|
||||
ButtonSr = Key.Unbound,
|
||||
},
|
||||
|
||||
RightJoyconStick = new JoyconConfigKeyboardStick<Key>
|
||||
{
|
||||
StickUp = Key.I,
|
||||
StickDown = Key.K,
|
||||
StickLeft = Key.J,
|
||||
StickRight = Key.L,
|
||||
StickButton = Key.H,
|
||||
},
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isNintendoStyle = gamepadName.Contains("Nintendo");
|
||||
|
||||
config = new StandardControllerInputConfig
|
||||
{
|
||||
Version = InputConfig.CurrentVersion,
|
||||
Backend = InputBackendType.GamepadSDL2,
|
||||
Id = null,
|
||||
ControllerType = ControllerType.JoyconPair,
|
||||
DeadzoneLeft = 0.1f,
|
||||
DeadzoneRight = 0.1f,
|
||||
RangeLeft = 1.0f,
|
||||
RangeRight = 1.0f,
|
||||
TriggerThreshold = 0.5f,
|
||||
LeftJoycon = new LeftJoyconCommonConfig<ConfigGamepadInputId>
|
||||
{
|
||||
DpadUp = ConfigGamepadInputId.DpadUp,
|
||||
DpadDown = ConfigGamepadInputId.DpadDown,
|
||||
DpadLeft = ConfigGamepadInputId.DpadLeft,
|
||||
DpadRight = ConfigGamepadInputId.DpadRight,
|
||||
ButtonMinus = ConfigGamepadInputId.Minus,
|
||||
ButtonL = ConfigGamepadInputId.LeftShoulder,
|
||||
ButtonZl = ConfigGamepadInputId.LeftTrigger,
|
||||
ButtonSl = ConfigGamepadInputId.Unbound,
|
||||
ButtonSr = ConfigGamepadInputId.Unbound,
|
||||
},
|
||||
|
||||
LeftJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
|
||||
{
|
||||
Joystick = ConfigStickInputId.Left,
|
||||
StickButton = ConfigGamepadInputId.LeftStick,
|
||||
InvertStickX = false,
|
||||
InvertStickY = false,
|
||||
Rotate90CW = false,
|
||||
},
|
||||
|
||||
RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
|
||||
{
|
||||
ButtonA = isNintendoStyle ? ConfigGamepadInputId.A : ConfigGamepadInputId.B,
|
||||
ButtonB = isNintendoStyle ? ConfigGamepadInputId.B : ConfigGamepadInputId.A,
|
||||
ButtonX = isNintendoStyle ? ConfigGamepadInputId.X : ConfigGamepadInputId.Y,
|
||||
ButtonY = isNintendoStyle ? ConfigGamepadInputId.Y : ConfigGamepadInputId.X,
|
||||
ButtonPlus = ConfigGamepadInputId.Plus,
|
||||
ButtonR = ConfigGamepadInputId.RightShoulder,
|
||||
ButtonZr = ConfigGamepadInputId.RightTrigger,
|
||||
ButtonSl = ConfigGamepadInputId.Unbound,
|
||||
ButtonSr = ConfigGamepadInputId.Unbound,
|
||||
},
|
||||
|
||||
RightJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
|
||||
{
|
||||
Joystick = ConfigStickInputId.Right,
|
||||
StickButton = ConfigGamepadInputId.RightStick,
|
||||
InvertStickX = false,
|
||||
InvertStickY = false,
|
||||
Rotate90CW = false,
|
||||
},
|
||||
|
||||
Motion = new StandardMotionConfigController
|
||||
{
|
||||
MotionBackend = MotionInputBackendType.GamepadDriver,
|
||||
EnableMotion = true,
|
||||
Sensitivity = 100,
|
||||
GyroDeadzone = 1,
|
||||
},
|
||||
Rumble = new RumbleConfigController
|
||||
{
|
||||
StrongRumble = 1f,
|
||||
WeakRumble = 1f,
|
||||
EnableRumble = false,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string profileBasePath;
|
||||
|
||||
if (isKeyboard)
|
||||
{
|
||||
profileBasePath = Path.Combine(AppDataManager.ProfilesDirPath, "keyboard");
|
||||
}
|
||||
else
|
||||
{
|
||||
profileBasePath = Path.Combine(AppDataManager.ProfilesDirPath, "controller");
|
||||
}
|
||||
|
||||
string path = Path.Combine(profileBasePath, inputProfileName + ".json");
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Input profile \"{inputProfileName}\" not found for \"{inputId}\"");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
config = JsonHelper.DeserializeFromFile(path, _serializerContext.InputConfig);
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Input profile \"{inputProfileName}\" parsing failed for \"{inputId}\"");
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
config.Id = inputId;
|
||||
config.PlayerIndex = index;
|
||||
|
||||
string inputTypeName = isKeyboard ? "Keyboard" : "Gamepad";
|
||||
|
||||
Logger.Info?.Print(LogClass.Application, $"{config.PlayerIndex} configured with {inputTypeName} \"{config.Id}\"");
|
||||
|
||||
// If both stick ranges are 0 (usually indicative of an outdated profile load) then both sticks will be set to 1.0.
|
||||
if (config is StandardControllerInputConfig controllerConfig)
|
||||
{
|
||||
if (controllerConfig.RangeLeft <= 0.0f && controllerConfig.RangeRight <= 0.0f)
|
||||
{
|
||||
controllerConfig.RangeLeft = 1.0f;
|
||||
controllerConfig.RangeRight = 1.0f;
|
||||
|
||||
Logger.Info?.Print(LogClass.Application, $"{config.PlayerIndex} stick range reset. Save the profile now to update your configuration");
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
static void Load(string[] originalArgs, Options option)
|
||||
static void Load(Options option)
|
||||
{
|
||||
Initialize();
|
||||
|
||||
bool useLastUsedProfile = false;
|
||||
|
||||
if (option.InheritConfig)
|
||||
{
|
||||
option.InheritMainConfig(originalArgs, ConfigurationState.Instance, out useLastUsedProfile);
|
||||
}
|
||||
|
||||
AppDataManager.Initialize(option.BaseDataDir);
|
||||
|
||||
if (useLastUsedProfile && AccountSaveDataManager.GetLastUsedUser().TryGet(out var profile))
|
||||
option.UserProfile = profile.Name;
|
||||
|
||||
// Check if keys exists.
|
||||
if (!File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys")))
|
||||
{
|
||||
if (!(AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile && File.Exists(Path.Combine(AppDataManager.KeysDirPathUser, "prod.keys"))))
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, "Keys not found");
|
||||
}
|
||||
}
|
||||
|
||||
ReloadConfig();
|
||||
|
||||
|
||||
_virtualFileSystem = VirtualFileSystem.CreateInstance();
|
||||
_libHacHorizonManager = new LibHacHorizonManager();
|
||||
|
||||
@@ -177,7 +352,7 @@ namespace Ryujinx.Headless
|
||||
|
||||
_inputManager = new InputManager(new SDL2KeyboardDriver(), new SDL2GamepadDriver());
|
||||
|
||||
GraphicsConfig.EnableShaderCache = !option.DisableShaderCache;
|
||||
GraphicsConfig.EnableShaderCache = true;
|
||||
|
||||
if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
@@ -188,13 +363,15 @@ namespace Ryujinx.Headless
|
||||
}
|
||||
}
|
||||
|
||||
IGamepad gamepad;
|
||||
|
||||
if (option.ListInputIds)
|
||||
{
|
||||
Logger.Info?.Print(LogClass.Application, "Input Ids:");
|
||||
|
||||
foreach (string id in _inputManager.KeyboardDriver.GamepadsIds)
|
||||
{
|
||||
IGamepad gamepad = _inputManager.KeyboardDriver.GetGamepad(id);
|
||||
gamepad = _inputManager.KeyboardDriver.GetGamepad(id);
|
||||
|
||||
Logger.Info?.Print(LogClass.Application, $"- {id} (\"{gamepad.Name}\")");
|
||||
|
||||
@@ -203,7 +380,7 @@ namespace Ryujinx.Headless
|
||||
|
||||
foreach (string id in _inputManager.GamepadDriver.GamepadsIds)
|
||||
{
|
||||
IGamepad gamepad = _inputManager.GamepadDriver.GetGamepad(id);
|
||||
gamepad = _inputManager.GamepadDriver.GetGamepad(id);
|
||||
|
||||
Logger.Info?.Print(LogClass.Application, $"- {id} (\"{gamepad.Name}\")");
|
||||
|
||||
@@ -220,7 +397,7 @@ namespace Ryujinx.Headless
|
||||
return;
|
||||
}
|
||||
|
||||
_inputConfiguration ??= [];
|
||||
_inputConfiguration = new List<InputConfig>();
|
||||
_enableKeyboard = option.EnableKeyboard;
|
||||
_enableMouse = option.EnableMouse;
|
||||
|
||||
@@ -233,9 +410,9 @@ namespace Ryujinx.Headless
|
||||
_inputConfiguration.Add(inputConfig);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LoadPlayerConfiguration(option.InputProfile1Name, option.InputId1, PlayerIndex.Player1);
|
||||
LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2);
|
||||
LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2);
|
||||
LoadPlayerConfiguration(option.InputProfile3Name, option.InputId3, PlayerIndex.Player3);
|
||||
LoadPlayerConfiguration(option.InputProfile4Name, option.InputId4, PlayerIndex.Player4);
|
||||
LoadPlayerConfiguration(option.InputProfile5Name, option.InputId5, PlayerIndex.Player5);
|
||||
@@ -243,7 +420,6 @@ namespace Ryujinx.Headless
|
||||
LoadPlayerConfiguration(option.InputProfile7Name, option.InputId7, PlayerIndex.Player7);
|
||||
LoadPlayerConfiguration(option.InputProfile8Name, option.InputId8, PlayerIndex.Player8);
|
||||
LoadPlayerConfiguration(option.InputProfileHandheldName, option.InputIdHandheld, PlayerIndex.Handheld);
|
||||
|
||||
|
||||
if (_inputConfiguration.Count == 0)
|
||||
{
|
||||
@@ -255,7 +431,7 @@ namespace Ryujinx.Headless
|
||||
Logger.SetEnable(LogLevel.Stub, !option.LoggingDisableStub);
|
||||
Logger.SetEnable(LogLevel.Info, !option.LoggingDisableInfo);
|
||||
Logger.SetEnable(LogLevel.Warning, !option.LoggingDisableWarning);
|
||||
Logger.SetEnable(LogLevel.Error, !option.LoggingDisableError);
|
||||
Logger.SetEnable(LogLevel.Error, option.LoggingEnableError);
|
||||
Logger.SetEnable(LogLevel.Trace, option.LoggingEnableTrace);
|
||||
Logger.SetEnable(LogLevel.Guest, !option.LoggingDisableGuest);
|
||||
Logger.SetEnable(LogLevel.AccessLog, option.LoggingEnableFsAccessLog);
|
||||
@@ -339,6 +515,83 @@ namespace Ryujinx.Headless
|
||||
: new OpenGLWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet);
|
||||
}
|
||||
|
||||
private static IRenderer CreateRenderer(Options options, WindowBase window)
|
||||
{
|
||||
if (options.GraphicsBackend == GraphicsBackend.Vulkan && window is VulkanWindow vulkanWindow)
|
||||
{
|
||||
string preferredGpuId = string.Empty;
|
||||
Vk api = Vk.GetApi();
|
||||
|
||||
if (!string.IsNullOrEmpty(options.PreferredGPUVendor))
|
||||
{
|
||||
string preferredGpuVendor = options.PreferredGPUVendor.ToLowerInvariant();
|
||||
var devices = VulkanRenderer.GetPhysicalDevices(api);
|
||||
|
||||
foreach (var device in devices)
|
||||
{
|
||||
if (device.Vendor.ToLowerInvariant() == preferredGpuVendor)
|
||||
{
|
||||
preferredGpuId = device.Id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new VulkanRenderer(
|
||||
api,
|
||||
(instance, vk) => new SurfaceKHR((ulong)(vulkanWindow.CreateWindowSurface(instance.Handle))),
|
||||
vulkanWindow.GetRequiredInstanceExtensions,
|
||||
preferredGpuId);
|
||||
}
|
||||
|
||||
return new OpenGLRenderer();
|
||||
}
|
||||
|
||||
private static Switch InitializeEmulationContext(WindowBase window, IRenderer renderer, Options options)
|
||||
{
|
||||
BackendThreading threadingMode = options.BackendThreading;
|
||||
|
||||
bool threadedGAL = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading);
|
||||
|
||||
if (threadedGAL)
|
||||
{
|
||||
renderer = new ThreadedRenderer(renderer);
|
||||
}
|
||||
|
||||
HLEConfiguration configuration = new(_virtualFileSystem,
|
||||
_libHacHorizonManager,
|
||||
_contentManager,
|
||||
_accountManager,
|
||||
_userChannelPersistence,
|
||||
renderer,
|
||||
new SDL2HardwareDeviceDriver(),
|
||||
options.DramSize,
|
||||
window,
|
||||
options.SystemLanguage,
|
||||
options.SystemRegion,
|
||||
options.VSyncMode,
|
||||
!options.DisableDockedMode,
|
||||
!options.DisablePTC,
|
||||
options.EnableInternetAccess,
|
||||
!options.DisableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None,
|
||||
options.FsGlobalAccessLogMode,
|
||||
options.SystemTimeOffset,
|
||||
options.SystemTimeZone,
|
||||
options.MemoryManagerMode,
|
||||
options.IgnoreMissingServices,
|
||||
options.AspectRatio,
|
||||
options.AudioVolume,
|
||||
options.UseHypervisor ?? true,
|
||||
options.MultiplayerLanInterfaceId,
|
||||
Common.Configuration.Multiplayer.MultiplayerMode.Disabled,
|
||||
false,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
options.CustomVSyncInterval);
|
||||
|
||||
return new Switch(configuration);
|
||||
}
|
||||
|
||||
private static void ExecutionEntrypoint()
|
||||
{
|
||||
if (OperatingSystem.IsWindows())
|
||||
73
src/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj
Normal file
73
src/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj
Normal file
@@ -0,0 +1,73 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Version>1.0.0-dirty</Version>
|
||||
<DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants>
|
||||
<SigningCertificate Condition=" '$(SigningCertificate)' == '' ">-</SigningCertificate>
|
||||
<TieredPGO>true</TieredPGO>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenTK.Core" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="$([MSBuild]::IsOSPlatform('OSX'))">
|
||||
<Exec Command="codesign --entitlements '$(ProjectDir)..\..\distribution\macos\entitlements.xml' -f -s $(SigningCertificate) '$(TargetDir)$(TargetName)'" />
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Input\Ryujinx.Input.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Input.SDL2\Ryujinx.Input.SDL2.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.HLE\Ryujinx.HLE.csproj" />
|
||||
<ProjectReference Include="..\ARMeilleure\ARMeilleure.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.OpenGL\Ryujinx.Graphics.OpenGL.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommandLineParser" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64'" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\..\distribution\legal\THIRDPARTY.md">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<TargetPath>THIRDPARTY.md</TargetPath>
|
||||
</Content>
|
||||
<Content Include="..\..\LICENSE.txt">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<TargetPath>LICENSE.txt</TargetPath>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64' OR '$(RuntimeIdentifier)' == 'linux-arm64' OR ('$(RuntimeIdentifier)' == '' AND $([MSBuild]::IsOSPlatform('Linux')))">
|
||||
<Content Include="..\..\distribution\linux\Ryujinx.sh">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Ryujinx.bmp" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Due to .net core 3.1 embedded resource loading -->
|
||||
<PropertyGroup>
|
||||
<EmbeddedResourceUseDependentUponConvention>false</EmbeddedResourceUseDependentUponConvention>
|
||||
<ApplicationIcon>..\Ryujinx\Ryujinx.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)' != ''">
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
<TrimMode>partial</TrimMode>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
BIN
src/Ryujinx.Headless.SDL2/Ryujinx.bmp
Normal file
BIN
src/Ryujinx.Headless.SDL2/Ryujinx.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.1 KiB |
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Headless
|
||||
namespace Ryujinx.Headless.SDL2
|
||||
{
|
||||
class StatusUpdatedEventArgs(
|
||||
string vSyncMode,
|
||||
@@ -6,7 +6,7 @@ using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using static SDL2.SDL;
|
||||
|
||||
namespace Ryujinx.Headless
|
||||
namespace Ryujinx.Headless.SDL2.Vulkan
|
||||
{
|
||||
class VulkanWindow : WindowBase
|
||||
{
|
||||
@@ -1,6 +1,5 @@
|
||||
using Humanizer;
|
||||
using LibHac.Tools.Fs;
|
||||
using Ryujinx.Ava;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Logging;
|
||||
@@ -27,7 +26,7 @@ using AntiAliasing = Ryujinx.Common.Configuration.AntiAliasing;
|
||||
using ScalingFilter = Ryujinx.Common.Configuration.ScalingFilter;
|
||||
using Switch = Ryujinx.HLE.Switch;
|
||||
|
||||
namespace Ryujinx.Headless
|
||||
namespace Ryujinx.Headless.SDL2
|
||||
{
|
||||
abstract partial class WindowBase : IHostUIHandler, IDisposable
|
||||
{
|
||||
@@ -137,7 +136,7 @@ namespace Ryujinx.Headless
|
||||
|
||||
private void SetWindowIcon()
|
||||
{
|
||||
Stream iconStream = typeof(Program).Assembly.GetManifestResourceStream("HeadlessLogo");
|
||||
Stream iconStream = typeof(WindowBase).Assembly.GetManifestResourceStream("Ryujinx.Headless.SDL2.Ryujinx.bmp");
|
||||
byte[] iconBytes = new byte[iconStream!.Length];
|
||||
|
||||
if (iconStream.Read(iconBytes, 0, iconBytes.Length) != iconBytes.Length)
|
||||
@@ -319,7 +318,7 @@ namespace Ryujinx.Headless
|
||||
Device.VSyncMode.ToString(),
|
||||
dockedMode,
|
||||
Device.Configuration.AspectRatio.ToText(),
|
||||
$"{Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",
|
||||
$"Game: {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",
|
||||
$"FIFO: {Device.Statistics.GetFifoPercent():0.00} %",
|
||||
$"GPU: {_gpuDriverName}"));
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.HLE.HOS.SystemState;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Ryujinx.UI.Common.Configuration.System
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace Ryujinx.UI.Common.Helper
|
||||
|
||||
if (uninstall)
|
||||
{
|
||||
// If the types don't already exist, there's nothing to do, and we can call this operation successful.
|
||||
// If the types don't already exist, there's nothing to do and we can call this operation successful.
|
||||
if (!AreMimeTypesRegisteredWindows())
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -552,13 +552,15 @@
|
||||
"AboutUrlTooltipMessage": "انقر لفتح موقع ريوجينكس في متصفحك الافتراضي.",
|
||||
"AboutDisclaimerMessage": "ريوجينكس لا ينتمي إلى نينتندو™،\nأو أي من شركائها بأي شكل من الأشكال.",
|
||||
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com) يتم \nاستخدامه في محاكاة أمبيو لدينا.",
|
||||
"AboutPatreonUrlTooltipMessage": "انقر لفتح صفحة ريوجينكس في باتريون في متصفحك الافتراضي.",
|
||||
"AboutGithubUrlTooltipMessage": "انقر لفتح صفحة ريوجينكس في غيت هاب في متصفحك الافتراضي.",
|
||||
"AboutDiscordUrlTooltipMessage": "انقر لفتح دعوة إلى خادم ريوجينكس في ديكسورد في متصفحك الافتراضي.",
|
||||
"AboutTwitterUrlTooltipMessage": "انقر لفتح صفحة ريوجينكس في تويتر في متصفحك الافتراضي.",
|
||||
"AboutRyujinxAboutTitle": "حول:",
|
||||
"AboutRyujinxAboutContent": "Ryujinx is an emulator for the Nintendo Switch™.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
|
||||
"AboutRyujinxAboutContent": "ريوجينكس هو محاكي لجهاز نينتندو سويتش™.\nمن فضلك ادعمنا على باتريون.\nاحصل على آخر الأخبار على تويتر أو ديسكورد.\nيمكن للمطورين المهتمين بالمساهمة معرفة المزيد على غيت هاب أو ديسكورد.",
|
||||
"AboutRyujinxMaintainersTitle": "تتم صيانته بواسطة:",
|
||||
"AboutRyujinxFormerMaintainersTitle": "Formerly Maintained By:",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "انقر لفتح صفحة المساهمين في متصفحك الافتراضي.",
|
||||
"AboutRyujinxSupprtersTitle": "مدعوم على باتريون بواسطة:",
|
||||
"AmiiboSeriesLabel": "مجموعة أميبو",
|
||||
"AmiiboCharacterLabel": "شخصية",
|
||||
"AmiiboScanButtonLabel": "فحصه",
|
||||
|
||||
@@ -552,13 +552,15 @@
|
||||
"AboutUrlTooltipMessage": "Klicke hier, um die Ryujinx Website im Standardbrowser zu öffnen.",
|
||||
"AboutDisclaimerMessage": "Ryujinx ist in keinster Weise weder mit Nintendo™, \nnoch mit deren Partnern verbunden.",
|
||||
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com) wird in unserer Amiibo \nEmulation benutzt.",
|
||||
"AboutPatreonUrlTooltipMessage": "Klicke hier, um die Ryujinx Patreon Seite im Standardbrowser zu öffnen.",
|
||||
"AboutGithubUrlTooltipMessage": "Klicke hier, um die Ryujinx GitHub Seite im Standardbrowser zu öffnen.",
|
||||
"AboutDiscordUrlTooltipMessage": "Klicke hier, um eine Einladung zum Ryujinx Discord Server im Standardbrowser zu öffnen.",
|
||||
"AboutTwitterUrlTooltipMessage": "Klicke hier, um die Ryujinx Twitter Seite im Standardbrowser zu öffnen.",
|
||||
"AboutRyujinxAboutTitle": "Über:",
|
||||
"AboutRyujinxAboutContent": "Ryujinx is an emulator for the Nintendo Switch™.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
|
||||
"AboutRyujinxAboutContent": "Ryujinx ist ein Nintendo Switch™ Emulator.\nBitte unterstütze uns auf Patreon.\nAuf Twitter oder Discord erfährst du alle Neuigkeiten.\nEntwickler, die an einer Mitarbeit interessiert sind, können auf GitHub oder Discord mehr erfahren.",
|
||||
"AboutRyujinxMaintainersTitle": "Entwickelt von:",
|
||||
"AboutRyujinxFormerMaintainersTitle": "Formerly Maintained By:",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "Klicke hier, um die Liste der Mitwirkenden im Standardbrowser zu öffnen.",
|
||||
"AboutRyujinxSupprtersTitle": "Unterstützt auf Patreon von:",
|
||||
"AmiiboSeriesLabel": "Amiibo-Serie",
|
||||
"AmiiboCharacterLabel": "Charakter",
|
||||
"AmiiboScanButtonLabel": "Einscannen",
|
||||
|
||||
@@ -552,13 +552,15 @@
|
||||
"AboutUrlTooltipMessage": "Κάντε κλικ για να ανοίξετε τον ιστότοπο Ryujinx στο προεπιλεγμένο πρόγραμμα περιήγησης.",
|
||||
"AboutDisclaimerMessage": "Το Ryujinx δεν είναι συνδεδεμένο με τη Nintendo™,\nούτε με κανέναν από τους συνεργάτες της, με οποιονδήποτε τρόπο.",
|
||||
"AboutAmiiboDisclaimerMessage": "Το AmiiboAPI (www.amiiboapi.com) χρησιμοποιείται\nστην προσομοίωση Amiibo.",
|
||||
"AboutPatreonUrlTooltipMessage": "Κάντε κλικ για να ανοίξετε τη σελίδα Ryujinx Patreon στο προεπιλεγμένο πρόγραμμα περιήγησης.",
|
||||
"AboutGithubUrlTooltipMessage": "Κάντε κλικ για να ανοίξετε τη σελίδα Ryujinx GitHub στο προεπιλεγμένο πρόγραμμα περιήγησης.",
|
||||
"AboutDiscordUrlTooltipMessage": "Κάντε κλικ για να ανοίξετε μία πρόσκληση στον διακομιστή Ryujinx Discord στο προεπιλεγμένο πρόγραμμα περιήγησης.",
|
||||
"AboutTwitterUrlTooltipMessage": "Κάντε κλικ για να ανοίξετε τη σελίδα Ryujinx Twitter στο προεπιλεγμένο πρόγραμμα περιήγησης.",
|
||||
"AboutRyujinxAboutTitle": "Σχετικά με:",
|
||||
"AboutRyujinxAboutContent": "Ryujinx is an emulator for the Nintendo Switch™.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
|
||||
"AboutRyujinxAboutContent": "Το Ryujinx είναι ένας εξομοιωτής για το Nintendo Switch™.\nΥποστηρίξτε μας στο Patreon.\nΛάβετε όλα τα τελευταία νέα στο Twitter ή στο Discord.\nΟι προγραμματιστές που ενδιαφέρονται να συνεισφέρουν μπορούν να μάθουν περισσότερα στο GitHub ή στο Discord μας.",
|
||||
"AboutRyujinxMaintainersTitle": "Συντηρείται από:",
|
||||
"AboutRyujinxFormerMaintainersTitle": "Formerly Maintained By:",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "Κάντε κλικ για να ανοίξετε τη σελίδα Συνεισφέροντες στο προεπιλεγμένο πρόγραμμα περιήγησης.",
|
||||
"AboutRyujinxSupprtersTitle": "Υποστηρίζεται στο Patreon από:",
|
||||
"AmiiboSeriesLabel": "Σειρά Amiibo",
|
||||
"AmiiboCharacterLabel": "Χαρακτήρας",
|
||||
"AmiiboScanButtonLabel": "Σαρώστε το",
|
||||
|
||||
@@ -564,13 +564,15 @@
|
||||
"AboutUrlTooltipMessage": "Click to open the Ryujinx website in your default browser.",
|
||||
"AboutDisclaimerMessage": "Ryujinx is not affiliated with Nintendo™,\nor any of its partners, in any way.",
|
||||
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com) is used\nin our Amiibo emulation.",
|
||||
"AboutPatreonUrlTooltipMessage": "Click to open the Ryujinx Patreon page in your default browser.",
|
||||
"AboutGithubUrlTooltipMessage": "Click to open the Ryujinx GitHub page in your default browser.",
|
||||
"AboutDiscordUrlTooltipMessage": "Click to open an invite to the Ryujinx Discord server in your default browser.",
|
||||
"AboutTwitterUrlTooltipMessage": "Click to open the Ryujinx Twitter page in your default browser.",
|
||||
"AboutRyujinxAboutTitle": "About:",
|
||||
"AboutRyujinxAboutContent": "Ryujinx is an emulator for the Nintendo Switch™.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
|
||||
"AboutRyujinxAboutContent": "Ryujinx is an emulator for the Nintendo Switch™.\nPlease support us on Patreon.\nGet all the latest news on our Twitter or Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
|
||||
"AboutRyujinxMaintainersTitle": "Maintained By:",
|
||||
"AboutRyujinxFormerMaintainersTitle": "Formerly Maintained By:",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "Click to open the Contributors page in your default browser.",
|
||||
"AboutRyujinxSupprtersTitle": "Supported on Patreon By:",
|
||||
"AmiiboSeriesLabel": "Amiibo Series",
|
||||
"AmiiboCharacterLabel": "Character",
|
||||
"AmiiboScanButtonLabel": "Scan It",
|
||||
|
||||
@@ -552,13 +552,15 @@
|
||||
"AboutUrlTooltipMessage": "Haz clic para abrir el sitio web de Ryujinx en tu navegador predeterminado.",
|
||||
"AboutDisclaimerMessage": "Ryujinx no tiene afiliación alguna con Nintendo™,\nni con ninguno de sus socios.",
|
||||
"AboutAmiiboDisclaimerMessage": "Utilizamos AmiiboAPI (www.amiiboapi.com)\nen nuestra emulación de Amiibo.",
|
||||
"AboutPatreonUrlTooltipMessage": "Haz clic para abrir el Patreon de Ryujinx en tu navegador predeterminado.",
|
||||
"AboutGithubUrlTooltipMessage": "Haz clic para abrir el GitHub de Ryujinx en tu navegador predeterminado.",
|
||||
"AboutDiscordUrlTooltipMessage": "Haz clic para recibir una invitación al Discord de Ryujinx en tu navegador predeterminado.",
|
||||
"AboutTwitterUrlTooltipMessage": "Haz clic para abrir el Twitter de Ryujinx en tu navegador predeterminado.",
|
||||
"AboutRyujinxAboutTitle": "Acerca de:",
|
||||
"AboutRyujinxAboutContent": "Ryujinx is an emulator for the Nintendo Switch™.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
|
||||
"AboutRyujinxAboutContent": "Ryujinx es un emulador para Nintendo Switch™.\nPor favor, apóyanos en Patreon.\nEncuentra las noticias más recientes en nuestro Twitter o Discord.\nDesarrolladores interesados en contribuir pueden encontrar más información en GitHub o Discord.",
|
||||
"AboutRyujinxMaintainersTitle": "Mantenido por:",
|
||||
"AboutRyujinxFormerMaintainersTitle": "Formerly Maintained By:",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "Haz clic para abrir la página de contribuidores en tu navegador predeterminado.",
|
||||
"AboutRyujinxSupprtersTitle": "Apoyado en Patreon Por:",
|
||||
"AmiiboSeriesLabel": "Serie de Amiibo",
|
||||
"AmiiboCharacterLabel": "Personaje",
|
||||
"AmiiboScanButtonLabel": "Escanear",
|
||||
|
||||
@@ -552,13 +552,15 @@
|
||||
"AboutUrlTooltipMessage": "Cliquez pour ouvrir le site de Ryujinx dans votre navigateur par défaut.",
|
||||
"AboutDisclaimerMessage": "Ryujinx n'est pas affilié à Nintendo™,\nou à aucun de ses partenaires, de quelque manière que ce soit.",
|
||||
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com) est utilisé\ndans notre émulation Amiibo.",
|
||||
"AboutPatreonUrlTooltipMessage": "Cliquez pour ouvrir la page Patreon de Ryujinx dans votre navigateur par défaut.",
|
||||
"AboutGithubUrlTooltipMessage": "Cliquez pour ouvrir la page GitHub de Ryujinx dans votre navigateur par défaut.",
|
||||
"AboutDiscordUrlTooltipMessage": "Cliquez pour ouvrir une invitation au serveur Discord de Ryujinx dans votre navigateur par défaut.",
|
||||
"AboutTwitterUrlTooltipMessage": "Cliquez pour ouvrir la page Twitter de Ryujinx dans votre navigateur par défaut.",
|
||||
"AboutRyujinxAboutTitle": "À propos :",
|
||||
"AboutRyujinxAboutContent": "Ryujinx is an emulator for the Nintendo Switch™.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
|
||||
"AboutRyujinxAboutContent": "Ryujinx est un émulateur pour la Nintendo Switch™.\nMerci de nous soutenir sur Patreon.\nObtenez toutes les dernières actualités sur notre Twitter ou notre Discord.\nLes développeurs intéressés à contribuer peuvent en savoir plus sur notre GitHub ou notre Discord.",
|
||||
"AboutRyujinxMaintainersTitle": "Maintenu par :",
|
||||
"AboutRyujinxFormerMaintainersTitle": "Formerly Maintained By:",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "Cliquez pour ouvrir la page Contributeurs dans votre navigateur par défaut.",
|
||||
"AboutRyujinxSupprtersTitle": "Supporté sur Patreon par :",
|
||||
"AmiiboSeriesLabel": "Séries Amiibo",
|
||||
"AmiiboCharacterLabel": "Personnage",
|
||||
"AmiiboScanButtonLabel": "Scanner",
|
||||
|
||||
@@ -552,13 +552,15 @@
|
||||
"AboutUrlTooltipMessage": "לחץ כדי לפתוח את אתר ריוג'ינקס בדפדפן ברירת המחדל שלך.",
|
||||
"AboutDisclaimerMessage": "ריוג'ינקס אינה מזוהת עם נינטנדו,\nאו שוטפייה בכל דרך שהיא.",
|
||||
"AboutAmiiboDisclaimerMessage": "ממשק אמיבו (www.amiiboapi.com) משומש בהדמיית האמיבו שלנו.",
|
||||
"AboutPatreonUrlTooltipMessage": "לחץ כדי לפתוח את דף הפטראון של ריוג'ינקס בדפדפן ברירת המחדל שלך.",
|
||||
"AboutGithubUrlTooltipMessage": "לחץ כדי לפתוח את דף הגיטהב של ריוג'ינקס בדפדפן ברירת המחדל שלך.",
|
||||
"AboutDiscordUrlTooltipMessage": "לחץ כדי לפתוח הזמנה לשרת הדיסקורד של ריוג'ינקס בדפדפן ברירת המחדל שלך.",
|
||||
"AboutTwitterUrlTooltipMessage": "לחץ כדי לפתוח את דף הטוויטר של Ryujinx בדפדפן ברירת המחדל שלך.",
|
||||
"AboutRyujinxAboutTitle": "אודות:",
|
||||
"AboutRyujinxAboutContent": "Ryujinx is an emulator for the Nintendo Switch™.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
|
||||
"AboutRyujinxAboutContent": "ריוג'ינקס הוא אמולטור עבור הנינטנדו סוויץ' (כל הזכויות שמורות).\nבבקשה תתמכו בנו בפטראון.\nקבל את כל החדשות האחרונות בטוויטר או בדיסקורד שלנו.\nמפתחים המעוניינים לתרום יכולים לקבל מידע נוסף ב-גיטהאב או ב-דיסקורד שלנו.",
|
||||
"AboutRyujinxMaintainersTitle": "מתוחזק על ידי:",
|
||||
"AboutRyujinxFormerMaintainersTitle": "Formerly Maintained By:",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "לחץ כדי לפתוח את דף התורמים בדפדפן ברירת המחדל שלך.",
|
||||
"AboutRyujinxSupprtersTitle": "תמוך באמצעות Patreon",
|
||||
"AmiiboSeriesLabel": "סדרת אמיבו",
|
||||
"AmiiboCharacterLabel": "דמות",
|
||||
"AmiiboScanButtonLabel": "סרוק את זה",
|
||||
|
||||
@@ -552,13 +552,15 @@
|
||||
"AboutUrlTooltipMessage": "Clicca per aprire il sito web di Ryujinx nel tuo browser predefinito.",
|
||||
"AboutDisclaimerMessage": "Ryujinx non è affiliato con Nintendo™,\no i suoi partner, in alcun modo.",
|
||||
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com) è usata\nnella nostra emulazione Amiibo.",
|
||||
"AboutPatreonUrlTooltipMessage": "Clicca per aprire la pagina Patreon di Ryujinx nel tuo browser predefinito.",
|
||||
"AboutGithubUrlTooltipMessage": "Clicca per aprire la pagina GitHub di Ryujinx nel tuo browser predefinito.",
|
||||
"AboutDiscordUrlTooltipMessage": "Clicca per aprire un invito al server Discord di Ryujinx nel tuo browser predefinito.",
|
||||
"AboutTwitterUrlTooltipMessage": "Clicca per aprire la pagina Twitter di Ryujinx nel tuo browser predefinito.",
|
||||
"AboutRyujinxAboutTitle": "Informazioni:",
|
||||
"AboutRyujinxAboutContent": "Ryujinx is an emulator for the Nintendo Switch™.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
|
||||
"AboutRyujinxAboutContent": "Ryujinx è un emulatore per la console Nintendo Switch™.\nSostienici su Patreon.\nRicevi tutte le ultime notizie sul nostro Twitter o su Discord.\nGli sviluppatori interessati a contribuire possono trovare più informazioni sul nostro GitHub o Discord.",
|
||||
"AboutRyujinxMaintainersTitle": "Mantenuto da:",
|
||||
"AboutRyujinxFormerMaintainersTitle": "Formerly Maintained By:",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "Clicca per aprire la pagina dei contributori nel tuo browser predefinito.",
|
||||
"AboutRyujinxSupprtersTitle": "Supportato su Patreon da:",
|
||||
"AmiiboSeriesLabel": "Serie Amiibo",
|
||||
"AmiiboCharacterLabel": "Personaggio",
|
||||
"AmiiboScanButtonLabel": "Scansiona",
|
||||
|
||||
@@ -552,13 +552,15 @@
|
||||
"AboutUrlTooltipMessage": "クリックするとデフォルトのブラウザで Ryujinx のウェブサイトを開きます.",
|
||||
"AboutDisclaimerMessage": "Ryujinx は Nintendo™ および\nそのパートナー企業とは一切関係ありません.",
|
||||
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com) は\nAmiibo エミュレーションに使用されています.",
|
||||
"AboutPatreonUrlTooltipMessage": "クリックするとデフォルトのブラウザで Ryujinx の Patreon ページを開きます.",
|
||||
"AboutGithubUrlTooltipMessage": "クリックするとデフォルトのブラウザで Ryujinx の Github ページを開きます.",
|
||||
"AboutDiscordUrlTooltipMessage": "クリックするとデフォルトのブラウザで Ryujinx の Discord サーバを開きます.",
|
||||
"AboutTwitterUrlTooltipMessage": "クリックするとデフォルトのブラウザで Ryujinx の Twitter ページを開きます.",
|
||||
"AboutRyujinxAboutTitle": "Ryujinx について:",
|
||||
"AboutRyujinxAboutContent": "Ryujinx is an emulator for the Nintendo Switch™.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
|
||||
"AboutRyujinxAboutContent": "Ryujinx は Nintendo Switch™ のエミュレータです.\nPatreon で私達の活動を支援してください.\n最新の情報は Twitter または Discord から取得できます.\n貢献したい開発者の方は GitHub または Discord で詳細をご確認ください.",
|
||||
"AboutRyujinxMaintainersTitle": "開発者:",
|
||||
"AboutRyujinxFormerMaintainersTitle": "Formerly Maintained By:",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "クリックするとデフォルトのブラウザで 貢献者のページを開きます.",
|
||||
"AboutRyujinxSupprtersTitle": "Patreon での支援者:",
|
||||
"AmiiboSeriesLabel": "Amiibo シリーズ",
|
||||
"AmiiboCharacterLabel": "キャラクタ",
|
||||
"AmiiboScanButtonLabel": "スキャン",
|
||||
|
||||
@@ -552,13 +552,15 @@
|
||||
"AboutUrlTooltipMessage": "클릭하면 기본 브라우저에서 Ryujinx 웹사이트가 열립니다.",
|
||||
"AboutDisclaimerMessage": "Ryujinx는 Nintendo™\n또는 그 파트너와 제휴한 바가 없습니다.",
|
||||
"AboutAmiiboDisclaimerMessage": "AmiiboAPI(www.amiiboapi.com)는\nAmiibo 에뮬레이션에 사용됩니다.",
|
||||
"AboutPatreonUrlTooltipMessage": "클릭하면 기본 브라우저에서 Ryujinx Patreon 페이지가 열립니다.",
|
||||
"AboutGithubUrlTooltipMessage": "클릭하면 기본 브라우저에서 Ryujinx GitHub 페이지가 열립니다.",
|
||||
"AboutDiscordUrlTooltipMessage": "클릭하면 기본 브라우저에서 Ryujinx 디스코드 서버 초대장이 열립니다.",
|
||||
"AboutTwitterUrlTooltipMessage": "클릭하면 기본 브라우저에서 Ryujinx 트위터 페이지가 열립니다.",
|
||||
"AboutRyujinxAboutTitle": "정보 :",
|
||||
"AboutRyujinxAboutContent": "Ryujinx is an emulator for the Nintendo Switch™.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
|
||||
"AboutRyujinxAboutContent": "Ryujinx는 Nintendo Switch™용 에뮬레이터입니다.\nPatreon에서 저희를 후원해 주세요.\nTwitter나 Discord에서 최신 뉴스를 모두 받아보세요.\n기여에 관심이 있는 개발자는 GitHub이나 Discord에서 자세한 내용을 알아볼 수 있습니다.",
|
||||
"AboutRyujinxMaintainersTitle": "유지 관리 :",
|
||||
"AboutRyujinxFormerMaintainersTitle": "Formerly Maintained By:",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "클릭하면 기본 브라우저에서 기여자 페이지가 열립니다.",
|
||||
"AboutRyujinxSupprtersTitle": "Patreon에서 후원 :",
|
||||
"AmiiboSeriesLabel": "Amiibo 시리즈",
|
||||
"AmiiboCharacterLabel": "캐릭터",
|
||||
"AmiiboScanButtonLabel": "스캔하기",
|
||||
|
||||
@@ -552,13 +552,15 @@
|
||||
"AboutUrlTooltipMessage": "Kliknij, aby otworzyć stronę Ryujinx w domyślnej przeglądarce.",
|
||||
"AboutDisclaimerMessage": "Ryujinx nie jest w żaden sposób powiązany z Nintendo™,\nani z żadnym z jej partnerów.",
|
||||
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com) jest używane\nw naszej emulacji Amiibo.",
|
||||
"AboutPatreonUrlTooltipMessage": "Kliknij, aby otworzyć stronę Patreon Ryujinx w domyślnej przeglądarce.",
|
||||
"AboutGithubUrlTooltipMessage": "Kliknij, aby otworzyć stronę GitHub Ryujinx w domyślnej przeglądarce.",
|
||||
"AboutDiscordUrlTooltipMessage": "Kliknij, aby otworzyć zaproszenie na serwer Discord Ryujinx w domyślnej przeglądarce.",
|
||||
"AboutTwitterUrlTooltipMessage": "Kliknij, aby otworzyć stronę Twitter Ryujinx w domyślnej przeglądarce.",
|
||||
"AboutRyujinxAboutTitle": "O Aplikacji:",
|
||||
"AboutRyujinxAboutContent": "Ryujinx is an emulator for the Nintendo Switch™.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
|
||||
"AboutRyujinxAboutContent": "Ryujinx to emulator Nintendo Switch™.\nWspieraj nas na Patreonie.\nOtrzymuj najnowsze wiadomości na naszym Twitterze lub Discordzie.\nDeweloperzy zainteresowani współpracą mogą dowiedzieć się więcej na naszym GitHubie lub Discordzie.",
|
||||
"AboutRyujinxMaintainersTitle": "Utrzymywany Przez:",
|
||||
"AboutRyujinxFormerMaintainersTitle": "Formerly Maintained By:",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "Kliknij, aby otworzyć stronę Współtwórcy w domyślnej przeglądarce.",
|
||||
"AboutRyujinxSupprtersTitle": "Wspierani na Patreonie Przez:",
|
||||
"AmiiboSeriesLabel": "Seria Amiibo",
|
||||
"AmiiboCharacterLabel": "Postać",
|
||||
"AmiiboScanButtonLabel": "Zeskanuj",
|
||||
|
||||
@@ -552,13 +552,15 @@
|
||||
"AboutUrlTooltipMessage": "Clique para abrir o site do Ryujinx no seu navegador padrão.",
|
||||
"AboutDisclaimerMessage": "Ryujinx não é afiliado com a Nintendo™,\nou qualquer um de seus parceiros, de nenhum modo.",
|
||||
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com) é usado\nem nossa emulação de Amiibo.",
|
||||
"AboutPatreonUrlTooltipMessage": "Clique para abrir a página do Patreon do Ryujinx no seu navegador padrão.",
|
||||
"AboutGithubUrlTooltipMessage": "Clique para abrir a página do GitHub do Ryujinx no seu navegador padrão.",
|
||||
"AboutDiscordUrlTooltipMessage": "Clique para abrir um convite ao servidor do Discord do Ryujinx no seu navegador padrão.",
|
||||
"AboutTwitterUrlTooltipMessage": "Clique para abrir a página do Twitter do Ryujinx no seu navegador padrão.",
|
||||
"AboutRyujinxAboutTitle": "Sobre:",
|
||||
"AboutRyujinxAboutContent": "Ryujinx is an emulator for the Nintendo Switch™.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
|
||||
"AboutRyujinxAboutContent": "Ryujinx é um emulador de Nintendo Switch™.\nPor favor, nos dê apoio no Patreon.\nFique por dentro de todas as novidades no Twitter ou Discord.\nDesenvolvedores com interesse em contribuir podem conseguir mais informações no GitHub ou Discord.",
|
||||
"AboutRyujinxMaintainersTitle": "Mantido por:",
|
||||
"AboutRyujinxFormerMaintainersTitle": "Formerly Maintained By:",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "Clique para abrir a página de contribuidores no seu navegador padrão.",
|
||||
"AboutRyujinxSupprtersTitle": "Apoiado no Patreon por:",
|
||||
"AmiiboSeriesLabel": "Franquia Amiibo",
|
||||
"AmiiboCharacterLabel": "Personagem",
|
||||
"AmiiboScanButtonLabel": "Escanear",
|
||||
|
||||
@@ -552,13 +552,15 @@
|
||||
"AboutUrlTooltipMessage": "Нажмите, чтобы открыть веб-сайт Ryujinx",
|
||||
"AboutDisclaimerMessage": "Ryujinx никоим образом не связан ни с Nintendo™, ни с кем-либо из ее партнеров.",
|
||||
"AboutAmiiboDisclaimerMessage": "Amiibo API (www.amiiboapi.com) используется для эмуляции Amiibo.",
|
||||
"AboutPatreonUrlTooltipMessage": "Нажмите, чтобы открыть страницу Ryujinx на Patreon",
|
||||
"AboutGithubUrlTooltipMessage": "Нажмите, чтобы открыть страницу Ryujinx на GitHub",
|
||||
"AboutDiscordUrlTooltipMessage": "Нажмите, чтобы открыть приглашение на сервер Ryujinx в Discord",
|
||||
"AboutTwitterUrlTooltipMessage": "Нажмите, чтобы открыть страницу Ryujinx в X (бывший Twitter)",
|
||||
"AboutRyujinxAboutTitle": "О программе:",
|
||||
"AboutRyujinxAboutContent": "Ryujinx is an emulator for the Nintendo Switch™.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
|
||||
"AboutRyujinxAboutContent": "Ryujinx — это эмулятор Nintendo Switch™.\nПожалуйста, поддержите нас на Patreon.\nЧитайте последние новости в наших X (Twitter) или Discord.\nРазработчики, заинтересованные в участии, могут ознакомиться с проектом на GitHub или в Discord.",
|
||||
"AboutRyujinxMaintainersTitle": "Разработка:",
|
||||
"AboutRyujinxFormerMaintainersTitle": "Formerly Maintained By:",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "Нажмите, чтобы открыть страницу с участниками",
|
||||
"AboutRyujinxSupprtersTitle": "Поддержка на Patreon:",
|
||||
"AmiiboSeriesLabel": "Серия Amiibo",
|
||||
"AmiiboCharacterLabel": "Персонаж",
|
||||
"AmiiboScanButtonLabel": "Сканировать",
|
||||
|
||||
@@ -552,13 +552,15 @@
|
||||
"AboutUrlTooltipMessage": "คลิกเพื่อเปิดเว็บไซต์ Ryujinx บนเบราว์เซอร์เริ่มต้นของคุณ",
|
||||
"AboutDisclaimerMessage": "ทางผู้พัฒนาโปรแกรม Ryujinx ไม่มีส่วนเกี่ยวข้องกับทางบริษัท Nintendo™\nหรือพันธมิตรใดๆ ทั้งสิ้น!",
|
||||
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com) ถูกใช้\nในการจำลอง อะมิโบ ของเรา",
|
||||
"AboutPatreonUrlTooltipMessage": "คลิกเพื่อเปิดหน้า Patreon ของ Ryujinx บนเบราว์เซอร์เริ่มต้นของคุณ",
|
||||
"AboutGithubUrlTooltipMessage": "คลิกเพื่อเปิดหน้า Github ของ Ryujinx บนเบราว์เซอร์เริ่มต้นของคุณ",
|
||||
"AboutDiscordUrlTooltipMessage": "คลิกเพื่อเปิดคำเชิญเข้าสู่เซิร์ฟเวอร์ Discord ของ Ryujinx บนเบราว์เซอร์เริ่มต้นของคุณ",
|
||||
"AboutTwitterUrlTooltipMessage": "คลิกเพื่อเปิดหน้าเพจ Twitter ของ Ryujinx บนเบราว์เซอร์เริ่มต้นของคุณ",
|
||||
"AboutRyujinxAboutTitle": "เกี่ยวกับ:",
|
||||
"AboutRyujinxAboutContent": "Ryujinx is an emulator for the Nintendo Switch™.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
|
||||
"AboutRyujinxAboutContent": "Ryujinx เป็นอีมูเลเตอร์สำหรับ Nintendo Switch™\nโปรดสนับสนุนเราบน Patreon\nรับข่าวสารล่าสุดทั้งหมดบน Twitter หรือ Discord ของเรา\nนักพัฒนาที่สนใจจะมีส่วนร่วมสามารถดูข้อมูลเพิ่มเติมได้ที่ GitHub หรือ Discord ของเรา",
|
||||
"AboutRyujinxMaintainersTitle": "ได้รับการดูแลโดย:",
|
||||
"AboutRyujinxFormerMaintainersTitle": "Formerly Maintained By:",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "คลิกเพื่อเปิดหน้าผู้มีส่วนร่วมบนเบราว์เซอร์เริ่มต้นของคุณ",
|
||||
"AboutRyujinxSupprtersTitle": "ผู้สนับสนุนบน Patreon:",
|
||||
"AmiiboSeriesLabel": "Amiibo Series",
|
||||
"AmiiboCharacterLabel": "ตัวละคร",
|
||||
"AmiiboScanButtonLabel": "สแกนเลย",
|
||||
|
||||
@@ -552,13 +552,15 @@
|
||||
"AboutUrlTooltipMessage": "Ryujinx'in websitesini varsayılan tarayıcınızda açmak için tıklayın.",
|
||||
"AboutDisclaimerMessage": "Ryujinx, Nintendo™ veya ortaklarıyla herhangi bir şekilde bağlantılı değildir.",
|
||||
"AboutAmiiboDisclaimerMessage": "Amiibo emülasyonumuzda \nAmiiboAPI (www.amiiboapi.com) kullanılmaktadır.",
|
||||
"AboutPatreonUrlTooltipMessage": "Ryujinx'in Patreon sayfasını varsayılan tarayıcınızda açmak için tıklayın.",
|
||||
"AboutGithubUrlTooltipMessage": "Ryujinx'in GitHub sayfasını varsayılan tarayıcınızda açmak için tıklayın.",
|
||||
"AboutDiscordUrlTooltipMessage": "Varsayılan tarayıcınızda Ryujinx'in Discord'una bir davet açmak için tıklayın.",
|
||||
"AboutTwitterUrlTooltipMessage": "Ryujinx'in Twitter sayfasını varsayılan tarayıcınızda açmak için tıklayın.",
|
||||
"AboutRyujinxAboutTitle": "Hakkında:",
|
||||
"AboutRyujinxAboutContent": "Ryujinx is an emulator for the Nintendo Switch™.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
|
||||
"AboutRyujinxAboutContent": "Ryujinx bir Nintendo Switch™ emülatörüdür.\nLütfen bizi Patreon'da destekleyin.\nEn son haberleri Twitter veya Discord'umuzdan alın.\nKatkıda bulunmak isteyen geliştiriciler GitHub veya Discord üzerinden daha fazla bilgi edinebilir.",
|
||||
"AboutRyujinxMaintainersTitle": "Geliştiriciler:",
|
||||
"AboutRyujinxFormerMaintainersTitle": "Formerly Maintained By:",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "Katkıda bulunanlar sayfasını varsayılan tarayıcınızda açmak için tıklayın.",
|
||||
"AboutRyujinxSupprtersTitle": "Patreon Destekleyicileri:",
|
||||
"AmiiboSeriesLabel": "Amiibo Serisi",
|
||||
"AmiiboCharacterLabel": "Karakter",
|
||||
"AmiiboScanButtonLabel": "Tarat",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"Language": "Українська",
|
||||
"MenuBarFileOpenApplet": "Відкрити аплет",
|
||||
"MenuBarFileOpenAppletOpenMiiApplet": "Mii Edit Applet",
|
||||
"MenuBarFileOpenAppletOpenMiiApplet": "Аплет для редагування Mii",
|
||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Відкрити аплет Mii Editor в автономному режимі",
|
||||
"SettingsTabInputDirectMouseAccess": "Прямий доступ мишею",
|
||||
"SettingsTabSystemMemoryManagerMode": "Режим диспетчера пам’яті:",
|
||||
@@ -11,10 +11,10 @@
|
||||
"SettingsTabSystemUseHypervisor": "Використовувати гіпервізор",
|
||||
"MenuBarFile": "_Файл",
|
||||
"MenuBarFileOpenFromFile": "_Завантажити програму з файлу",
|
||||
"MenuBarFileOpenFromFileError": "No applications found in selected file.",
|
||||
"MenuBarFileOpenFromFileError": "У вибраному файлі не знайдено жодних додатків.",
|
||||
"MenuBarFileOpenUnpacked": "Завантажити _розпаковану гру",
|
||||
"MenuBarFileLoadDlcFromFolder": "Load DLC From Folder",
|
||||
"MenuBarFileLoadTitleUpdatesFromFolder": "Load Title Updates From Folder",
|
||||
"MenuBarFileLoadDlcFromFolder": "Завантажити DLC з теки",
|
||||
"MenuBarFileLoadTitleUpdatesFromFolder": "Завантажити оновлення заголовків з теки",
|
||||
"MenuBarFileOpenEmuFolder": "Відкрити теку Ryujinx",
|
||||
"MenuBarFileOpenLogsFolder": "Відкрити теку журналів змін",
|
||||
"MenuBarFileExit": "_Вихід",
|
||||
@@ -37,9 +37,9 @@
|
||||
"MenuBarToolsManageFileTypes": "Керувати типами файлів",
|
||||
"MenuBarToolsInstallFileTypes": "Установити типи файлів",
|
||||
"MenuBarToolsUninstallFileTypes": "Видалити типи файлів",
|
||||
"MenuBarToolsXCITrimmer": "Trim XCI Files",
|
||||
"MenuBarView": "_View",
|
||||
"MenuBarViewWindow": "Window Size",
|
||||
"MenuBarToolsXCITrimmer": "Обрізати XCI файли",
|
||||
"MenuBarView": "_Вид",
|
||||
"MenuBarViewWindow": "Розмір вікна",
|
||||
"MenuBarViewWindow720": "720p",
|
||||
"MenuBarViewWindow1080": "1080p",
|
||||
"MenuBarHelp": "_Допомога",
|
||||
@@ -89,8 +89,8 @@
|
||||
"GameListContextMenuOpenModsDirectoryToolTip": "Відкриває каталог, який містить модифікації Додатків",
|
||||
"GameListContextMenuOpenSdModsDirectory": "Відкрити каталог модифікацій Atmosphere",
|
||||
"GameListContextMenuOpenSdModsDirectoryToolTip": "Відкриває альтернативний каталог SD-карти Atmosphere, що містить модифікації Додатків. Корисно для модифікацій, зроблених для реального обладнання.",
|
||||
"GameListContextMenuTrimXCI": "Check and Trim XCI File",
|
||||
"GameListContextMenuTrimXCIToolTip": "Check and Trim XCI File to Save Disk Space",
|
||||
"GameListContextMenuTrimXCI": "Перевірка та Нарізка XCI Файлів",
|
||||
"GameListContextMenuTrimXCIToolTip": "Перевірка та Нарізка XCI Файлів для збереження місця на диску",
|
||||
"StatusBarGamesLoaded": "{0}/{1} ігор завантажено",
|
||||
"StatusBarSystemVersion": "Версія системи: {0}",
|
||||
"StatusBarXCIFileTrimming": "Trimming XCI File '{0}'",
|
||||
@@ -107,15 +107,15 @@
|
||||
"SettingsTabGeneralEnableDiscordRichPresence": "Увімкнути розширену присутність Discord",
|
||||
"SettingsTabGeneralCheckUpdatesOnLaunch": "Перевіряти наявність оновлень під час запуску",
|
||||
"SettingsTabGeneralShowConfirmExitDialog": "Показати діалогове вікно «Підтвердити вихід».",
|
||||
"SettingsTabGeneralRememberWindowState": "Remember Window Size/Position",
|
||||
"SettingsTabGeneralShowTitleBar": "Show Title Bar (Requires restart)",
|
||||
"SettingsTabGeneralRememberWindowState": "Запам'ятати Розмір/Позицію вікна",
|
||||
"SettingsTabGeneralShowTitleBar": "Показувати рядок заголовка (Потрібен перезапуск)",
|
||||
"SettingsTabGeneralHideCursor": "Сховати вказівник:",
|
||||
"SettingsTabGeneralHideCursorNever": "Ніколи",
|
||||
"SettingsTabGeneralHideCursorOnIdle": "Сховати у режимі очікування",
|
||||
"SettingsTabGeneralHideCursorAlways": "Завжди",
|
||||
"SettingsTabGeneralGameDirectories": "Тека ігор",
|
||||
"SettingsTabGeneralAutoloadDirectories": "Autoload DLC/Updates Directories",
|
||||
"SettingsTabGeneralAutoloadNote": "DLC and Updates which refer to missing files will be unloaded automatically",
|
||||
"SettingsTabGeneralAutoloadDirectories": "Автозавантаження каталогів DLC/Оновлень",
|
||||
"SettingsTabGeneralAutoloadNote": "DLC та Оновлення, які посилаються на відсутні файли, будуть автоматично вимкнуті.",
|
||||
"SettingsTabGeneralAdd": "Додати",
|
||||
"SettingsTabGeneralRemove": "Видалити",
|
||||
"SettingsTabSystem": "Система",
|
||||
@@ -148,7 +148,18 @@
|
||||
"SettingsTabSystemSystemLanguageTraditionalChinese": "Традиційна китайська",
|
||||
"SettingsTabSystemSystemTimeZone": "Часовий пояс системи:",
|
||||
"SettingsTabSystemSystemTime": "Час системи:",
|
||||
"SettingsTabSystemEnableVsync": "Вертикальна синхронізація",
|
||||
"SettingsTabSystemVSyncMode": "Вертикальна синхронізація (VSync):",
|
||||
"SettingsTabSystemEnableCustomVSyncInterval": "Увімкнути користувацьку частоту оновлення (Експериментально)",
|
||||
"SettingsTabSystemVSyncModeSwitch": "Switch",
|
||||
"SettingsTabSystemVSyncModeUnbounded": "Безмежна",
|
||||
"SettingsTabSystemVSyncModeCustom": "Користувацька",
|
||||
"SettingsTabSystemVSyncModeTooltip": "Емульована вертикальна синхронізація. 'Switch' емулює частоту оновлення Switch 60 Гц. 'Безмежна' — частота оновлення не матиме обмежень.",
|
||||
"SettingsTabSystemVSyncModeTooltipCustom": "Емульована вертикальна синхронізація. 'Switch' емулює частоту оновлення Switch 60 Гц. 'Безмежна' — частота оновлення не матиме обмежень. 'Користувацька' емулює вказану користувацьку частоту оновлення.",
|
||||
"SettingsTabSystemEnableCustomVSyncIntervalTooltip": "Дозволяє користувачу вказати емульовану частоту оновлення. У деяких іграх це може прискорити або сповільнити логіку гри. У інших іграх це може дозволити обмежити FPS на певні кратні частоти оновлення або призвести до непередбачуваної поведінки. Це експериментальна функція, без гарантій того, як це вплине на ігровий процес. \n\nЗалиште ВИМКНЕНИМ, якщо не впевнені.",
|
||||
"SettingsTabSystemCustomVSyncIntervalValueTooltip": "Цільове значення користувацької частоти оновлення.",
|
||||
"SettingsTabSystemCustomVSyncIntervalSliderTooltip": "Користувацька частота оновлення, як відсоток від стандартної частоти оновлення Switch.",
|
||||
"SettingsTabSystemCustomVSyncIntervalPercentage": "Користувацька частота оновлення %:",
|
||||
"SettingsTabSystemCustomVSyncIntervalValue": "Значення користувацька частота оновлення:",
|
||||
"SettingsTabSystemEnablePptc": "PPTC (профільований постійний кеш перекладу)",
|
||||
"SettingsTabSystemEnableLowPowerPptc": "Low-power PPTC",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "Перевірка цілісності FS",
|
||||
@@ -160,10 +171,10 @@
|
||||
"SettingsTabSystemHacks": "Хитрощі",
|
||||
"SettingsTabSystemHacksNote": " (може викликати нестабільність)",
|
||||
"SettingsTabSystemDramSize": "Використовувати альтернативне розташування пам'яті (розробники)",
|
||||
"SettingsTabSystemDramSize4GiB": "4GiB",
|
||||
"SettingsTabSystemDramSize6GiB": "6GiB",
|
||||
"SettingsTabSystemDramSize8GiB": "8GiB",
|
||||
"SettingsTabSystemDramSize12GiB": "12GiB",
|
||||
"SettingsTabSystemDramSize4GiB": "4Гб",
|
||||
"SettingsTabSystemDramSize6GiB": "6Гб",
|
||||
"SettingsTabSystemDramSize8GiB": "8Гб",
|
||||
"SettingsTabSystemDramSize12GiB": "12Гб",
|
||||
"SettingsTabSystemIgnoreMissingServices": "Ігнорувати відсутні служби",
|
||||
"SettingsTabSystemIgnoreApplet": "Ігнорувати Аплет",
|
||||
"SettingsTabGraphics": "Графіка",
|
||||
@@ -201,7 +212,7 @@
|
||||
"SettingsTabLoggingEnableGuestLogs": "Увімкнути журнали гостей",
|
||||
"SettingsTabLoggingEnableFsAccessLogs": "Увімкнути журнали доступу Fs",
|
||||
"SettingsTabLoggingFsGlobalAccessLogMode": "Режим журналу глобального доступу Fs:",
|
||||
"SettingsTabLoggingDeveloperOptions": "Параметри розробника (УВАГА: знизиться продуктивність)",
|
||||
"SettingsTabLoggingDeveloperOptions": "Параметри розробника (УВАГА: шкодить продуктивності)",
|
||||
"SettingsTabLoggingDeveloperOptionsNote": "УВАГА: Знижує продуктивність",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevel": "Рівень журналу графічного сервера:",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelNone": "Немає",
|
||||
@@ -291,29 +302,29 @@
|
||||
"ControllerSettingsMotionGyroDeadzone": "Мертва зона гіроскопа:",
|
||||
"ControllerSettingsSave": "Зберегти",
|
||||
"ControllerSettingsClose": "Закрити",
|
||||
"KeyUnknown": "Unknown",
|
||||
"KeyShiftLeft": "Shift Left",
|
||||
"KeyShiftRight": "Shift Right",
|
||||
"KeyControlLeft": "Ctrl Left",
|
||||
"KeyMacControlLeft": "⌃ Left",
|
||||
"KeyControlRight": "Ctrl Right",
|
||||
"KeyMacControlRight": "⌃ Right",
|
||||
"KeyAltLeft": "Alt Left",
|
||||
"KeyMacAltLeft": "⌥ Left",
|
||||
"KeyAltRight": "Alt Right",
|
||||
"KeyMacAltRight": "⌥ Right",
|
||||
"KeyWinLeft": "⊞ Left",
|
||||
"KeyMacWinLeft": "⌘ Left",
|
||||
"KeyWinRight": "⊞ Right",
|
||||
"KeyMacWinRight": "⌘ Right",
|
||||
"KeyUnknown": "Невідома",
|
||||
"KeyShiftLeft": "Shift Лівий",
|
||||
"KeyShiftRight": "Shift Правий",
|
||||
"KeyControlLeft": "Ctrl Лівий",
|
||||
"KeyMacControlLeft": "⌃ Лівий",
|
||||
"KeyControlRight": "Ctrl Правий",
|
||||
"KeyMacControlRight": "⌃ Правий",
|
||||
"KeyAltLeft": "Alt Лівий",
|
||||
"KeyMacAltLeft": "⌥ Лівий",
|
||||
"KeyAltRight": "Alt Правий",
|
||||
"KeyMacAltRight": "⌥ Правий",
|
||||
"KeyWinLeft": "⊞ Лівий",
|
||||
"KeyMacWinLeft": "⌘ Лівий",
|
||||
"KeyWinRight": "⊞ Правий",
|
||||
"KeyMacWinRight": "⌘ Правий",
|
||||
"KeyMenu": "Menu",
|
||||
"KeyUp": "Up",
|
||||
"KeyDown": "Down",
|
||||
"KeyLeft": "Left",
|
||||
"KeyRight": "Right",
|
||||
"KeyLeft": "Вліво",
|
||||
"KeyRight": "Вправо",
|
||||
"KeyEnter": "Enter",
|
||||
"KeyEscape": "Escape",
|
||||
"KeySpace": "Space",
|
||||
"KeySpace": "Пробіл",
|
||||
"KeyTab": "Tab",
|
||||
"KeyBackSpace": "Backspace",
|
||||
"KeyInsert": "Insert",
|
||||
@@ -327,7 +338,7 @@
|
||||
"KeyPrintScreen": "Print Screen",
|
||||
"KeyPause": "Pause",
|
||||
"KeyNumLock": "Num Lock",
|
||||
"KeyClear": "Clear",
|
||||
"KeyClear": "Очистити",
|
||||
"KeyKeypad0": "Keypad 0",
|
||||
"KeyKeypad1": "Keypad 1",
|
||||
"KeyKeypad2": "Keypad 2",
|
||||
@@ -366,7 +377,7 @@
|
||||
"KeyPeriod": ".",
|
||||
"KeySlash": "/",
|
||||
"KeyBackSlash": "\\",
|
||||
"KeyUnbound": "Unbound",
|
||||
"KeyUnbound": "Відв'язати",
|
||||
"GamepadLeftStick": "L Stick Button",
|
||||
"GamepadRightStick": "R Stick Button",
|
||||
"GamepadLeftShoulder": "Left Shoulder",
|
||||
@@ -446,7 +457,7 @@
|
||||
"DialogExitSubMessage": "Усі незбережені дані буде втрачено!",
|
||||
"DialogMessageCreateSaveErrorMessage": "Під час створення вказаних даних збереження сталася помилка: {0}",
|
||||
"DialogMessageFindSaveErrorMessage": "Під час пошуку вказаних даних збереження сталася помилка: {0}",
|
||||
"FolderDialogExtractTitle": "Виберіть папку для видобування",
|
||||
"FolderDialogExtractTitle": "Виберіть теку для видобування",
|
||||
"DialogNcaExtractionMessage": "Видобування розділу {0} з {1}...",
|
||||
"DialogNcaExtractionTitle": "Екстрактор розділів NCA",
|
||||
"DialogNcaExtractionMainNcaNotFoundErrorMessage": "Помилка видобування. Основний NCA не був присутній у вибраному файлі.",
|
||||
@@ -550,15 +561,17 @@
|
||||
"MenuBarOptionsPauseEmulation": "Пауза",
|
||||
"MenuBarOptionsResumeEmulation": "Продовжити",
|
||||
"AboutUrlTooltipMessage": "Натисніть, щоб відкрити сайт Ryujinx у браузері за замовчування.",
|
||||
"AboutDisclaimerMessage": "Ryujinx жодним чином не пов’язано з Nintendo™,\nчи будь-яким із їхніх партнерів.",
|
||||
"AboutDisclaimerMessage": "Ryujinx жодним чином не пов’язаний з Nintendo™,\nчи будь-яким із їхніх партнерів.",
|
||||
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com) використовується в нашій емуляції Amiibo.",
|
||||
"AboutPatreonUrlTooltipMessage": "Натисніть, щоб відкрити сторінку Patreon Ryujinx у вашому браузері за замовчування.",
|
||||
"AboutGithubUrlTooltipMessage": "Натисніть, щоб відкрити сторінку GitHub Ryujinx у браузері за замовчуванням.",
|
||||
"AboutDiscordUrlTooltipMessage": "Натисніть, щоб відкрити запрошення на сервер Discord Ryujinx у браузері за замовчуванням.",
|
||||
"AboutTwitterUrlTooltipMessage": "Натисніть, щоб відкрити сторінку Twitter Ryujinx у браузері за замовчуванням.",
|
||||
"AboutRyujinxAboutTitle": "Про програму:",
|
||||
"AboutRyujinxAboutContent": "Ryujinx is an emulator for the Nintendo Switch™.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
|
||||
"AboutRyujinxAboutContent": "Ryujinx — це емулятор для Nintendo Switch™.\nБудь ласка, підтримайте нас на Patreon.\nОтримуйте всі останні новини в нашому Twitter або Discord.\nРозробники, які хочуть зробити внесок, можуть дізнатися більше на нашому GitHub або в Discord.",
|
||||
"AboutRyujinxMaintainersTitle": "Підтримується:",
|
||||
"AboutRyujinxFormerMaintainersTitle": "Formerly Maintained By:",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "Натисніть, щоб відкрити сторінку співавторів у вашому браузері за замовчування.",
|
||||
"AboutRyujinxSupprtersTitle": "Підтримується на Patreon:",
|
||||
"AmiiboSeriesLabel": "Серія Amiibo",
|
||||
"AmiiboCharacterLabel": "Персонаж",
|
||||
"AmiiboScanButtonLabel": "Сканувати",
|
||||
@@ -585,8 +598,8 @@
|
||||
"AddGameDirBoxTooltip": "Введіть каталог ігор, щоб додати до списку",
|
||||
"AddGameDirTooltip": "Додати каталог гри до списку",
|
||||
"RemoveGameDirTooltip": "Видалити вибраний каталог гри",
|
||||
"AddAutoloadDirBoxTooltip": "Enter an autoload directory to add to the list",
|
||||
"AddAutoloadDirTooltip": "Add an autoload directory to the list",
|
||||
"AddAutoloadDirBoxTooltip": "Введіть шлях автозавантаження для додавання до списку",
|
||||
"AddAutoloadDirTooltip": "Додайте шлях автозавантаження для додавання до списку",
|
||||
"RemoveAutoloadDirTooltip": "Remove selected autoload directory",
|
||||
"CustomThemeCheckTooltip": "Використовуйте користувацьку тему Avalonia для графічного інтерфейсу, щоб змінити вигляд меню емулятора",
|
||||
"CustomThemePathTooltip": "Шлях до користувацької теми графічного інтерфейсу",
|
||||
@@ -633,10 +646,10 @@
|
||||
"DebugLogTooltip": "Друкує повідомлення журналу налагодження на консолі.\n\nВикористовуйте це лише за спеціальною вказівкою співробітника, оскільки це ускладнить читання журналів і погіршить роботу емулятора.",
|
||||
"LoadApplicationFileTooltip": "Відкриває файловий провідник, щоб вибрати для завантаження сумісний файл Switch",
|
||||
"LoadApplicationFolderTooltip": "Відкриває файловий провідник, щоб вибрати сумісну з комутатором розпаковану програму для завантаження",
|
||||
"LoadDlcFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load DLC from",
|
||||
"LoadTitleUpdatesFromFolderTooltip": "Open a file explorer to choose one or more folders to bulk load title updates from",
|
||||
"OpenRyujinxFolderTooltip": "Відкриває папку файлової системи Ryujinx",
|
||||
"OpenRyujinxLogsTooltip": "Відкриває папку, куди записуються журнали",
|
||||
"LoadDlcFromFolderTooltip": "Відкрийте провідник файлів, щоб вибрати одну або кілька папок для масового завантаження DLC",
|
||||
"LoadTitleUpdatesFromFolderTooltip": "Відкрийте провідник файлів, щоб вибрати одну або кілька папок для масового завантаження оновлень заголовків",
|
||||
"OpenRyujinxFolderTooltip": "Відкриває теку файлової системи Ryujinx",
|
||||
"OpenRyujinxLogsTooltip": "Відкриває теку, куди записуються журнали",
|
||||
"ExitTooltip": "Виходить з Ryujinx",
|
||||
"OpenSettingsTooltip": "Відкриває вікно налаштувань",
|
||||
"OpenProfileManagerTooltip": "Відкриває вікно диспетчера профілів користувачів",
|
||||
@@ -692,8 +705,8 @@
|
||||
"TitleXCIStatusTrimmableLabel": "Untrimmed",
|
||||
"TitleXCIStatusUntrimmableLabel": "Trimmed",
|
||||
"TitleXCIStatusFailedLabel": "(Failed)",
|
||||
"TitleXCICanSaveLabel": "Save {0:n0} Mb",
|
||||
"TitleXCISavingLabel": "Saved {0:n0} Mb",
|
||||
"TitleXCICanSaveLabel": "Зберегти {0:n0} Мб",
|
||||
"TitleXCISavingLabel": "Збережено {0:n0} Мб",
|
||||
"RyujinxInfo": "Ryujin x - Інформація",
|
||||
"RyujinxConfirm": "Ryujinx - Підтвердження",
|
||||
"FileDialogAllTypes": "Всі типи",
|
||||
@@ -701,8 +714,8 @@
|
||||
"SwkbdMinCharacters": "Мінімальна кількість символів: {0}",
|
||||
"SwkbdMinRangeCharacters": "Має бути {0}-{1} символів",
|
||||
"CabinetTitle": "Cabinet Dialog",
|
||||
"CabinetDialog": "Enter your Amiibo's new name",
|
||||
"CabinetScanDialog": "Please scan your Amiibo now.",
|
||||
"CabinetDialog": "Вкажіть ваше нове ім'я Amiibo",
|
||||
"CabinetScanDialog": "Проскануйте ваш Amiibo будь ласка.",
|
||||
"SoftwareKeyboard": "Програмна клавіатура",
|
||||
"SoftwareKeyboardModeNumeric": "Повинно бути лише 0-9 або “.”",
|
||||
"SoftwareKeyboardModeAlphabet": "Повинно бути лише не CJK-символи",
|
||||
@@ -730,12 +743,15 @@
|
||||
"AllSupportedFormats": "Усі підтримувані формати",
|
||||
"RyujinxUpdater": "Програма оновлення Ryujinx",
|
||||
"SettingsTabHotkeys": "Гарячі клавіші клавіатури",
|
||||
"SettingsTabHotkeysToggleVSyncModeHotkey": "Перемкнути VSync режим:",
|
||||
"SettingsTabHotkeysHotkeys": "Гарячі клавіші клавіатури",
|
||||
"SettingsTabHotkeysToggleVsyncHotkey": "Увімк/вимк вертикальну синхронізацію:",
|
||||
"SettingsTabHotkeysScreenshotHotkey": "Знімок екрана:",
|
||||
"SettingsTabHotkeysShowUiHotkey": "Показати інтерфейс:",
|
||||
"SettingsTabHotkeysPauseHotkey": "Пауза:",
|
||||
"SettingsTabHotkeysToggleMuteHotkey": "Вимкнути звук:",
|
||||
"SettingsTabHotkeysIncrementCustomVSyncIntervalHotkey": "Підвищити користувацьку частоту оновлення",
|
||||
"SettingsTabHotkeysDecrementCustomVSyncIntervalHotkey": "Понизити користувацьку частоту оновлення",
|
||||
"ControllerMotionTitle": "Налаштування керування рухом",
|
||||
"ControllerRumbleTitle": "Налаштування вібрації",
|
||||
"SettingsSelectThemeFileDialogTitle": "Виберіть файл теми",
|
||||
@@ -748,19 +764,19 @@
|
||||
"SelectDlcDialogTitle": "Виберіть файли DLC",
|
||||
"SelectUpdateDialogTitle": "Виберіть файли оновлення",
|
||||
"SelectModDialogTitle": "Виберіть теку з модами",
|
||||
"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",
|
||||
"TrimXCIFileDialogTitle": "Перевірити та Обрізати XCI файл",
|
||||
"TrimXCIFileDialogPrimaryText": "Ця функція спочатку перевірить вільний простір, а потім обрізатиме файл XCI для економії місця на диску.",
|
||||
"TrimXCIFileDialogSecondaryText": "Поточний розмір файла: {0:n} MB\nGame Data Size: {1:n} MB\nDisk Space Savings: {2:n} MB",
|
||||
"TrimXCIFileNoTrimNecessary": "XCI файл не потребує обрізання. Перевірте журнали для додаткової інформації",
|
||||
"TrimXCIFileNoUntrimPossible": "XCI файл не може бути обрізаний. Перевірте журнали для додаткової інформації",
|
||||
"TrimXCIFileReadOnlyFileCannotFix": "XCI файл Тільки для Читання і не може бути прочитаним. Перевірте журнали додаткової інформації",
|
||||
"TrimXCIFileFileSizeChanged": "Розмір файлу XCI змінився з моменту сканування. Перевірте, чи не записується файл, і спробуйте знову.",
|
||||
"TrimXCIFileFreeSpaceCheckFailed": "Файл XCI містить дані в зоні вільного простору, тому обрізка небезпечна",
|
||||
"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",
|
||||
"TrimXCIFileFailedPrimaryText": "Не вдалося обрізати файл XCI",
|
||||
"TrimXCIFileCancelled": "Операція перервана",
|
||||
"TrimXCIFileFileUndertermined": "Операція не проводилася",
|
||||
"UserProfileWindowTitle": "Менеджер профілів користувачів",
|
||||
"CheatWindowTitle": "Менеджер читів",
|
||||
"DlcWindowTitle": "Менеджер вмісту для завантаження",
|
||||
@@ -771,27 +787,27 @@
|
||||
"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",
|
||||
"XCITrimmerTitleStatusFailed": "Невдача",
|
||||
"XCITrimmerPotentialSavings": "Потенційна економія",
|
||||
"XCITrimmerActualSavings": "Зекономлено",
|
||||
"XCITrimmerSavingsMb": "{0:n0} Mb",
|
||||
"XCITrimmerSelectDisplayed": "Select Shown",
|
||||
"XCITrimmerDeselectDisplayed": "Deselect Shown",
|
||||
"XCITrimmerSortName": "Title",
|
||||
"XCITrimmerSortSaved": "Space Savings",
|
||||
"XCITrimmerTrim": "Trim",
|
||||
"XCITrimmerUntrim": "Untrim",
|
||||
"UpdateWindowUpdateAddedMessage": "{0} new update(s) added",
|
||||
"UpdateWindowBundledContentNotice": "Bundled updates cannot be removed, only disabled.",
|
||||
"XCITrimmerSortName": "Заголовок",
|
||||
"XCITrimmerSortSaved": "Економія місця",
|
||||
"XCITrimmerTrim": "Обрізка",
|
||||
"XCITrimmerUntrim": "Зшивання",
|
||||
"UpdateWindowUpdateAddedMessage": "{0} нове оновлення додано",
|
||||
"UpdateWindowBundledContentNotice": "Вбудовані оновлення не можуть бути видалені, лише вимкнені.",
|
||||
"CheatWindowHeading": "Коди доступні для {0} [{1}]",
|
||||
"BuildId": "ID збірки:",
|
||||
"DlcWindowBundledContentNotice": "Bundled DLC cannot be removed, only disabled.",
|
||||
"DlcWindowBundledContentNotice": "Вбудований DLC не може бути видаленим, лише вимкненим.",
|
||||
"DlcWindowHeading": "{0} DLC(s) available",
|
||||
"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",
|
||||
"DlcWindowDlcAddedMessage": "{0} новий завантажувальний вміст додано",
|
||||
"AutoloadDlcAddedMessage": "{0} новий завантажувальний вміст додано",
|
||||
"AutoloadDlcRemovedMessage": "{0} відсутній завантажуваний вміст видалено.",
|
||||
"AutoloadUpdateAddedMessage": "{0} нове оновлення додано",
|
||||
"AutoloadUpdateRemovedMessage": "{0} відсутнє оновлення видалено",
|
||||
"ModWindowHeading": "{0} мод(ів)",
|
||||
"UserProfilesEditProfile": "Редагувати вибране",
|
||||
"Continue": "Continue",
|
||||
@@ -832,7 +848,7 @@
|
||||
"Name": "Назва",
|
||||
"Size": "Розмір",
|
||||
"Search": "Пошук",
|
||||
"UserProfilesRecoverLostAccounts": "Відновлення втрачених облікових записів",
|
||||
"UserProfilesRecoverLostAccounts": "Відновлення профілів",
|
||||
"Recover": "Відновити",
|
||||
"UserProfilesRecoverHeading": "Знайдено збереження для наступних облікових записів",
|
||||
"UserProfilesRecoverEmptyList": "Немає профілів для відновлення",
|
||||
@@ -864,15 +880,15 @@
|
||||
"MultiplayerModeDisabled": "Вимкнено",
|
||||
"MultiplayerModeLdnMitm": "ldn_mitm",
|
||||
"MultiplayerModeLdnRyu": "RyuLDN",
|
||||
"MultiplayerDisableP2P": "Disable P2P Network Hosting (may increase latency)",
|
||||
"MultiplayerDisableP2PTooltip": "Disable P2P network hosting, peers will proxy through the master server instead of connecting to you directly.",
|
||||
"LdnPassphrase": "Network Passphrase:",
|
||||
"LdnPassphraseTooltip": "You will only be able to see hosted games with the same passphrase as you.",
|
||||
"LdnPassphraseInputTooltip": "Enter a passphrase in the format Ryujinx-<8 hex chars>. You will only be able to see hosted games with the same passphrase as you.",
|
||||
"LdnPassphraseInputPublic": "(public)",
|
||||
"GenLdnPass": "Generate Random",
|
||||
"GenLdnPassTooltip": "Generates a new passphrase, which can be shared with other players.",
|
||||
"ClearLdnPass": "Clear",
|
||||
"ClearLdnPassTooltip": "Clears the current passphrase, returning to the public network.",
|
||||
"InvalidLdnPassphrase": "Invalid Passphrase! Must be in the format \"Ryujinx-<8 hex chars>\""
|
||||
"MultiplayerDisableP2P": "Вимкнути хостинг P2P мережі (може збільшити затримку)",
|
||||
"MultiplayerDisableP2PTooltip": "Вимкнути хостинг P2P мережі, піри будуть підключатися через майстер-сервер замість прямого з'єднання з вами.",
|
||||
"LdnPassphrase": "Мережевий пароль:",
|
||||
"LdnPassphraseTooltip": "Ви зможете бачити лише ті ігри, які мають такий самий пароль, як і у вас.",
|
||||
"LdnPassphraseInputTooltip": "Введіть пароль у форматі Ryujinx-<8 символів>. Ви зможете бачити лише ті ігри, які мають такий самий пароль, як і у вас.",
|
||||
"LdnPassphraseInputPublic": "(публічний)",
|
||||
"GenLdnPass": "Згенерувати випадкову",
|
||||
"GenLdnPassTooltip": "Генерує новий пароль, яким можна поділитися з іншими гравцями.",
|
||||
"ClearLdnPass": "Очистити",
|
||||
"ClearLdnPassTooltip": "Очищає поточну пароль, повертаючись до публічної мережі.",
|
||||
"InvalidLdnPassphrase": "Невірний пароль! Має бути в форматі \"Ryujinx-<8 символів>\""
|
||||
}
|
||||
|
||||
@@ -552,13 +552,15 @@
|
||||
"AboutUrlTooltipMessage": "在浏览器中打开 Ryujinx 模拟器官网。",
|
||||
"AboutDisclaimerMessage": "Ryujinx 与 Nintendo™ 以及其合作伙伴没有任何关联。",
|
||||
"AboutAmiiboDisclaimerMessage": "我们的 Amiibo 模拟使用了\nAmiiboAPI (www.amiiboapi.com)。",
|
||||
"AboutPatreonUrlTooltipMessage": "在浏览器中打开 Ryujinx 的 Patreon 赞助页。",
|
||||
"AboutGithubUrlTooltipMessage": "在浏览器中打开 Ryujinx 的 GitHub 代码库。",
|
||||
"AboutDiscordUrlTooltipMessage": "在浏览器中打开 Ryujinx 的 Discord 邀请链接。",
|
||||
"AboutTwitterUrlTooltipMessage": "在浏览器中打开 Ryujinx 的 Twitter 主页。",
|
||||
"AboutRyujinxAboutTitle": "关于:",
|
||||
"AboutRyujinxAboutContent": "Ryujinx is an emulator for the Nintendo Switch™.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
|
||||
"AboutRyujinxAboutContent": "Ryujinx 是一款 Nintendo Switch™ 模拟器。\n您可以在 Patreon 上赞助 Ryujinx。\n关注 Twitter 或 Discord 可以获取模拟器最新动态。\n如果您对开发感兴趣,欢迎来 GitHub 或 Discord 加入我们!",
|
||||
"AboutRyujinxMaintainersTitle": "开发维护人员名单:",
|
||||
"AboutRyujinxFormerMaintainersTitle": "Formerly Maintained By:",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "在浏览器中打开贡献者页面",
|
||||
"AboutRyujinxSupprtersTitle": "感谢 Patreon 上的赞助者:",
|
||||
"AmiiboSeriesLabel": "Amiibo 系列",
|
||||
"AmiiboCharacterLabel": "角色",
|
||||
"AmiiboScanButtonLabel": "扫描",
|
||||
|
||||
@@ -552,13 +552,15 @@
|
||||
"AboutUrlTooltipMessage": "在預設瀏覽器中開啟 Ryujinx 網站。",
|
||||
"AboutDisclaimerMessage": "Ryujinx 和 Nintendo™\n或其任何合作夥伴完全沒有關聯。",
|
||||
"AboutAmiiboDisclaimerMessage": "我們在 Amiibo 模擬中\n使用了 AmiiboAPI (www.amiiboapi.com)。",
|
||||
"AboutPatreonUrlTooltipMessage": "在預設瀏覽器中開啟 Ryujinx 的 Patreon 網頁。",
|
||||
"AboutGithubUrlTooltipMessage": "在預設瀏覽器中開啟 Ryujinx 的 GitHub 網頁。",
|
||||
"AboutDiscordUrlTooltipMessage": "在預設瀏覽器中開啟 Ryujinx 的 Discord 邀請連結。",
|
||||
"AboutTwitterUrlTooltipMessage": "在預設瀏覽器中開啟 Ryujinx 的 Twitter 網頁。",
|
||||
"AboutRyujinxAboutTitle": "關於:",
|
||||
"AboutRyujinxAboutContent": "Ryujinx is an emulator for the Nintendo Switch™.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
|
||||
"AboutRyujinxAboutContent": "Ryujinx 是一款 Nintendo Switch™ 模擬器。\n請在 Patreon 上支持我們。\n關注我們的 Twitter 或 Discord 取得所有最新消息。\n對於有興趣貢獻的開發者,可以在我們的 GitHub 或 Discord 上了解更多資訊。",
|
||||
"AboutRyujinxMaintainersTitle": "維護者:",
|
||||
"AboutRyujinxFormerMaintainersTitle": "Formerly Maintained By:",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "在預設瀏覽器中開啟貢獻者的網頁",
|
||||
"AboutRyujinxSupprtersTitle": "Patreon 支持者:",
|
||||
"AmiiboSeriesLabel": "Amiibo 系列",
|
||||
"AmiiboCharacterLabel": "角色",
|
||||
"AmiiboScanButtonLabel": "掃描",
|
||||
|
||||
24
src/Ryujinx/Common/XCIFileTrimmerMainWindowLog.cs
Normal file
24
src/Ryujinx/Common/XCIFileTrimmerMainWindowLog.cs
Normal 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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
23
src/Ryujinx/Common/XCIFileTrimmerWindowLog.cs
Normal file
23
src/Ryujinx/Common/XCIFileTrimmerWindowLog.cs
Normal 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));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
using Avalonia.Threading;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
|
||||
namespace Ryujinx.Ava.Common
|
||||
{
|
||||
public static class XCITrimmerLog
|
||||
{
|
||||
internal class MainWindow : Ryujinx.Common.Logging.XCIFileTrimmerLog
|
||||
{
|
||||
private readonly MainWindowViewModel _viewModel;
|
||||
|
||||
public MainWindow(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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
internal class TrimmerWindow : Ryujinx.Common.Logging.XCIFileTrimmerLog
|
||||
{
|
||||
private readonly XCITrimmerViewModel _viewModel;
|
||||
|
||||
public TrimmerWindow(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));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,361 +0,0 @@
|
||||
using DiscordRPC;
|
||||
using LibHac.Tools.FsSystem;
|
||||
using Ryujinx.Audio.Backends.SDL2;
|
||||
using Ryujinx.Ava;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
||||
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.GAL.Multithreading;
|
||||
using Ryujinx.Graphics.OpenGL;
|
||||
using Ryujinx.Graphics.Vulkan;
|
||||
using Ryujinx.HLE;
|
||||
using Ryujinx.Input;
|
||||
using Ryujinx.UI.Common;
|
||||
using Ryujinx.UI.Common.Configuration;
|
||||
using Silk.NET.Vulkan;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
|
||||
using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
|
||||
using Key = Ryujinx.Common.Configuration.Hid.Key;
|
||||
|
||||
namespace Ryujinx.Headless
|
||||
{
|
||||
public partial class HeadlessRyujinx
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
// Ensure Discord presence timestamp begins at the absolute start of when Ryujinx is launched
|
||||
DiscordIntegrationModule.StartedAt = Timestamps.Now;
|
||||
|
||||
// Delete backup files after updating.
|
||||
Task.Run(Updater.CleanupUpdate);
|
||||
|
||||
// Hook unhandled exception and process exit events.
|
||||
AppDomain.CurrentDomain.UnhandledException += (sender, e)
|
||||
=> Program.ProcessUnhandledException(sender, e.ExceptionObject as Exception, e.IsTerminating);
|
||||
AppDomain.CurrentDomain.ProcessExit += (_, _) => Program.Exit();
|
||||
|
||||
// Initialize the configuration.
|
||||
ConfigurationState.Initialize();
|
||||
|
||||
// Initialize Discord integration.
|
||||
DiscordIntegrationModule.Initialize();
|
||||
|
||||
// Logging system information.
|
||||
Program.PrintSystemInfo();
|
||||
}
|
||||
|
||||
private static InputConfig HandlePlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index)
|
||||
{
|
||||
if (inputId == null)
|
||||
{
|
||||
if (index == PlayerIndex.Player1)
|
||||
{
|
||||
Logger.Info?.Print(LogClass.Application, $"{index} not configured, defaulting to default keyboard.");
|
||||
|
||||
// Default to keyboard
|
||||
inputId = "0";
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Info?.Print(LogClass.Application, $"{index} not configured");
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
IGamepad gamepad = _inputManager.KeyboardDriver.GetGamepad(inputId);
|
||||
|
||||
bool isKeyboard = true;
|
||||
|
||||
if (gamepad == null)
|
||||
{
|
||||
gamepad = _inputManager.GamepadDriver.GetGamepad(inputId);
|
||||
isKeyboard = false;
|
||||
|
||||
if (gamepad == null)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"{index} gamepad not found (\"{inputId}\")");
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
string gamepadName = gamepad.Name;
|
||||
|
||||
gamepad.Dispose();
|
||||
|
||||
InputConfig config;
|
||||
|
||||
if (inputProfileName == null || inputProfileName.Equals("default"))
|
||||
{
|
||||
if (isKeyboard)
|
||||
{
|
||||
config = new StandardKeyboardInputConfig
|
||||
{
|
||||
Version = InputConfig.CurrentVersion,
|
||||
Backend = InputBackendType.WindowKeyboard,
|
||||
Id = null,
|
||||
ControllerType = ControllerType.JoyconPair,
|
||||
LeftJoycon = new LeftJoyconCommonConfig<Key>
|
||||
{
|
||||
DpadUp = Key.Up,
|
||||
DpadDown = Key.Down,
|
||||
DpadLeft = Key.Left,
|
||||
DpadRight = Key.Right,
|
||||
ButtonMinus = Key.Minus,
|
||||
ButtonL = Key.E,
|
||||
ButtonZl = Key.Q,
|
||||
ButtonSl = Key.Unbound,
|
||||
ButtonSr = Key.Unbound,
|
||||
},
|
||||
|
||||
LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
|
||||
{
|
||||
StickUp = Key.W,
|
||||
StickDown = Key.S,
|
||||
StickLeft = Key.A,
|
||||
StickRight = Key.D,
|
||||
StickButton = Key.F,
|
||||
},
|
||||
|
||||
RightJoycon = new RightJoyconCommonConfig<Key>
|
||||
{
|
||||
ButtonA = Key.Z,
|
||||
ButtonB = Key.X,
|
||||
ButtonX = Key.C,
|
||||
ButtonY = Key.V,
|
||||
ButtonPlus = Key.Plus,
|
||||
ButtonR = Key.U,
|
||||
ButtonZr = Key.O,
|
||||
ButtonSl = Key.Unbound,
|
||||
ButtonSr = Key.Unbound,
|
||||
},
|
||||
|
||||
RightJoyconStick = new JoyconConfigKeyboardStick<Key>
|
||||
{
|
||||
StickUp = Key.I,
|
||||
StickDown = Key.K,
|
||||
StickLeft = Key.J,
|
||||
StickRight = Key.L,
|
||||
StickButton = Key.H,
|
||||
},
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isNintendoStyle = gamepadName.Contains("Nintendo");
|
||||
|
||||
config = new StandardControllerInputConfig
|
||||
{
|
||||
Version = InputConfig.CurrentVersion,
|
||||
Backend = InputBackendType.GamepadSDL2,
|
||||
Id = null,
|
||||
ControllerType = ControllerType.JoyconPair,
|
||||
DeadzoneLeft = 0.1f,
|
||||
DeadzoneRight = 0.1f,
|
||||
RangeLeft = 1.0f,
|
||||
RangeRight = 1.0f,
|
||||
TriggerThreshold = 0.5f,
|
||||
LeftJoycon = new LeftJoyconCommonConfig<ConfigGamepadInputId>
|
||||
{
|
||||
DpadUp = ConfigGamepadInputId.DpadUp,
|
||||
DpadDown = ConfigGamepadInputId.DpadDown,
|
||||
DpadLeft = ConfigGamepadInputId.DpadLeft,
|
||||
DpadRight = ConfigGamepadInputId.DpadRight,
|
||||
ButtonMinus = ConfigGamepadInputId.Minus,
|
||||
ButtonL = ConfigGamepadInputId.LeftShoulder,
|
||||
ButtonZl = ConfigGamepadInputId.LeftTrigger,
|
||||
ButtonSl = ConfigGamepadInputId.Unbound,
|
||||
ButtonSr = ConfigGamepadInputId.Unbound,
|
||||
},
|
||||
|
||||
LeftJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
|
||||
{
|
||||
Joystick = ConfigStickInputId.Left,
|
||||
StickButton = ConfigGamepadInputId.LeftStick,
|
||||
InvertStickX = false,
|
||||
InvertStickY = false,
|
||||
Rotate90CW = false,
|
||||
},
|
||||
|
||||
RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
|
||||
{
|
||||
ButtonA = isNintendoStyle ? ConfigGamepadInputId.A : ConfigGamepadInputId.B,
|
||||
ButtonB = isNintendoStyle ? ConfigGamepadInputId.B : ConfigGamepadInputId.A,
|
||||
ButtonX = isNintendoStyle ? ConfigGamepadInputId.X : ConfigGamepadInputId.Y,
|
||||
ButtonY = isNintendoStyle ? ConfigGamepadInputId.Y : ConfigGamepadInputId.X,
|
||||
ButtonPlus = ConfigGamepadInputId.Plus,
|
||||
ButtonR = ConfigGamepadInputId.RightShoulder,
|
||||
ButtonZr = ConfigGamepadInputId.RightTrigger,
|
||||
ButtonSl = ConfigGamepadInputId.Unbound,
|
||||
ButtonSr = ConfigGamepadInputId.Unbound,
|
||||
},
|
||||
|
||||
RightJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
|
||||
{
|
||||
Joystick = ConfigStickInputId.Right,
|
||||
StickButton = ConfigGamepadInputId.RightStick,
|
||||
InvertStickX = false,
|
||||
InvertStickY = false,
|
||||
Rotate90CW = false,
|
||||
},
|
||||
|
||||
Motion = new StandardMotionConfigController
|
||||
{
|
||||
MotionBackend = MotionInputBackendType.GamepadDriver,
|
||||
EnableMotion = true,
|
||||
Sensitivity = 100,
|
||||
GyroDeadzone = 1,
|
||||
},
|
||||
Rumble = new RumbleConfigController
|
||||
{
|
||||
StrongRumble = 1f,
|
||||
WeakRumble = 1f,
|
||||
EnableRumble = false,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string profileBasePath;
|
||||
|
||||
if (isKeyboard)
|
||||
{
|
||||
profileBasePath = Path.Combine(AppDataManager.ProfilesDirPath, "keyboard");
|
||||
}
|
||||
else
|
||||
{
|
||||
profileBasePath = Path.Combine(AppDataManager.ProfilesDirPath, "controller");
|
||||
}
|
||||
|
||||
string path = Path.Combine(profileBasePath, inputProfileName + ".json");
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Input profile \"{inputProfileName}\" not found for \"{inputId}\"");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
config = JsonHelper.DeserializeFromFile(path, _serializerContext.InputConfig);
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Input profile \"{inputProfileName}\" parsing failed for \"{inputId}\"");
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
config.Id = inputId;
|
||||
config.PlayerIndex = index;
|
||||
|
||||
string inputTypeName = isKeyboard ? "Keyboard" : "Gamepad";
|
||||
|
||||
Logger.Info?.Print(LogClass.Application, $"{config.PlayerIndex} configured with {inputTypeName} \"{config.Id}\"");
|
||||
|
||||
// If both stick ranges are 0 (usually indicative of an outdated profile load) then both sticks will be set to 1.0.
|
||||
if (config is StandardControllerInputConfig controllerConfig)
|
||||
{
|
||||
if (controllerConfig.RangeLeft <= 0.0f && controllerConfig.RangeRight <= 0.0f)
|
||||
{
|
||||
controllerConfig.RangeLeft = 1.0f;
|
||||
controllerConfig.RangeRight = 1.0f;
|
||||
|
||||
Logger.Info?.Print(LogClass.Application, $"{config.PlayerIndex} stick range reset. Save the profile now to update your configuration");
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
private static IRenderer CreateRenderer(Options options, WindowBase window)
|
||||
{
|
||||
if (options.GraphicsBackend == GraphicsBackend.Vulkan && window is VulkanWindow vulkanWindow)
|
||||
{
|
||||
string preferredGpuId = string.Empty;
|
||||
Vk api = Vk.GetApi();
|
||||
|
||||
if (!string.IsNullOrEmpty(options.PreferredGPUVendor))
|
||||
{
|
||||
string preferredGpuVendor = options.PreferredGPUVendor.ToLowerInvariant();
|
||||
var devices = VulkanRenderer.GetPhysicalDevices(api);
|
||||
|
||||
foreach (var device in devices)
|
||||
{
|
||||
if (device.Vendor.ToLowerInvariant() == preferredGpuVendor)
|
||||
{
|
||||
preferredGpuId = device.Id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new VulkanRenderer(
|
||||
api,
|
||||
(instance, vk) => new SurfaceKHR((ulong)(vulkanWindow.CreateWindowSurface(instance.Handle))),
|
||||
vulkanWindow.GetRequiredInstanceExtensions,
|
||||
preferredGpuId);
|
||||
}
|
||||
|
||||
return new OpenGLRenderer();
|
||||
}
|
||||
|
||||
private static Switch InitializeEmulationContext(WindowBase window, IRenderer renderer, Options options)
|
||||
{
|
||||
BackendThreading threadingMode = options.BackendThreading;
|
||||
|
||||
bool threadedGAL = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading);
|
||||
|
||||
if (threadedGAL)
|
||||
{
|
||||
renderer = new ThreadedRenderer(renderer);
|
||||
}
|
||||
|
||||
HLEConfiguration configuration = new(_virtualFileSystem,
|
||||
_libHacHorizonManager,
|
||||
_contentManager,
|
||||
_accountManager,
|
||||
_userChannelPersistence,
|
||||
renderer,
|
||||
new SDL2HardwareDeviceDriver(),
|
||||
options.DramSize,
|
||||
window,
|
||||
options.SystemLanguage,
|
||||
options.SystemRegion,
|
||||
options.VSyncMode,
|
||||
!options.DisableDockedMode,
|
||||
!options.DisablePTC,
|
||||
options.EnableInternetAccess,
|
||||
!options.DisableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None,
|
||||
options.FsGlobalAccessLogMode,
|
||||
options.SystemTimeOffset,
|
||||
options.SystemTimeZone,
|
||||
options.MemoryManagerMode,
|
||||
options.IgnoreMissingServices,
|
||||
options.AspectRatio,
|
||||
options.AudioVolume,
|
||||
options.UseHypervisor ?? true,
|
||||
options.MultiplayerLanInterfaceId,
|
||||
Common.Configuration.Multiplayer.MultiplayerMode.Disabled,
|
||||
false,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
options.CustomVSyncInterval);
|
||||
|
||||
return new Switch(configuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.9 KiB |
@@ -14,7 +14,6 @@ using Ryujinx.Common.GraphicsDriver;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.SystemInterop;
|
||||
using Ryujinx.Graphics.Vulkan.MoltenVK;
|
||||
using Ryujinx.Headless;
|
||||
using Ryujinx.SDL2.Common;
|
||||
using Ryujinx.UI.App.Common;
|
||||
using Ryujinx.UI.Common;
|
||||
@@ -53,15 +52,9 @@ namespace Ryujinx.Ava
|
||||
}
|
||||
|
||||
PreviewerDetached = true;
|
||||
|
||||
if (args.Length > 0 && args[0] is "--no-gui" or "nogui")
|
||||
{
|
||||
HeadlessRyujinx.Entrypoint(args[1..]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Initialize(args);
|
||||
|
||||
|
||||
LoggerAdapter.Register();
|
||||
|
||||
IconProvider.Current
|
||||
@@ -113,7 +106,7 @@ namespace Ryujinx.Ava
|
||||
AppDomain.CurrentDomain.UnhandledException += (sender, e)
|
||||
=> ProcessUnhandledException(sender, e.ExceptionObject as Exception, e.IsTerminating);
|
||||
AppDomain.CurrentDomain.ProcessExit += (_, _) => Exit();
|
||||
|
||||
|
||||
// Setup base data directory.
|
||||
AppDataManager.Initialize(CommandLineState.BaseDirPathArg);
|
||||
|
||||
@@ -229,7 +222,7 @@ namespace Ryujinx.Ava
|
||||
UseHardwareAcceleration = CommandLineState.OverrideHardwareAcceleration.Value;
|
||||
}
|
||||
|
||||
internal static void PrintSystemInfo()
|
||||
private static void PrintSystemInfo()
|
||||
{
|
||||
Logger.Notice.Print(LogClass.Application, $"{App.FullAppName} Version: {Version}");
|
||||
SystemInfo.Gather().Print();
|
||||
@@ -246,7 +239,7 @@ namespace Ryujinx.Ava
|
||||
: $"Launch Mode: {AppDataManager.Mode}");
|
||||
}
|
||||
|
||||
internal static void ProcessUnhandledException(object sender, Exception ex, bool isTerminating)
|
||||
private static void ProcessUnhandledException(object sender, Exception ex, bool isTerminating)
|
||||
{
|
||||
Logger.Log log = Logger.Error ?? Logger.Notice;
|
||||
string message = $"Unhandled exception caught: {ex}";
|
||||
@@ -261,7 +254,7 @@ namespace Ryujinx.Ava
|
||||
Exit();
|
||||
}
|
||||
|
||||
internal static void Exit()
|
||||
public static void Exit()
|
||||
{
|
||||
DiscordIntegrationModule.Exit();
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
<PackageReference Include="Avalonia.Markup.Xaml.Loader" />
|
||||
<PackageReference Include="Avalonia.Svg" />
|
||||
<PackageReference Include="Avalonia.Svg.Skia" />
|
||||
<PackageReference Include="CommandLineParser" />
|
||||
<PackageReference Include="DynamicData" />
|
||||
<PackageReference Include="FluentAvaloniaUI" />
|
||||
<PackageReference Include="Projektanker.Icons.Avalonia" />
|
||||
@@ -163,7 +162,6 @@
|
||||
<EmbeddedResource Include="Assets\Icons\Controller_JoyConPair.svg" />
|
||||
<EmbeddedResource Include="Assets\Icons\Controller_JoyConRight.svg" />
|
||||
<EmbeddedResource Include="Assets\Icons\Controller_ProCon.svg" />
|
||||
<EmbeddedResource Include="Headless\Ryujinx.bmp" LogicalName="HeadlessLogo" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AdditionalFiles Include="Assets\Locales\en_US.json" />
|
||||
|
||||
@@ -45,9 +45,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public string Developers => "GreemDev";
|
||||
|
||||
public string FormerDevelopers => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.AboutPageDeveloperListMore, "gdkchan, Ac_K, marysaka, rip in peri peri, LDj3SNuD, emmaus, Thealexbarney, GoffyDude, TSRBerry, IsaacMarovitz");
|
||||
public string Developers => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.AboutPageDeveloperListMore, "gdkchan, Ac_K, marysaka, rip in peri peri, LDj3SNuD, emmaus, Thealexbarney, GoffyDude, TSRBerry, IsaacMarovitz, GreemDev");
|
||||
|
||||
public AboutWindowViewModel()
|
||||
{
|
||||
|
||||
@@ -402,7 +402,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public bool OpenDeviceSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.DeviceSaveDataSize > 0;
|
||||
|
||||
public bool TrimXCIEnabled => XCIFileTrimmer.CanTrim(SelectedApplication.Path, new XCITrimmerLog.MainWindow(this));
|
||||
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;
|
||||
|
||||
@@ -2165,7 +2165,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
return;
|
||||
}
|
||||
|
||||
var trimmer = new XCIFileTrimmer(filename, new XCITrimmerLog.MainWindow(this));
|
||||
var trimmer = new XCIFileTrimmer(filename, new Common.XCIFileTrimmerMainWindowLog(this));
|
||||
|
||||
if (trimmer.CanBeTrimmed)
|
||||
{
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
private const string _FileExtXCI = "XCI";
|
||||
|
||||
private readonly Ryujinx.Common.Logging.XCIFileTrimmerLog _logger;
|
||||
private ApplicationLibrary ApplicationLibrary => _mainWindowViewModel.ApplicationLibrary;
|
||||
private readonly ApplicationLibrary _applicationLibrary;
|
||||
private Optional<XCITrimmerFileModel> _processingApplication = null;
|
||||
private AvaloniaList<XCITrimmerFileModel> _allXCIFiles = new();
|
||||
private AvaloniaList<XCITrimmerFileModel> _selectedXCIFiles = new();
|
||||
@@ -47,14 +47,15 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public XCITrimmerViewModel(MainWindowViewModel mainWindowViewModel)
|
||||
{
|
||||
_logger = new XCITrimmerLog.TrimmerWindow(this);
|
||||
_logger = new XCIFileTrimmerWindowLog(this);
|
||||
_mainWindowViewModel = mainWindowViewModel;
|
||||
_applicationLibrary = _mainWindowViewModel.ApplicationLibrary;
|
||||
LoadXCIApplications();
|
||||
}
|
||||
|
||||
private void LoadXCIApplications()
|
||||
{
|
||||
var apps = ApplicationLibrary.Applications.Items
|
||||
var apps = _applicationLibrary.Applications.Items
|
||||
.Where(app => app.FileExtension == _FileExtXCI);
|
||||
|
||||
foreach (var xciApp in apps)
|
||||
@@ -67,7 +68,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
string path,
|
||||
OperationOutcome operationOutcome = OperationOutcome.Undetermined)
|
||||
{
|
||||
var xciApp = ApplicationLibrary.Applications.Items.First(app => app.FileExtension == _FileExtXCI && app.Path == path);
|
||||
var xciApp = _applicationLibrary.Applications.Items.First(app => app.FileExtension == _FileExtXCI && app.Path == path);
|
||||
return XCITrimmerFileModel.FromApplicationData(xciApp, _logger) with { ProcessingOutcome = operationOutcome };
|
||||
}
|
||||
|
||||
@@ -537,4 +538,4 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -165,16 +165,7 @@
|
||||
Text="{ext:Locale AboutRyujinxMaintainersTitle}" />
|
||||
<TextBlock
|
||||
FontSize="10"
|
||||
Margin="0, 0, 0, 5"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Developers}"/>
|
||||
<TextBlock
|
||||
FontSize="15"
|
||||
FontWeight="Bold"
|
||||
Text="{ext:Locale AboutRyujinxFormerMaintainersTitle}" />
|
||||
<TextBlock
|
||||
FontSize="10"
|
||||
Text="{Binding FormerDevelopers}"
|
||||
Text="{Binding Developers}"
|
||||
TextWrapping="Wrap" />
|
||||
<Button
|
||||
Padding="5"
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
PrimaryButtonText = string.Empty,
|
||||
SecondaryButtonText = string.Empty,
|
||||
CloseButtonText = LocaleManager.Instance[LocaleKeys.UserProfilesClose],
|
||||
Content = new AboutWindow()
|
||||
Content = new AboutWindow(),
|
||||
};
|
||||
|
||||
Style closeButton = new(x => x.Name("CloseButton"));
|
||||
|
||||
@@ -74,7 +74,14 @@ namespace Ryujinx.Ava
|
||||
_platformExt = $"linux_{arch}.tar.gz";
|
||||
}
|
||||
|
||||
if (!Version.TryParse(Program.Version, out Version currentVersion))
|
||||
Version newVersion;
|
||||
Version currentVersion;
|
||||
|
||||
try
|
||||
{
|
||||
currentVersion = Version.Parse(Program.Version);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to convert the current {App.FullAppName} version!");
|
||||
|
||||
@@ -157,7 +164,11 @@ namespace Ryujinx.Ava
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Version.TryParse(_buildVer, out Version newVersion))
|
||||
try
|
||||
{
|
||||
newVersion = Version.Parse(_buildVer);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to convert the received {App.FullAppName} version from GitHub!");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user