mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-06-28 00:16:23 +02:00
Merge branch ryujinx:master into fr-locale-update
This commit is contained in:
commit
c8a0644b08
14 changed files with 69 additions and 119 deletions
|
@ -42,6 +42,8 @@
|
|||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||
<PackageVersion Include="Ryujinx.LibHac" Version="0.20.0" />
|
||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
||||
<PackageVersion Include="Ryujinx.UpdateClient" Version="1.0.29" />
|
||||
<PackageVersion Include="Ryujinx.Systems.Update.Common" Version="1.0.29" />
|
||||
<PackageVersion Include="Gommon" Version="2.7.1.1" />
|
||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||
<PackageVersion Include="Sep" Version="0.6.0" />
|
||||
|
|
|
@ -13144,7 +13144,7 @@
|
|||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "无法转换从更新服务器接收的 Ryujinx 版本。",
|
||||
"zh_TW": "無法轉換從更新何服器接收的 Ryujinx 版本。"
|
||||
"zh_TW": "無法轉換從更新伺服器接收的 Ryujinx 版本。"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -23669,7 +23669,7 @@
|
|||
"tr_TR": "",
|
||||
"uk_UA": "Вимкнути хостинг P2P мережі, піри будуть підключатися через майстер-сервер замість прямого з'єднання з вами.",
|
||||
"zh_CN": "禁用 P2P 网络连接,对方将通过主服务器进行连接,而不是直接连接到您。",
|
||||
"zh_TW": "停用對等網路代管 (P2P Network Hosting), 用戶群會經過代理何服器而非直接連線至你的主機。"
|
||||
"zh_TW": "停用對等網路代管 (P2P Network Hosting), 用戶群會經過代理伺服器而非直接連線至你的主機。"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -10,11 +10,13 @@
|
|||
</packageSources>
|
||||
<packageSourceMapping>
|
||||
<!-- key value for <packageSource> should match key values from <packageSources> element -->
|
||||
<!-- These are defined and .NET still yells about multiple package sources with no mappings. Not sure what to do, this is in the docs lol -->
|
||||
<packageSource key="nuget.org">
|
||||
<package pattern="*" />
|
||||
</packageSource>
|
||||
<packageSource key="Ryujinx.UpdateClient">
|
||||
<package pattern="Ryujinx.UpdateClient" />
|
||||
<package pattern="Ryujinx.Systems.Update.Common" />
|
||||
</packageSource>
|
||||
<!--<packageSource key="LibHacAlpha">
|
||||
<package pattern="Ryujinx.LibHac" />
|
||||
|
|
|
@ -21,6 +21,21 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
|||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandCmif(3)] // 20.0.0+
|
||||
// CreateLibraryAppletEx(u32, u32, u64) -> object<nn::am::service::ILibraryAppletAccessor>
|
||||
public ResultCode CreateLibraryAppletEx(ServiceCtx context)
|
||||
{
|
||||
AppletId appletId = (AppletId)context.RequestData.ReadInt32();
|
||||
|
||||
_ = context.RequestData.ReadInt32(); // libraryAppletMode
|
||||
|
||||
_ = context.RequestData.ReadUInt64(); // threadId
|
||||
|
||||
MakeObject(context, new ILibraryAppletAccessor(appletId, context.Device.System));
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandCmif(10)]
|
||||
// CreateStorage(u64) -> object<nn::am::service::IStorage>
|
||||
public ResultCode CreateStorage(ServiceCtx context)
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
namespace Ryujinx.Ava.Common.Models.Github
|
||||
{
|
||||
public class GithubReleaseAssetJsonResponse
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string State { get; set; }
|
||||
public string BrowserDownloadUrl { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Ava.Common.Models.Github
|
||||
{
|
||||
public class GithubReleasesJsonResponse
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string TagName { get; set; }
|
||||
public List<GithubReleaseAssetJsonResponse> Assets { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Ryujinx.Ava.Common.Models.Github
|
||||
{
|
||||
[JsonSerializable(typeof(GithubReleasesJsonResponse), GenerationMode = JsonSourceGenerationMode.Metadata)]
|
||||
public partial class GithubReleasesJsonSerializerContext : JsonSerializerContext;
|
||||
}
|
|
@ -65,6 +65,8 @@
|
|||
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'win-arm64'" />
|
||||
<PackageReference Include="Ryujinx.UpdateClient" />
|
||||
<PackageReference Include="Ryujinx.Systems.Update.Common" />
|
||||
<PackageReference Include="securifybv.ShellLink" />
|
||||
<PackageReference Include="Sep" />
|
||||
<PackageReference Include="Silk.NET.Vulkan" />
|
||||
|
|
|
@ -75,6 +75,7 @@ namespace Ryujinx.Ava.Systems
|
|||
|
||||
private readonly long _ticksPerFrame;
|
||||
private readonly Stopwatch _chrono;
|
||||
private readonly Stopwatch _playTimer;
|
||||
private long _ticks;
|
||||
|
||||
private readonly AccountManager _accountManager;
|
||||
|
@ -175,6 +176,7 @@ namespace Ryujinx.Ava.Systems
|
|||
|
||||
_chrono = new Stopwatch();
|
||||
_ticksPerFrame = Stopwatch.Frequency / TargetFps;
|
||||
_playTimer = new Stopwatch();
|
||||
|
||||
if (ApplicationPath.StartsWith("@SystemContent"))
|
||||
{
|
||||
|
@ -565,6 +567,7 @@ namespace Ryujinx.Ava.Systems
|
|||
public void Stop()
|
||||
{
|
||||
_isActive = false;
|
||||
_playTimer.Stop();
|
||||
}
|
||||
|
||||
private void Exit()
|
||||
|
@ -616,7 +619,7 @@ namespace Ryujinx.Ava.Systems
|
|||
private void Dispose()
|
||||
{
|
||||
if (Device.Processes != null)
|
||||
MainWindowViewModel.UpdateGameMetadata(Device.Processes.ActiveApplication.ProgramIdText);
|
||||
MainWindowViewModel.UpdateGameMetadata(Device.Processes.ActiveApplication.ProgramIdText, _playTimer.Elapsed);
|
||||
|
||||
ConfigurationState.Instance.System.IgnoreMissingServices.Event -= UpdateIgnoreMissingServicesState;
|
||||
ConfigurationState.Instance.Graphics.AspectRatio.Event -= UpdateAspectRatioState;
|
||||
|
@ -635,6 +638,7 @@ namespace Ryujinx.Ava.Systems
|
|||
_gpuCancellationTokenSource.Dispose();
|
||||
|
||||
_chrono.Stop();
|
||||
_playTimer.Stop();
|
||||
}
|
||||
|
||||
public void DisposeGpu()
|
||||
|
@ -868,6 +872,7 @@ namespace Ryujinx.Ava.Systems
|
|||
ApplicationLibrary.LoadAndSaveMetaData(Device.Processes.ActiveApplication.ProgramIdText,
|
||||
appMetadata => appMetadata.UpdatePreGame()
|
||||
);
|
||||
_playTimer.Start();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -877,6 +882,7 @@ namespace Ryujinx.Ava.Systems
|
|||
Device?.System.TogglePauseEmulation(false);
|
||||
|
||||
_viewModel.IsPaused = false;
|
||||
_playTimer.Start();
|
||||
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI);
|
||||
Logger.Info?.Print(LogClass.Emulation, "Emulation was resumed");
|
||||
}
|
||||
|
@ -886,6 +892,7 @@ namespace Ryujinx.Ava.Systems
|
|||
Device?.System.TogglePauseEmulation(true);
|
||||
|
||||
_viewModel.IsPaused = true;
|
||||
_playTimer.Stop();
|
||||
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI, LocaleManager.Instance[LocaleKeys.Paused]);
|
||||
Logger.Info?.Print(LogClass.Emulation, "Emulation was paused");
|
||||
}
|
||||
|
|
|
@ -33,19 +33,11 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
|||
/// <summary>
|
||||
/// Updates <see cref="LastPlayed"/> and <see cref="TimePlayed"/>. Call this after a game ends.
|
||||
/// </summary>
|
||||
public void UpdatePostGame()
|
||||
/// <param name="playTime">The active gameplay time this past session.</param>
|
||||
public void UpdatePostGame(TimeSpan playTime)
|
||||
{
|
||||
DateTime? prevLastPlayed = LastPlayed;
|
||||
UpdatePreGame();
|
||||
|
||||
if (!prevLastPlayed.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TimeSpan diff = DateTime.UtcNow - prevLastPlayed.Value;
|
||||
double newTotalSeconds = TimePlayed.Add(diff).TotalSeconds;
|
||||
TimePlayed = TimeSpan.FromSeconds(Math.Round(newTotalSeconds, MidpointRounding.AwayFromZero));
|
||||
TimePlayed += playTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,42 +4,26 @@ using Ryujinx.Ava.UI.Helpers;
|
|||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Helper;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Systems.Update.Client;
|
||||
using Ryujinx.Systems.Update.Common;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Ava.Systems
|
||||
{
|
||||
internal static partial class Updater
|
||||
{
|
||||
private static string CreateUpdateQueryUrl()
|
||||
{
|
||||
#pragma warning disable CS8524
|
||||
var os = RunningPlatform.CurrentOS switch
|
||||
#pragma warning restore CS8524
|
||||
{
|
||||
OperatingSystemType.MacOS => "mac",
|
||||
OperatingSystemType.Linux => "linux",
|
||||
OperatingSystemType.Windows => "win"
|
||||
};
|
||||
private static VersionResponse _versionResponse;
|
||||
|
||||
var arch = RunningPlatform.Architecture switch
|
||||
{
|
||||
Architecture.Arm64 => "arm",
|
||||
Architecture.X64 => "amd64",
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (arch is null)
|
||||
return null;
|
||||
|
||||
var rc = ReleaseInformation.IsCanaryBuild ? "canary" : "stable";
|
||||
|
||||
return $"https://update.ryujinx.app/latest/query?os={os}&arch={arch}&rc={rc}";
|
||||
}
|
||||
private static UpdateClient CreateUpdateClient()
|
||||
=> UpdateClient.Builder()
|
||||
.WithServerEndpoint("https://update.ryujinx.app") // This is the default, and doesn't need to be provided; it's here for transparency.
|
||||
.WithLogger((format, args, caller) =>
|
||||
Logger.Info?.Print(
|
||||
LogClass.Application,
|
||||
args.Length is 0 ? format : format.Format(args),
|
||||
caller: caller)
|
||||
);
|
||||
|
||||
public static async Task<Optional<(Version Current, Version Incoming)>> CheckVersionAsync(bool showVersionUpToDate = false)
|
||||
{
|
||||
|
@ -57,39 +41,31 @@ namespace Ryujinx.Ava.Systems
|
|||
return default;
|
||||
}
|
||||
|
||||
if (CreateUpdateQueryUrl() is not {} updateUrl)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, "Could not determine URL for updates.");
|
||||
|
||||
_running = false;
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
Logger.Info?.Print(LogClass.Application, $"Checking for updates from {updateUrl}.");
|
||||
|
||||
// Get latest version number from update.ryujinx.app API
|
||||
using HttpClient jsonClient = ConstructHttpClient();
|
||||
using UpdateClient updateClient = CreateUpdateClient();
|
||||
|
||||
try
|
||||
{
|
||||
UpdaterResponse response =
|
||||
await jsonClient.GetFromJsonAsync(updateUrl, UpdaterResponseJsonContext.Default.UpdaterResponse);
|
||||
|
||||
_buildVer = response.Tag;
|
||||
_buildUrl = response.DownloadUrl;
|
||||
_changelogUrlFormat = response.ReleaseUrlFormat;
|
||||
_versionResponse = await updateClient.QueryLatestAsync(ReleaseInformation.IsCanaryBuild
|
||||
? ReleaseChannel.Canary
|
||||
: ReleaseChannel.Stable);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"An error occurred when parsing JSON response from API ({e.GetType().AsFullNamePrettyString()}): {e.Message}");
|
||||
Logger.Error?.Print(LogClass.Application, $"An error occurred when requesting for updates ({e.GetType().AsFullNamePrettyString()}): {e.Message}");
|
||||
|
||||
_running = false;
|
||||
return default;
|
||||
}
|
||||
|
||||
if (_versionResponse == null)
|
||||
{
|
||||
// logging is done via the UpdateClient library
|
||||
_running = false;
|
||||
return default;
|
||||
}
|
||||
|
||||
// If build URL not found, assume no new update is available.
|
||||
if (_buildUrl is null or "")
|
||||
if (_versionResponse.ArtifactUrl is null or "")
|
||||
{
|
||||
if (showVersionUpToDate)
|
||||
{
|
||||
|
@ -99,7 +75,7 @@ namespace Ryujinx.Ava.Systems
|
|||
|
||||
if (userResult is UserResult.Ok)
|
||||
{
|
||||
OpenHelper.OpenUrl(_changelogUrlFormat.Format(currentVersion));
|
||||
OpenHelper.OpenUrl(_versionResponse.ReleaseUrlFormat.Format(currentVersion));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,7 +87,7 @@ namespace Ryujinx.Ava.Systems
|
|||
}
|
||||
|
||||
|
||||
if (!Version.TryParse(_buildVer, out Version newVersion))
|
||||
if (!Version.TryParse(_versionResponse.Version, out Version newVersion))
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application,
|
||||
$"Failed to convert the received {RyujinxApp.FullAppName} version from the update server!");
|
||||
|
@ -127,17 +103,5 @@ namespace Ryujinx.Ava.Systems
|
|||
|
||||
return (currentVersion, newVersion);
|
||||
}
|
||||
|
||||
[JsonSerializable(typeof(UpdaterResponse))]
|
||||
partial class UpdaterResponseJsonContext : JsonSerializerContext;
|
||||
|
||||
public class UpdaterResponse
|
||||
{
|
||||
[JsonPropertyName("tag")] public string Tag { get; set; }
|
||||
[JsonPropertyName("download_url")] public string DownloadUrl { get; set; }
|
||||
[JsonPropertyName("web_url")] public string ReleaseUrl { get; set; }
|
||||
|
||||
[JsonIgnore] public string ReleaseUrlFormat => ReleaseUrl.Replace(Tag, "{0}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,13 +5,11 @@ using ICSharpCode.SharpZipLib.GZip;
|
|||
using ICSharpCode.SharpZipLib.Tar;
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Common.Models.Github;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Helper;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
@ -35,17 +33,13 @@ namespace Ryujinx.Ava.Systems
|
|||
private static readonly string _updateDir = Path.Combine(Path.GetTempPath(), "Ryujinx", "update");
|
||||
private static readonly string _updatePublishDir = Path.Combine(_updateDir, "publish");
|
||||
private const int ConnectionCount = 4;
|
||||
|
||||
private static string _buildVer;
|
||||
private static string _buildUrl;
|
||||
|
||||
private static long _buildSize;
|
||||
private static bool _updateSuccessful;
|
||||
private static bool _running;
|
||||
|
||||
private static readonly string[] _windowsDependencyDirs = [];
|
||||
|
||||
private static string _changelogUrlFormat = null;
|
||||
|
||||
public static async Task BeginUpdateAsync(bool showVersionUpToDate = false)
|
||||
{
|
||||
if (_running)
|
||||
|
@ -72,7 +66,7 @@ namespace Ryujinx.Ava.Systems
|
|||
|
||||
if (userResult is UserResult.Ok)
|
||||
{
|
||||
OpenHelper.OpenUrl(_changelogUrlFormat.Format(currentVersion));
|
||||
OpenHelper.OpenUrl(_versionResponse.ReleaseUrlFormat.Format(currentVersion));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,7 +86,7 @@ namespace Ryujinx.Ava.Systems
|
|||
// GitLab instance is located in Ukraine. Connection times will vary across the world.
|
||||
buildSizeClient.Timeout = TimeSpan.FromSeconds(10);
|
||||
|
||||
HttpResponseMessage message = await buildSizeClient.GetAsync(new Uri(_buildUrl), HttpCompletionOption.ResponseHeadersRead);
|
||||
HttpResponseMessage message = await buildSizeClient.GetAsync(new Uri(_versionResponse.ArtifactUrl), HttpCompletionOption.ResponseHeadersRead);
|
||||
|
||||
_buildSize = message.Content.Headers.ContentRange.Length.Value;
|
||||
}
|
||||
|
@ -122,7 +116,7 @@ namespace Ryujinx.Ava.Systems
|
|||
switch (shouldUpdate)
|
||||
{
|
||||
case UserResult.Yes:
|
||||
await UpdateRyujinx(_buildUrl);
|
||||
await UpdateRyujinx(_versionResponse.ArtifactUrl);
|
||||
break;
|
||||
// Secondary button maps to no, which in this case is the show changelog button.
|
||||
case UserResult.No:
|
||||
|
|
|
@ -1688,8 +1688,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
RendererHostControl.Focus();
|
||||
});
|
||||
|
||||
public static void UpdateGameMetadata(string titleId)
|
||||
=> ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata => appMetadata.UpdatePostGame());
|
||||
public static void UpdateGameMetadata(string titleId, TimeSpan playTime)
|
||||
=> ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata => appMetadata.UpdatePostGame(playTime));
|
||||
|
||||
public void RefreshFirmwareStatus()
|
||||
{
|
||||
|
|
|
@ -213,13 +213,13 @@ namespace Ryujinx.Ava.UI.Windows
|
|||
}
|
||||
}
|
||||
|
||||
public void Application_Opened(object sender, ApplicationOpenedEventArgs args)
|
||||
public async void Application_Opened(object sender, ApplicationOpenedEventArgs args)
|
||||
{
|
||||
if (args.Application != null)
|
||||
{
|
||||
ViewModel.SelectedIcon = args.Application.Icon;
|
||||
|
||||
ViewModel.LoadApplication(args.Application).Wait();
|
||||
await ViewModel.LoadApplication(args.Application);
|
||||
}
|
||||
|
||||
args.Handled = true;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue