mirror of
https://github.com/Ryujinx/Ryujinx.git
synced 2024-11-20 02:36:35 +00:00
Appveyor Ryujinx Updater (#1403)
Co-authored-by: Xpl0itR <xpl0itr@outlook.com>
This commit is contained in:
parent
4f65043ad7
commit
a15459366e
16 changed files with 685 additions and 61 deletions
|
@ -14,7 +14,7 @@ namespace Ryujinx.Configuration
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current version of the file format
|
/// The current version of the file format
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int CurrentVersion = 12;
|
public const int CurrentVersion = 14;
|
||||||
|
|
||||||
public int Version { get; set; }
|
public int Version { get; set; }
|
||||||
|
|
||||||
|
@ -118,6 +118,11 @@ namespace Ryujinx.Configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnableDiscordIntegration { get; set; }
|
public bool EnableDiscordIntegration { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks for updates when Ryujinx starts when enabled
|
||||||
|
/// </summary>
|
||||||
|
public bool CheckUpdatesOnStart { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enables or disables Vertical Sync
|
/// Enables or disables Vertical Sync
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -343,6 +343,11 @@ namespace Ryujinx.Configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ReactiveObject<bool> EnableDiscordIntegration { get; private set; }
|
public ReactiveObject<bool> EnableDiscordIntegration { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks for updates when Ryujinx starts when enabled
|
||||||
|
/// </summary>
|
||||||
|
public ReactiveObject<bool> CheckUpdatesOnStart { get; private set; }
|
||||||
|
|
||||||
private ConfigurationState()
|
private ConfigurationState()
|
||||||
{
|
{
|
||||||
Ui = new UiSection();
|
Ui = new UiSection();
|
||||||
|
@ -351,6 +356,7 @@ namespace Ryujinx.Configuration
|
||||||
Graphics = new GraphicsSection();
|
Graphics = new GraphicsSection();
|
||||||
Hid = new HidSection();
|
Hid = new HidSection();
|
||||||
EnableDiscordIntegration = new ReactiveObject<bool>();
|
EnableDiscordIntegration = new ReactiveObject<bool>();
|
||||||
|
CheckUpdatesOnStart = new ReactiveObject<bool>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigurationFileFormat ToFileFormat()
|
public ConfigurationFileFormat ToFileFormat()
|
||||||
|
@ -393,6 +399,7 @@ namespace Ryujinx.Configuration
|
||||||
SystemTimeOffset = System.SystemTimeOffset,
|
SystemTimeOffset = System.SystemTimeOffset,
|
||||||
DockedMode = System.EnableDockedMode,
|
DockedMode = System.EnableDockedMode,
|
||||||
EnableDiscordIntegration = EnableDiscordIntegration,
|
EnableDiscordIntegration = EnableDiscordIntegration,
|
||||||
|
CheckUpdatesOnStart = CheckUpdatesOnStart,
|
||||||
EnableVsync = Graphics.EnableVsync,
|
EnableVsync = Graphics.EnableVsync,
|
||||||
EnableMulticoreScheduling = System.EnableMulticoreScheduling,
|
EnableMulticoreScheduling = System.EnableMulticoreScheduling,
|
||||||
EnablePtc = System.EnablePtc,
|
EnablePtc = System.EnablePtc,
|
||||||
|
@ -452,6 +459,7 @@ namespace Ryujinx.Configuration
|
||||||
System.SystemTimeOffset.Value = 0;
|
System.SystemTimeOffset.Value = 0;
|
||||||
System.EnableDockedMode.Value = false;
|
System.EnableDockedMode.Value = false;
|
||||||
EnableDiscordIntegration.Value = true;
|
EnableDiscordIntegration.Value = true;
|
||||||
|
CheckUpdatesOnStart.Value = true;
|
||||||
Graphics.EnableVsync.Value = true;
|
Graphics.EnableVsync.Value = true;
|
||||||
System.EnableMulticoreScheduling.Value = true;
|
System.EnableMulticoreScheduling.Value = true;
|
||||||
System.EnablePtc.Value = false;
|
System.EnablePtc.Value = false;
|
||||||
|
@ -696,6 +704,15 @@ namespace Ryujinx.Configuration
|
||||||
configurationFileUpdated = true;
|
configurationFileUpdated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (configurationFileFormat.Version < 14)
|
||||||
|
{
|
||||||
|
Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 14.");
|
||||||
|
|
||||||
|
configurationFileFormat.CheckUpdatesOnStart = true;
|
||||||
|
|
||||||
|
configurationFileUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
List<InputConfig> inputConfig = new List<InputConfig>();
|
List<InputConfig> inputConfig = new List<InputConfig>();
|
||||||
inputConfig.AddRange(configurationFileFormat.ControllerConfig);
|
inputConfig.AddRange(configurationFileFormat.ControllerConfig);
|
||||||
inputConfig.AddRange(configurationFileFormat.KeyboardConfig);
|
inputConfig.AddRange(configurationFileFormat.KeyboardConfig);
|
||||||
|
@ -720,6 +737,7 @@ namespace Ryujinx.Configuration
|
||||||
System.SystemTimeOffset.Value = configurationFileFormat.SystemTimeOffset;
|
System.SystemTimeOffset.Value = configurationFileFormat.SystemTimeOffset;
|
||||||
System.EnableDockedMode.Value = configurationFileFormat.DockedMode;
|
System.EnableDockedMode.Value = configurationFileFormat.DockedMode;
|
||||||
EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration;
|
EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration;
|
||||||
|
CheckUpdatesOnStart.Value = configurationFileFormat.CheckUpdatesOnStart;
|
||||||
Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync;
|
Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync;
|
||||||
System.EnableMulticoreScheduling.Value = configurationFileFormat.EnableMulticoreScheduling;
|
System.EnableMulticoreScheduling.Value = configurationFileFormat.EnableMulticoreScheduling;
|
||||||
System.EnablePtc.Value = configurationFileFormat.EnablePtc;
|
System.EnablePtc.Value = configurationFileFormat.EnablePtc;
|
||||||
|
|
|
@ -36,6 +36,7 @@ EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
.editorconfig = .editorconfig
|
.editorconfig = .editorconfig
|
||||||
|
appveyor.yml = appveyor.yml
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Memory", "Ryujinx.Memory\Ryujinx.Memory.csproj", "{A5E6C691-9E22-4263-8F40-42F002CE66BE}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Memory", "Ryujinx.Memory\Ryujinx.Memory.csproj", "{A5E6C691-9E22-4263-8F40-42F002CE66BE}"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": 11,
|
"version": 14,
|
||||||
"res_scale": 1,
|
"res_scale": 1,
|
||||||
"res_scale_custom": 1,
|
"res_scale_custom": 1,
|
||||||
"max_anisotropy": -1,
|
"max_anisotropy": -1,
|
||||||
|
@ -19,6 +19,7 @@
|
||||||
"system_time_offset": 0,
|
"system_time_offset": 0,
|
||||||
"docked_mode": false,
|
"docked_mode": false,
|
||||||
"enable_discord_integration": true,
|
"enable_discord_integration": true,
|
||||||
|
"check_updates_on_start": true,
|
||||||
"enable_vsync": true,
|
"enable_vsync": true,
|
||||||
"enable_multicore_scheduling": true,
|
"enable_multicore_scheduling": true,
|
||||||
"enable_ptc": false,
|
"enable_ptc": false,
|
||||||
|
|
|
@ -10,6 +10,7 @@ using Ryujinx.Ui.Diagnostic;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Ryujinx
|
namespace Ryujinx
|
||||||
{
|
{
|
||||||
|
@ -44,6 +45,9 @@ namespace Ryujinx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete backup files after updating
|
||||||
|
Task.Run(Updater.CleanupUpdate);
|
||||||
|
|
||||||
Toolkit.Init(new ToolkitOptions
|
Toolkit.Init(new ToolkitOptions
|
||||||
{
|
{
|
||||||
Backend = PlatformBackend.PreferNative,
|
Backend = PlatformBackend.PreferNative,
|
||||||
|
@ -122,6 +126,11 @@ namespace Ryujinx
|
||||||
mainWindow.LoadApplication(launchPath);
|
mainWindow.LoadApplication(launchPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ConfigurationState.Instance.CheckUpdatesOnStart.Value && Updater.CanUpdate(false))
|
||||||
|
{
|
||||||
|
Updater.BeginParse(mainWindow, false);
|
||||||
|
}
|
||||||
|
|
||||||
Application.Run();
|
Application.Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
@ -42,6 +42,7 @@
|
||||||
<None Remove="Ui\ProfileDialog.glade" />
|
<None Remove="Ui\ProfileDialog.glade" />
|
||||||
<None Remove="Ui\SettingsWindow.glade" />
|
<None Remove="Ui\SettingsWindow.glade" />
|
||||||
<None Remove="Ui\TitleUpdateWindow.glade" />
|
<None Remove="Ui\TitleUpdateWindow.glade" />
|
||||||
|
<None Remove="Ui\UpdateDialog.glade" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -66,6 +67,7 @@
|
||||||
<EmbeddedResource Include="Ui\SettingsWindow.glade" />
|
<EmbeddedResource Include="Ui\SettingsWindow.glade" />
|
||||||
<EmbeddedResource Include="Ui\DlcWindow.glade" />
|
<EmbeddedResource Include="Ui\DlcWindow.glade" />
|
||||||
<EmbeddedResource Include="Ui\TitleUpdateWindow.glade" />
|
<EmbeddedResource Include="Ui\TitleUpdateWindow.glade" />
|
||||||
|
<EmbeddedResource Include="Updater\UpdateDialog.glade" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -75,6 +77,7 @@
|
||||||
<PackageReference Include="GtkSharp.Dependencies" Version="1.1.0" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
<PackageReference Include="GtkSharp.Dependencies" Version="1.1.0" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="4.3.0" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="4.3.0" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||||
<PackageReference Include="OpenTK.NetStandard" Version="1.0.5.12" />
|
<PackageReference Include="OpenTK.NetStandard" Version="1.0.5.12" />
|
||||||
|
<PackageReference Include="SharpZipLib" Version="1.2.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -135,7 +135,7 @@ namespace Ryujinx.Ui
|
||||||
{
|
{
|
||||||
if (keyboard.IsKeyDown(OpenTK.Input.Key.Escape))
|
if (keyboard.IsKeyDown(OpenTK.Input.Key.Escape))
|
||||||
{
|
{
|
||||||
if (GtkDialog.CreateExitDialog())
|
if (GtkDialog.CreateChoiceDialog("Ryujinx - Exit", "Are you sure you want to stop emulation?", "All unsaved data will be lost!"))
|
||||||
{
|
{
|
||||||
Exit();
|
Exit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,10 @@ namespace Ryujinx.Ui
|
||||||
{
|
{
|
||||||
internal class GtkDialog : MessageDialog
|
internal class GtkDialog : MessageDialog
|
||||||
{
|
{
|
||||||
internal static bool _isExitDialogOpen = false;
|
private static bool _isChoiceDialogOpen;
|
||||||
|
|
||||||
private GtkDialog(string title, string mainText, string secondaryText,
|
private GtkDialog(string title, string mainText, string secondaryText, MessageType messageType = MessageType.Other, ButtonsType buttonsType = ButtonsType.Ok)
|
||||||
MessageType messageType = MessageType.Other, ButtonsType buttonsType = ButtonsType.Ok) : base(null, DialogFlags.Modal, messageType, buttonsType, null)
|
: base(null, DialogFlags.Modal, messageType, buttonsType, null)
|
||||||
{
|
{
|
||||||
Title = title;
|
Title = title;
|
||||||
Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png");
|
Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png");
|
||||||
|
@ -45,19 +45,16 @@ namespace Ryujinx.Ui
|
||||||
return new GtkDialog("Ryujinx - Confirmation", mainText, secondaryText, MessageType.Question, ButtonsType.YesNo);
|
return new GtkDialog("Ryujinx - Confirmation", mainText, secondaryText, MessageType.Question, ButtonsType.YesNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static bool CreateExitDialog()
|
internal static bool CreateChoiceDialog(string title, string mainText, string secondaryText)
|
||||||
{
|
{
|
||||||
if (_isExitDialogOpen)
|
if (_isChoiceDialogOpen)
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
_isExitDialogOpen = true;
|
_isChoiceDialogOpen = true;
|
||||||
ResponseType res = (ResponseType)new GtkDialog("Ryujinx - Exit", "Are you sure you want to stop emulation?",
|
ResponseType response = (ResponseType)new GtkDialog(title, mainText, secondaryText, MessageType.Question, ButtonsType.YesNo).Run();
|
||||||
"All unsaved data will be lost", MessageType.Question, ButtonsType.YesNo).Run();
|
_isChoiceDialogOpen = false;
|
||||||
_isExitDialogOpen = false;
|
|
||||||
|
|
||||||
return res == ResponseType.Yes;
|
return response == ResponseType.Yes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -49,36 +49,38 @@ namespace Ryujinx.Ui
|
||||||
|
|
||||||
#pragma warning disable CS0169, CS0649, IDE0044
|
#pragma warning disable CS0169, CS0649, IDE0044
|
||||||
|
|
||||||
[GUI] MenuBar _menuBar;
|
[GUI] public MenuItem ExitMenuItem;
|
||||||
[GUI] Box _footerBox;
|
[GUI] public MenuItem UpdateMenuItem;
|
||||||
[GUI] Box _statusBar;
|
[GUI] MenuBar _menuBar;
|
||||||
[GUI] MenuItem _stopEmulation;
|
[GUI] Box _footerBox;
|
||||||
[GUI] MenuItem _fullScreen;
|
[GUI] Box _statusBar;
|
||||||
[GUI] CheckMenuItem _favToggle;
|
[GUI] MenuItem _stopEmulation;
|
||||||
[GUI] MenuItem _firmwareInstallDirectory;
|
[GUI] MenuItem _fullScreen;
|
||||||
[GUI] MenuItem _firmwareInstallFile;
|
[GUI] CheckMenuItem _favToggle;
|
||||||
[GUI] Label _hostStatus;
|
[GUI] MenuItem _firmwareInstallDirectory;
|
||||||
[GUI] CheckMenuItem _iconToggle;
|
[GUI] MenuItem _firmwareInstallFile;
|
||||||
[GUI] CheckMenuItem _developerToggle;
|
[GUI] Label _hostStatus;
|
||||||
[GUI] CheckMenuItem _appToggle;
|
[GUI] CheckMenuItem _iconToggle;
|
||||||
[GUI] CheckMenuItem _timePlayedToggle;
|
[GUI] CheckMenuItem _developerToggle;
|
||||||
[GUI] CheckMenuItem _versionToggle;
|
[GUI] CheckMenuItem _appToggle;
|
||||||
[GUI] CheckMenuItem _lastPlayedToggle;
|
[GUI] CheckMenuItem _timePlayedToggle;
|
||||||
[GUI] CheckMenuItem _fileExtToggle;
|
[GUI] CheckMenuItem _versionToggle;
|
||||||
[GUI] CheckMenuItem _pathToggle;
|
[GUI] CheckMenuItem _lastPlayedToggle;
|
||||||
[GUI] CheckMenuItem _fileSizeToggle;
|
[GUI] CheckMenuItem _fileExtToggle;
|
||||||
[GUI] Label _dockedMode;
|
[GUI] CheckMenuItem _pathToggle;
|
||||||
[GUI] Label _gameStatus;
|
[GUI] CheckMenuItem _fileSizeToggle;
|
||||||
[GUI] TreeView _gameTable;
|
[GUI] Label _dockedMode;
|
||||||
[GUI] TreeSelection _gameTableSelection;
|
[GUI] Label _gameStatus;
|
||||||
[GUI] ScrolledWindow _gameTableWindow;
|
[GUI] TreeView _gameTable;
|
||||||
[GUI] Label _gpuName;
|
[GUI] TreeSelection _gameTableSelection;
|
||||||
[GUI] Label _progressLabel;
|
[GUI] ScrolledWindow _gameTableWindow;
|
||||||
[GUI] Label _firmwareVersionLabel;
|
[GUI] Label _gpuName;
|
||||||
[GUI] LevelBar _progressBar;
|
[GUI] Label _progressLabel;
|
||||||
[GUI] Box _viewBox;
|
[GUI] Label _firmwareVersionLabel;
|
||||||
[GUI] Label _vSyncStatus;
|
[GUI] LevelBar _progressBar;
|
||||||
[GUI] Box _listStatusBox;
|
[GUI] Box _viewBox;
|
||||||
|
[GUI] Label _vSyncStatus;
|
||||||
|
[GUI] Box _listStatusBox;
|
||||||
|
|
||||||
#pragma warning restore CS0649, IDE0044, CS0169
|
#pragma warning restore CS0649, IDE0044, CS0169
|
||||||
|
|
||||||
|
@ -1163,15 +1165,9 @@ namespace Ryujinx.Ui
|
||||||
|
|
||||||
private void Update_Pressed(object sender, EventArgs args)
|
private void Update_Pressed(object sender, EventArgs args)
|
||||||
{
|
{
|
||||||
string ryuUpdater = System.IO.Path.Combine(AppDataManager.BaseDirPath, "RyuUpdater.exe");
|
if (Updater.CanUpdate(true))
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
Process.Start(new ProcessStartInfo(ryuUpdater, "/U") { UseShellExecute = true });
|
Updater.BeginParse(this, true);
|
||||||
}
|
|
||||||
catch(System.ComponentModel.Win32Exception)
|
|
||||||
{
|
|
||||||
GtkDialog.CreateErrorDialog("Update canceled by user or updater was not found");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkMenuItem" id="Exit">
|
<object class="GtkMenuItem" id="ExitMenuItem">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="tooltip_text" translatable="yes">Exit Ryujinx</property>
|
<property name="tooltip_text" translatable="yes">Exit Ryujinx</property>
|
||||||
|
@ -320,10 +320,10 @@
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkMenuItem" id="CheckUpdates">
|
<object class="GtkMenuItem" id="UpdateMenuItem">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="tooltip_text" translatable="yes">Check for updates to Ryujinx (requires Ryujinx Installer)</property>
|
<property name="tooltip_text" translatable="yes">Check for updates to Ryujinx</property>
|
||||||
<property name="label" translatable="yes">Check for Updates</property>
|
<property name="label" translatable="yes">Check for Updates</property>
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
<signal name="activate" handler="Update_Pressed" swapped="no"/>
|
<signal name="activate" handler="Update_Pressed" swapped="no"/>
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace Ryujinx.Ui
|
||||||
[GUI] ComboBoxText _graphicsDebugLevel;
|
[GUI] ComboBoxText _graphicsDebugLevel;
|
||||||
[GUI] CheckButton _dockedModeToggle;
|
[GUI] CheckButton _dockedModeToggle;
|
||||||
[GUI] CheckButton _discordToggle;
|
[GUI] CheckButton _discordToggle;
|
||||||
|
[GUI] CheckButton _checkUpdatesToggle;
|
||||||
[GUI] CheckButton _vSyncToggle;
|
[GUI] CheckButton _vSyncToggle;
|
||||||
[GUI] CheckButton _multiSchedToggle;
|
[GUI] CheckButton _multiSchedToggle;
|
||||||
[GUI] CheckButton _ptcToggle;
|
[GUI] CheckButton _ptcToggle;
|
||||||
|
@ -170,6 +171,11 @@ namespace Ryujinx.Ui
|
||||||
_discordToggle.Click();
|
_discordToggle.Click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ConfigurationState.Instance.CheckUpdatesOnStart)
|
||||||
|
{
|
||||||
|
_checkUpdatesToggle.Click();
|
||||||
|
}
|
||||||
|
|
||||||
if (ConfigurationState.Instance.Graphics.EnableVsync)
|
if (ConfigurationState.Instance.Graphics.EnableVsync)
|
||||||
{
|
{
|
||||||
_vSyncToggle.Click();
|
_vSyncToggle.Click();
|
||||||
|
@ -519,6 +525,7 @@ namespace Ryujinx.Ui
|
||||||
ConfigurationState.Instance.Logger.GraphicsDebugLevel.Value = Enum.Parse<GraphicsDebugLevel>(_graphicsDebugLevel.ActiveId);
|
ConfigurationState.Instance.Logger.GraphicsDebugLevel.Value = Enum.Parse<GraphicsDebugLevel>(_graphicsDebugLevel.ActiveId);
|
||||||
ConfigurationState.Instance.System.EnableDockedMode.Value = _dockedModeToggle.Active;
|
ConfigurationState.Instance.System.EnableDockedMode.Value = _dockedModeToggle.Active;
|
||||||
ConfigurationState.Instance.EnableDiscordIntegration.Value = _discordToggle.Active;
|
ConfigurationState.Instance.EnableDiscordIntegration.Value = _discordToggle.Active;
|
||||||
|
ConfigurationState.Instance.CheckUpdatesOnStart.Value = _checkUpdatesToggle.Active;
|
||||||
ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active;
|
ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active;
|
||||||
ConfigurationState.Instance.System.EnableMulticoreScheduling.Value = _multiSchedToggle.Active;
|
ConfigurationState.Instance.System.EnableMulticoreScheduling.Value = _multiSchedToggle.Active;
|
||||||
ConfigurationState.Instance.System.EnablePtc.Value = _ptcToggle.Active;
|
ConfigurationState.Instance.System.EnablePtc.Value = _ptcToggle.Active;
|
||||||
|
|
|
@ -121,7 +121,23 @@
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="padding">5</property>
|
<property name="padding">5</property>
|
||||||
<property name="position">2</property>
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkCheckButton" id="_checkUpdatesToggle">
|
||||||
|
<property name="label" translatable="yes">Check for updates on launch</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">False</property>
|
||||||
|
<property name="halign">start</property>
|
||||||
|
<property name="draw_indicator">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="padding">5</property>
|
||||||
|
<property name="position">1</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
|
86
Ryujinx/Updater/UpdateDialog.cs
Normal file
86
Ryujinx/Updater/UpdateDialog.cs
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
using Gdk;
|
||||||
|
using Gtk;
|
||||||
|
using Mono.Unix;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ui
|
||||||
|
{
|
||||||
|
public class UpdateDialog : Gtk.Window
|
||||||
|
{
|
||||||
|
#pragma warning disable CS0649, IDE0044
|
||||||
|
[Builder.Object] public Label MainText;
|
||||||
|
[Builder.Object] public Label SecondaryText;
|
||||||
|
[Builder.Object] public LevelBar ProgressBar;
|
||||||
|
[Builder.Object] public Button YesButton;
|
||||||
|
[Builder.Object] public Button NoButton;
|
||||||
|
#pragma warning restore CS0649, IDE0044
|
||||||
|
|
||||||
|
private readonly MainWindow _mainWindow;
|
||||||
|
private readonly string _buildUrl;
|
||||||
|
private bool _restartQuery;
|
||||||
|
|
||||||
|
public UpdateDialog(MainWindow mainWindow, Version newVersion, string buildUrl) : this(new Builder("Ryujinx.Updater.UpdateDialog.glade"), mainWindow, newVersion, buildUrl) { }
|
||||||
|
|
||||||
|
private UpdateDialog(Builder builder, MainWindow mainWindow, Version newVersion, string buildUrl) : base(builder.GetObject("UpdateDialog").Handle)
|
||||||
|
{
|
||||||
|
builder.Autoconnect(this);
|
||||||
|
|
||||||
|
_mainWindow = mainWindow;
|
||||||
|
_buildUrl = buildUrl;
|
||||||
|
|
||||||
|
MainText.Text = "Do you want to update Ryujinx to the latest version?";
|
||||||
|
SecondaryText.Text = $"{Program.Version} -> {newVersion}";
|
||||||
|
|
||||||
|
ProgressBar.Hide();
|
||||||
|
|
||||||
|
YesButton.Pressed += YesButton_Pressed;
|
||||||
|
NoButton.Pressed += NoButton_Pressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void YesButton_Pressed(object sender, EventArgs args)
|
||||||
|
{
|
||||||
|
if (_restartQuery)
|
||||||
|
{
|
||||||
|
string ryuName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "Ryujinx.exe" : "Ryujinx";
|
||||||
|
string ryuExe = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ryuName);
|
||||||
|
|
||||||
|
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
UnixFileInfo unixFileInfo = new UnixFileInfo(ryuExe);
|
||||||
|
unixFileInfo.FileAccessPermissions |= FileAccessPermissions.UserExecute;
|
||||||
|
}
|
||||||
|
|
||||||
|
Process.Start(ryuExe);
|
||||||
|
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.Window.Functions = _mainWindow.Window.Functions = WMFunction.All & WMFunction.Close;
|
||||||
|
_mainWindow.ExitMenuItem.Sensitive = false;
|
||||||
|
|
||||||
|
YesButton.Hide();
|
||||||
|
NoButton.Hide();
|
||||||
|
ProgressBar.Show();
|
||||||
|
|
||||||
|
SecondaryText.Text = "";
|
||||||
|
_restartQuery = true;
|
||||||
|
|
||||||
|
Updater.UpdateRyujinx(this, _buildUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NoButton_Pressed(object sender, EventArgs args)
|
||||||
|
{
|
||||||
|
Updater.Running = false;
|
||||||
|
_mainWindow.Window.Functions = WMFunction.All;
|
||||||
|
|
||||||
|
_mainWindow.ExitMenuItem.Sensitive = true;
|
||||||
|
_mainWindow.UpdateMenuItem.Sensitive = true;
|
||||||
|
|
||||||
|
this.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
127
Ryujinx/Updater/UpdateDialog.glade
Normal file
127
Ryujinx/Updater/UpdateDialog.glade
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- Generated with glade 3.22.1 -->
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk+" version="3.20"/>
|
||||||
|
<object class="GtkWindow" id="UpdateDialog">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="title" translatable="yes">Ryujinx - Updater</property>
|
||||||
|
<property name="resizable">False</property>
|
||||||
|
<property name="window_position">center</property>
|
||||||
|
<property name="default_width">400</property>
|
||||||
|
<property name="default_height">130</property>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="MainBox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_left">10</property>
|
||||||
|
<property name="margin_right">10</property>
|
||||||
|
<property name="margin_top">10</property>
|
||||||
|
<property name="margin_bottom">10</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="BodyBox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="MainText">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_top">5</property>
|
||||||
|
<property name="margin_bottom">5</property>
|
||||||
|
<attributes>
|
||||||
|
<attribute name="weight" value="bold"/>
|
||||||
|
<attribute name="size" value="10000"/>
|
||||||
|
</attributes>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="SecondaryText">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_top">5</property>
|
||||||
|
<property name="margin_bottom">5</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLevelBar" id="ProgressBar">
|
||||||
|
<property name="height_request">20</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_top">5</property>
|
||||||
|
<property name="margin_bottom">5</property>
|
||||||
|
<property name="max_value">100</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="ButtonBox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="YesButton">
|
||||||
|
<property name="label" translatable="yes">Yes</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="margin_right">5</property>
|
||||||
|
<property name="margin_top">5</property>
|
||||||
|
<property name="margin_bottom">5</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="NoButton">
|
||||||
|
<property name="label" translatable="yes">No</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="margin_left">5</property>
|
||||||
|
<property name="margin_top">5</property>
|
||||||
|
<property name="margin_bottom">5</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</interface>
|
347
Ryujinx/Updater/Updater.cs
Normal file
347
Ryujinx/Updater/Updater.cs
Normal file
|
@ -0,0 +1,347 @@
|
||||||
|
using Gtk;
|
||||||
|
using ICSharpCode.SharpZipLib.GZip;
|
||||||
|
using ICSharpCode.SharpZipLib.Tar;
|
||||||
|
using ICSharpCode.SharpZipLib.Zip;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.Ui;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.NetworkInformation;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Ryujinx
|
||||||
|
{
|
||||||
|
public static class Updater
|
||||||
|
{
|
||||||
|
internal static bool Running;
|
||||||
|
|
||||||
|
private static readonly string HomeDir = AppDomain.CurrentDomain.BaseDirectory;
|
||||||
|
private static readonly string UpdateDir = Path.Combine(Path.GetTempPath(), "Ryujinx", "update");
|
||||||
|
private static readonly string UpdatePublishDir = Path.Combine(UpdateDir, "publish");
|
||||||
|
|
||||||
|
private static string _jobId;
|
||||||
|
private static string _buildVer;
|
||||||
|
private static string _platformExt;
|
||||||
|
private static string _buildUrl;
|
||||||
|
|
||||||
|
private const string AppveyorApiUrl = "https://ci.appveyor.com/api";
|
||||||
|
|
||||||
|
public static async Task BeginParse(MainWindow mainWindow, bool showVersionUpToDate)
|
||||||
|
{
|
||||||
|
if (Running) return;
|
||||||
|
|
||||||
|
Running = true;
|
||||||
|
mainWindow.UpdateMenuItem.Sensitive = false;
|
||||||
|
|
||||||
|
// Detect current platform
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||||
|
{
|
||||||
|
_platformExt = "osx_x64.zip";
|
||||||
|
}
|
||||||
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
_platformExt = "win_x64.zip";
|
||||||
|
}
|
||||||
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
|
{
|
||||||
|
_platformExt = "linux_x64.tar.gz";
|
||||||
|
}
|
||||||
|
|
||||||
|
Version newVersion;
|
||||||
|
Version currentVersion;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
currentVersion = Version.Parse(Program.Version);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
GtkDialog.CreateWarningDialog("Failed to convert the current Ryujinx version.", "Cancelling Update!");
|
||||||
|
Logger.Error?.Print(LogClass.Application, "Failed to convert the current Ryujinx version!");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get latest version number from Appveyor
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (WebClient jsonClient = new WebClient())
|
||||||
|
{
|
||||||
|
string fetchedJson = await jsonClient.DownloadStringTaskAsync($"{AppveyorApiUrl}/projects/gdkchan/ryujinx/branch/master");
|
||||||
|
JObject jsonRoot = JObject.Parse(fetchedJson);
|
||||||
|
JToken buildToken = jsonRoot["build"];
|
||||||
|
|
||||||
|
_jobId = (string)buildToken["jobs"][0]["jobId"];
|
||||||
|
_buildVer = (string)buildToken["version"];
|
||||||
|
_buildUrl = $"{AppveyorApiUrl}/buildjobs/{_jobId}/artifacts/ryujinx-{_buildVer}-{_platformExt}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, exception.Message);
|
||||||
|
GtkDialog.CreateErrorDialog("An error has occurred when trying to get release information from AppVeyor.");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
newVersion = Version.Parse(_buildVer);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
GtkDialog.CreateWarningDialog("Failed to convert the received Ryujinx version from AppVeyor.", "Cancelling Update!");
|
||||||
|
Logger.Error?.Print(LogClass.Application, "Failed to convert the received Ryujinx version from AppVeyor!");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newVersion <= currentVersion)
|
||||||
|
{
|
||||||
|
if (showVersionUpToDate)
|
||||||
|
{
|
||||||
|
GtkDialog.CreateInfoDialog("Ryujinx - Updater", "You are already using the most updated version of Ryujinx!", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
Running = false;
|
||||||
|
mainWindow.UpdateMenuItem.Sensitive = true;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show a message asking the user if they want to update
|
||||||
|
UpdateDialog updateDialog = new UpdateDialog(mainWindow, newVersion, _buildUrl);
|
||||||
|
updateDialog.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task UpdateRyujinx(UpdateDialog updateDialog, string downloadUrl)
|
||||||
|
{
|
||||||
|
// Empty update dir, although it shouldn't ever have anything inside it
|
||||||
|
if (Directory.Exists(UpdateDir))
|
||||||
|
{
|
||||||
|
Directory.Delete(UpdateDir, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Directory.CreateDirectory(UpdateDir);
|
||||||
|
|
||||||
|
string updateFile = Path.Combine(UpdateDir, "update.bin");
|
||||||
|
|
||||||
|
// Download the update .zip
|
||||||
|
updateDialog.MainText.Text = "Downloading Update...";
|
||||||
|
updateDialog.ProgressBar.Value = 0;
|
||||||
|
updateDialog.ProgressBar.MaxValue = 100;
|
||||||
|
|
||||||
|
using (WebClient client = new WebClient())
|
||||||
|
{
|
||||||
|
client.DownloadProgressChanged += (_, args) =>
|
||||||
|
{
|
||||||
|
updateDialog.ProgressBar.Value = args.ProgressPercentage;
|
||||||
|
};
|
||||||
|
|
||||||
|
await client.DownloadFileTaskAsync(downloadUrl, updateFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract Update
|
||||||
|
updateDialog.MainText.Text = "Extracting Update...";
|
||||||
|
updateDialog.ProgressBar.Value = 0;
|
||||||
|
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
|
{
|
||||||
|
using (Stream inStream = File.OpenRead(updateFile))
|
||||||
|
using (Stream gzipStream = new GZipInputStream(inStream))
|
||||||
|
using (TarInputStream tarStream = new TarInputStream(gzipStream))
|
||||||
|
{
|
||||||
|
updateDialog.ProgressBar.MaxValue = inStream.Length;
|
||||||
|
|
||||||
|
await Task.Run(() =>
|
||||||
|
{
|
||||||
|
TarEntry tarEntry;
|
||||||
|
while ((tarEntry = tarStream.GetNextEntry()) != null)
|
||||||
|
{
|
||||||
|
if (tarEntry.IsDirectory) continue;
|
||||||
|
|
||||||
|
string outPath = Path.Combine(UpdateDir, tarEntry.Name);
|
||||||
|
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(outPath));
|
||||||
|
|
||||||
|
using (FileStream outStream = File.OpenWrite(outPath))
|
||||||
|
{
|
||||||
|
tarStream.CopyEntryContents(outStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
File.SetLastWriteTime(outPath, DateTime.SpecifyKind(tarEntry.ModTime, DateTimeKind.Utc));
|
||||||
|
|
||||||
|
TarEntry entry = tarEntry;
|
||||||
|
|
||||||
|
Application.Invoke(delegate
|
||||||
|
{
|
||||||
|
updateDialog.ProgressBar.Value += entry.Size;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
updateDialog.ProgressBar.Value = inStream.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using (Stream inStream = File.OpenRead(updateFile))
|
||||||
|
using (ZipFile zipFile = new ZipFile(inStream))
|
||||||
|
{
|
||||||
|
updateDialog.ProgressBar.MaxValue = zipFile.Count;
|
||||||
|
|
||||||
|
await Task.Run(() =>
|
||||||
|
{
|
||||||
|
foreach (ZipEntry zipEntry in zipFile)
|
||||||
|
{
|
||||||
|
if (zipEntry.IsDirectory) continue;
|
||||||
|
|
||||||
|
string outPath = Path.Combine(UpdateDir, zipEntry.Name);
|
||||||
|
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(outPath));
|
||||||
|
|
||||||
|
using (Stream zipStream = zipFile.GetInputStream(zipEntry))
|
||||||
|
using (FileStream outStream = File.OpenWrite(outPath))
|
||||||
|
{
|
||||||
|
zipStream.CopyTo(outStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
File.SetLastWriteTime(outPath, DateTime.SpecifyKind(zipEntry.DateTime, DateTimeKind.Utc));
|
||||||
|
|
||||||
|
Application.Invoke(delegate
|
||||||
|
{
|
||||||
|
updateDialog.ProgressBar.Value++;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete downloaded zip
|
||||||
|
File.Delete(updateFile);
|
||||||
|
|
||||||
|
string[] allFiles = Directory.GetFiles(HomeDir, "*", SearchOption.AllDirectories);
|
||||||
|
|
||||||
|
updateDialog.MainText.Text = "Renaming Old Files...";
|
||||||
|
updateDialog.ProgressBar.Value = 0;
|
||||||
|
updateDialog.ProgressBar.MaxValue = allFiles.Length;
|
||||||
|
|
||||||
|
// Replace old files
|
||||||
|
await Task.Run(() =>
|
||||||
|
{
|
||||||
|
foreach (string file in allFiles)
|
||||||
|
{
|
||||||
|
if (!Path.GetExtension(file).Equals(".log"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Move(file, file + ".ryuold");
|
||||||
|
|
||||||
|
Application.Invoke(delegate
|
||||||
|
{
|
||||||
|
updateDialog.ProgressBar.Value++;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Logger.Warning?.Print(LogClass.Application, "Updater wasn't able to rename file: " + file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Application.Invoke(delegate
|
||||||
|
{
|
||||||
|
updateDialog.MainText.Text = "Adding New Files...";
|
||||||
|
updateDialog.ProgressBar.Value = 0;
|
||||||
|
updateDialog.ProgressBar.MaxValue = Directory.GetFiles(UpdatePublishDir, "*", SearchOption.AllDirectories).Length;
|
||||||
|
});
|
||||||
|
|
||||||
|
MoveAllFilesOver(UpdatePublishDir, HomeDir, updateDialog);
|
||||||
|
});
|
||||||
|
|
||||||
|
Directory.Delete(UpdateDir, true);
|
||||||
|
|
||||||
|
updateDialog.MainText.Text = "Update Complete!";
|
||||||
|
updateDialog.SecondaryText.Text = "Do you want to restart Ryujinx now?";
|
||||||
|
updateDialog.Modal = true;
|
||||||
|
|
||||||
|
updateDialog.ProgressBar.Hide();
|
||||||
|
updateDialog.YesButton.Show();
|
||||||
|
updateDialog.NoButton.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool CanUpdate(bool showWarnings)
|
||||||
|
{
|
||||||
|
if (RuntimeInformation.OSArchitecture != Architecture.X64)
|
||||||
|
{
|
||||||
|
if (showWarnings)
|
||||||
|
{
|
||||||
|
GtkDialog.CreateWarningDialog("You are not running a supported system architecture!", "(Only x64 systems are supported!)");
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NetworkInterface.GetIsNetworkAvailable())
|
||||||
|
{
|
||||||
|
if (showWarnings)
|
||||||
|
{
|
||||||
|
GtkDialog.CreateWarningDialog("You are not connected to the Internet!", "Please verify that you have a working Internet connection!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Program.Version.Contains("dirty"))
|
||||||
|
{
|
||||||
|
if (showWarnings)
|
||||||
|
{
|
||||||
|
GtkDialog.CreateWarningDialog("You Cannot update a Dirty build of Ryujinx!", "Please download Ryujinx at https://ryujinx.org/ if you are looking for a supported version.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void MoveAllFilesOver(string root, string dest, UpdateDialog dialog)
|
||||||
|
{
|
||||||
|
foreach (string directory in Directory.GetDirectories(root))
|
||||||
|
{
|
||||||
|
string dirName = Path.GetFileName(directory);
|
||||||
|
|
||||||
|
if (!Directory.Exists(Path.Combine(dest, dirName)))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(Path.Combine(dest, dirName));
|
||||||
|
}
|
||||||
|
|
||||||
|
MoveAllFilesOver(directory, Path.Combine(dest, dirName), dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string file in Directory.GetFiles(root))
|
||||||
|
{
|
||||||
|
File.Move(file, Path.Combine(dest, Path.GetFileName(file)), true);
|
||||||
|
|
||||||
|
Application.Invoke(delegate
|
||||||
|
{
|
||||||
|
dialog.ProgressBar.Value++;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CleanupUpdate()
|
||||||
|
{
|
||||||
|
foreach (string file in Directory.GetFiles(HomeDir, "*", SearchOption.AllDirectories))
|
||||||
|
{
|
||||||
|
if (Path.GetExtension(file).EndsWith(".ryuold"))
|
||||||
|
{
|
||||||
|
File.Delete(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -719,7 +719,7 @@
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"title": "Custom Resolution Scale",
|
"title": "Custom Resolution Scale",
|
||||||
"description": "A custom floating point scale applied to applicable render targets. Only active when Resolution Scale is -1.",
|
"description": "A custom floating point scale applied to applicable render targets. Only active when Resolution Scale is -1.",
|
||||||
"default": 1.0,
|
"default": 1.0
|
||||||
},
|
},
|
||||||
"max_anisotropy": {
|
"max_anisotropy": {
|
||||||
"$id": "#/properties/max_anisotropy",
|
"$id": "#/properties/max_anisotropy",
|
||||||
|
@ -966,6 +966,17 @@
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"check_updates_on_start": {
|
||||||
|
"$id": "#/properties/check_updates_on_start",
|
||||||
|
"type": "boolean",
|
||||||
|
"title": "Checks for updates when ryujinx starts when enabled",
|
||||||
|
"description": "Checks for updates when ryujinx starts when enabled",
|
||||||
|
"default": true,
|
||||||
|
"examples": [
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
"enable_vsync": {
|
"enable_vsync": {
|
||||||
"$id": "#/properties/enable_vsync",
|
"$id": "#/properties/enable_vsync",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
|
|
Loading…
Reference in a new issue