infra: Migrate to .NET 6 (#2829)

* infra: Migrate to .NET 6

* Rollback version naming change

* Workaround .NET 6 ZipArchive API issues

* ci: Switch to VS 2022 for AppVeyor

CI is now ready for .NET 6

* Suppress WebClient warning in DoUpdateWithMultipleThreads

* Attempt to workaround System.Drawing.Common changes on 6.0.0

* Change keyboard rendering from System.Drawing to ImageSharp

* Make the software keyboard renderer multithreaded

* Bump ImageSharp version to 1.0.4 to fix a bug in Image.Load

* Add fallback fonts to the keyboard renderer

* Fix warnings

* Address caian's comment

* Clean up linux workaround as it's uneeded now

* Update readme

Co-authored-by: Caian Benedicto <caianbene@gmail.com>
This commit is contained in:
Mary 2021-11-28 21:24:17 +01:00 committed by GitHub
parent 7b040e51b0
commit 57d3296ba4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
51 changed files with 917 additions and 766 deletions

View file

@ -4,7 +4,6 @@ using ICSharpCode.SharpZipLib.Tar;
using ICSharpCode.SharpZipLib.Zip;
using Mono.Unix;
using Newtonsoft.Json.Linq;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.Ui;
using Ryujinx.Ui.Widgets;
@ -13,6 +12,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Text;
@ -92,10 +92,10 @@ namespace Ryujinx.Modules
// Get latest version number from Appveyor
try
{
using (WebClient jsonClient = new WebClient())
using (HttpClient jsonClient = new HttpClient())
{
// Fetch latest build information
string fetchedJson = await jsonClient.DownloadStringTaskAsync($"{AppveyorApiUrl}/projects/gdkchan/ryujinx/branch/master");
string fetchedJson = await jsonClient.GetStringAsync($"{AppveyorApiUrl}/projects/gdkchan/ryujinx/branch/master");
JObject jsonRoot = JObject.Parse(fetchedJson);
JToken buildToken = jsonRoot["build"];
@ -149,15 +149,15 @@ namespace Ryujinx.Modules
}
// Fetch build size information to learn chunk sizes.
using (WebClient buildSizeClient = new WebClient())
{
using (HttpClient buildSizeClient = new HttpClient())
{
try
{
buildSizeClient.Headers.Add("Range", "bytes=0-0");
await buildSizeClient.DownloadDataTaskAsync(new Uri(_buildUrl));
buildSizeClient.DefaultRequestHeaders.Add("Range", "bytes=0-0");
string contentRange = buildSizeClient.ResponseHeaders["Content-Range"];
_buildSize = long.Parse(contentRange.Substring(contentRange.IndexOf('/') + 1));
HttpResponseMessage message = await buildSizeClient.GetAsync(new Uri(_buildUrl), HttpCompletionOption.ResponseHeadersRead);
_buildSize = message.Content.Headers.ContentRange.Length.Value;
}
catch (Exception ex)
{
@ -220,7 +220,10 @@ namespace Ryujinx.Modules
for (int i = 0; i < ConnectionCount; i++)
{
#pragma warning disable SYSLIB0014
// TODO: WebClient is obsolete and need to be replaced with a more complex logic using HttpClient.
using (WebClient client = new WebClient())
#pragma warning restore SYSLIB0014
{
webClients.Add(client);
@ -307,31 +310,56 @@ namespace Ryujinx.Modules
}
}
private static void DoUpdateWithSingleThread(UpdateDialog updateDialog, string downloadUrl, string updateFile)
private static void DoUpdateWithSingleThreadWorker(UpdateDialog updateDialog, string downloadUrl, string updateFile)
{
// Single-Threaded Updater
using (WebClient client = new WebClient())
using (HttpClient client = new HttpClient())
{
client.DownloadProgressChanged += (_, args) =>
{
updateDialog.ProgressBar.Value = args.ProgressPercentage;
};
// We do not want to timeout while downloading
client.Timeout = TimeSpan.FromDays(1);
client.DownloadDataCompleted += (_, args) =>
using (HttpResponseMessage response = client.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead).Result)
using (Stream remoteFileStream = response.Content.ReadAsStreamAsync().Result)
{
File.WriteAllBytes(updateFile, args.Result);
InstallUpdate(updateDialog, updateFile);
};
using (Stream updateFileStream = File.Open(updateFile, FileMode.Create))
{
long totalBytes = response.Content.Headers.ContentLength.Value;
long byteWritten = 0;
client.DownloadDataAsync(new Uri(downloadUrl));
byte[] buffer = new byte[32 * 1024];
while (true)
{
int readSize = remoteFileStream.Read(buffer);
if (readSize == 0)
{
break;
}
byteWritten += readSize;
updateDialog.ProgressBar.Value = ((double)byteWritten / totalBytes) * 100;
updateFileStream.Write(buffer, 0, readSize);
}
}
}
InstallUpdate(updateDialog, updateFile);
}
}
private static void DoUpdateWithSingleThread(UpdateDialog updateDialog, string downloadUrl, string updateFile)
{
Thread worker = new Thread(() => DoUpdateWithSingleThreadWorker(updateDialog, downloadUrl, updateFile));
worker.Name = "Updater.SingleThreadWorker";
worker.Start();
}
private static void SetUnixPermissions()
{
string ryuBin = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx");
string ryuBin = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx");
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
if (!OperatingSystem.IsWindows())
{
UnixFileInfo unixFileInfo = new UnixFileInfo(ryuBin);
unixFileInfo.FileAccessPermissions |= FileAccessPermissions.UserExecute;

View file

@ -61,6 +61,9 @@ namespace Ryujinx
}
}
// Enforce loading of Mono.Posix.NETStandard to avoid .NET runtime lazy loading it during an update.
Assembly.Load("Mono.Posix.NETStandard");
// Make process DPI aware for proper window sizing on high-res screens.
ForceDpiAware.Windows();
WindowScaleFactor = ForceDpiAware.GetWindowScaleFactor();

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
<OutputType>Exe</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@ -24,7 +24,8 @@
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
<PackageReference Include="OpenTK.Graphics" Version="4.5.0" />
<PackageReference Include="SPB" Version="0.0.3-build15" />
<PackageReference Include="SharpZipLib" Version="1.3.0" />
<PackageReference Include="SharpZipLib" Version="1.3.3" />
<PackageReference Include="Mono.Posix.NETStandard" Version="5.20.1-preview" />
</ItemGroup>
<ItemGroup>

View file

@ -1,6 +1,7 @@
using Gtk;
using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Utilities;
using Ryujinx.Ui.Widgets;
using System;
using System.Collections.Generic;
@ -9,7 +10,6 @@ using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
@ -128,7 +128,7 @@ namespace Ryujinx.Ui.Windows
{
amiiboJsonString = File.ReadAllText(_amiiboJsonPath);
if (await NeedsUpdate(JsonSerializer.Deserialize<AmiiboJson>(amiiboJsonString).LastUpdated))
if (await NeedsUpdate(JsonHelper.Deserialize<AmiiboJson>(amiiboJsonString).LastUpdated))
{
amiiboJsonString = await DownloadAmiiboJson();
}
@ -147,7 +147,7 @@ namespace Ryujinx.Ui.Windows
}
}
_amiiboList = JsonSerializer.Deserialize<AmiiboJson>(amiiboJsonString).Amiibo;
_amiiboList = JsonHelper.Deserialize<AmiiboJson>(amiiboJsonString).Amiibo;
_amiiboList = _amiiboList.OrderBy(amiibo => amiibo.AmiiboSeries).ToList();
if (LastScannedAmiiboShowAll)