aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Ryujinx.Common/Configuration/ConfigurationFileFormat.cs7
-rw-r--r--Ryujinx.Common/Configuration/ConfigurationState.cs18
-rw-r--r--Ryujinx.HLE/HOS/Horizon.cs19
-rw-r--r--Ryujinx.HLE/HOS/Services/Time/Clock/Types/TimeSpanType.cs15
-rw-r--r--Ryujinx/Config.json3
-rw-r--r--Ryujinx/Ui/SwitchSettings.cs78
-rw-r--r--Ryujinx/Ui/SwitchSettings.glade174
-rw-r--r--Ryujinx/_schema.json12
8 files changed, 320 insertions, 6 deletions
diff --git a/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs b/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs
index f47dc4b3..812dc2c3 100644
--- a/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs
+++ b/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs
@@ -19,7 +19,7 @@ namespace Ryujinx.Configuration
/// <summary>
/// The current version of the file format
/// </summary>
- public const int CurrentVersion = 4;
+ public const int CurrentVersion = 5;
public int Version { get; set; }
@@ -94,6 +94,11 @@ namespace Ryujinx.Configuration
public string SystemTimeZone { get; set; }
/// <summary>
+ /// Change System Time Offset in seconds
+ /// </summary>
+ public long SystemTimeOffset { get; set; }
+
+ /// <summary>
/// Enables or disables Docked Mode
/// </summary>
public bool DockedMode { get; set; }
diff --git a/Ryujinx.Common/Configuration/ConfigurationState.cs b/Ryujinx.Common/Configuration/ConfigurationState.cs
index 67628aa1..d2826d36 100644
--- a/Ryujinx.Common/Configuration/ConfigurationState.cs
+++ b/Ryujinx.Common/Configuration/ConfigurationState.cs
@@ -159,6 +159,11 @@ namespace Ryujinx.Configuration
public ReactiveObject<string> TimeZone { get; private set; }
/// <summary>
+ /// System Time Offset in seconds
+ /// </summary>
+ public ReactiveObject<long> SystemTimeOffset { get; private set; }
+
+ /// <summary>
/// Enables or disables Docked Mode
/// </summary>
public ReactiveObject<bool> EnableDockedMode { get; private set; }
@@ -188,6 +193,7 @@ namespace Ryujinx.Configuration
Language = new ReactiveObject<Language>();
Region = new ReactiveObject<Region>();
TimeZone = new ReactiveObject<string>();
+ SystemTimeOffset = new ReactiveObject<long>();
EnableDockedMode = new ReactiveObject<bool>();
EnableMulticoreScheduling = new ReactiveObject<bool>();
EnableFsIntegrityChecks = new ReactiveObject<bool>();
@@ -322,6 +328,7 @@ namespace Ryujinx.Configuration
SystemLanguage = System.Language,
SystemRegion = System.Region,
SystemTimeZone = System.TimeZone,
+ SystemTimeOffset = System.SystemTimeOffset,
DockedMode = System.EnableDockedMode,
EnableDiscordIntegration = EnableDiscordIntegration,
EnableVsync = Graphics.EnableVsync,
@@ -370,6 +377,7 @@ namespace Ryujinx.Configuration
System.Language.Value = Language.AmericanEnglish;
System.Region.Value = Region.USA;
System.TimeZone.Value = "UTC";
+ System.SystemTimeOffset.Value = 0;
System.EnableDockedMode.Value = false;
EnableDiscordIntegration.Value = true;
Graphics.EnableVsync.Value = true;
@@ -504,6 +512,15 @@ namespace Ryujinx.Configuration
configurationFileUpdated = true;
}
+ if (configurationFileFormat.Version < 5)
+ {
+ Common.Logging.Logger.PrintWarning(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 5.");
+
+ configurationFileFormat.SystemTimeOffset = 0;
+
+ configurationFileUpdated = true;
+ }
+
Graphics.MaxAnisotropy.Value = configurationFileFormat.MaxAnisotropy;
Graphics.ShadersDumpPath.Value = configurationFileFormat.GraphicsShadersDumpPath;
Logger.EnableDebug.Value = configurationFileFormat.LoggingEnableDebug;
@@ -518,6 +535,7 @@ namespace Ryujinx.Configuration
System.Language.Value = configurationFileFormat.SystemLanguage;
System.Region.Value = configurationFileFormat.SystemRegion;
System.TimeZone.Value = configurationFileFormat.SystemTimeZone;
+ System.SystemTimeOffset.Value = configurationFileFormat.SystemTimeOffset;
System.EnableDockedMode.Value = configurationFileFormat.DockedMode;
System.EnableDockedMode.Value = configurationFileFormat.DockedMode;
EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration;
diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs
index f6021ec7..ccb67edf 100644
--- a/Ryujinx.HLE/HOS/Horizon.cs
+++ b/Ryujinx.HLE/HOS/Horizon.cs
@@ -9,6 +9,7 @@ using LibHac.Ns;
using LibHac.Spl;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
+using Ryujinx.Configuration;
using Ryujinx.HLE.FileSystem.Content;
using Ryujinx.HLE.HOS.Font;
using Ryujinx.HLE.HOS.Kernel.Common;
@@ -224,8 +225,24 @@ namespace Ryujinx.HLE.HOS
// We assume the rtc is system time.
TimeSpanType systemTime = TimeSpanType.FromSeconds((long)rtcValue);
+ // Configure and setup internal offset
+ TimeSpanType internalOffset = TimeSpanType.FromSeconds(ConfigurationState.Instance.System.SystemTimeOffset);
+
+ TimeSpanType systemTimeOffset = new TimeSpanType(systemTime.NanoSeconds + internalOffset.NanoSeconds);
+
+ if (systemTime.IsDaylightSavingTime() && !systemTimeOffset.IsDaylightSavingTime())
+ {
+ internalOffset = internalOffset.AddSeconds(3600L);
+ }
+ else if (!systemTime.IsDaylightSavingTime() && systemTimeOffset.IsDaylightSavingTime())
+ {
+ internalOffset = internalOffset.AddSeconds(-3600L);
+ }
+
+ internalOffset = new TimeSpanType(-internalOffset.NanoSeconds);
+
// First init the standard steady clock
- TimeServiceManager.Instance.SetupStandardSteadyClock(null, clockSourceId, systemTime, TimeSpanType.Zero, TimeSpanType.Zero, false);
+ TimeServiceManager.Instance.SetupStandardSteadyClock(null, clockSourceId, systemTime, internalOffset, TimeSpanType.Zero, false);
TimeServiceManager.Instance.SetupStandardLocalSystemClock(null, new SystemClockContext(), systemTime.ToSeconds());
if (NxSettings.Settings.TryGetValue("time!standard_network_clock_sufficient_accuracy_minutes", out object standardNetworkClockSufficientAccuracyMinutes))
diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/Types/TimeSpanType.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/Types/TimeSpanType.cs
index c336ad41..89497d82 100644
--- a/Ryujinx.HLE/HOS/Services/Time/Clock/Types/TimeSpanType.cs
+++ b/Ryujinx.HLE/HOS/Services/Time/Clock/Types/TimeSpanType.cs
@@ -1,4 +1,5 @@
-using System.Runtime.InteropServices;
+using System;
+using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Services.Time.Clock
{
@@ -9,6 +10,8 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
public static readonly TimeSpanType Zero = new TimeSpanType(0);
+ private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+
public long NanoSeconds;
public TimeSpanType(long nanoSeconds)
@@ -21,6 +24,16 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
return NanoSeconds / NanoSecondsPerSecond;
}
+ public TimeSpanType AddSeconds(long seconds)
+ {
+ return new TimeSpanType(NanoSeconds + (seconds * NanoSecondsPerSecond));
+ }
+
+ public bool IsDaylightSavingTime()
+ {
+ return UnixEpoch.AddSeconds(ToSeconds()).ToLocalTime().IsDaylightSavingTime();
+ }
+
public static TimeSpanType FromSeconds(long seconds)
{
return new TimeSpanType(seconds * NanoSecondsPerSecond);
diff --git a/Ryujinx/Config.json b/Ryujinx/Config.json
index 8a365550..7a5fe972 100644
--- a/Ryujinx/Config.json
+++ b/Ryujinx/Config.json
@@ -1,5 +1,5 @@
{
- "version": 4,
+ "version": 5,
"max_anisotropy": -1,
"graphics_shaders_dump_path": "",
"logging_enable_debug": false,
@@ -14,6 +14,7 @@
"system_language": "AmericanEnglish",
"system_region": "USA",
"system_time_zone": "UTC",
+ "system_time_offset": 0,
"docked_mode": false,
"enable_discord_integration": true,
"enable_vsync": true,
diff --git a/Ryujinx/Ui/SwitchSettings.cs b/Ryujinx/Ui/SwitchSettings.cs
index 8ff40427..700d0596 100644
--- a/Ryujinx/Ui/SwitchSettings.cs
+++ b/Ryujinx/Ui/SwitchSettings.cs
@@ -20,6 +20,8 @@ namespace Ryujinx.Ui
private static bool _listeningForKeypress;
+ private long _systemTimeOffset;
+
#pragma warning disable CS0649
#pragma warning disable IDE0044
[GUI] Window _settingsWin;
@@ -42,6 +44,16 @@ namespace Ryujinx.Ui
[GUI] ComboBoxText _systemLanguageSelect;
[GUI] ComboBoxText _systemRegionSelect;
[GUI] ComboBoxText _systemTimeZoneSelect;
+ [GUI] SpinButton _systemTimeYearSpin;
+ [GUI] SpinButton _systemTimeMonthSpin;
+ [GUI] SpinButton _systemTimeDaySpin;
+ [GUI] SpinButton _systemTimeHourSpin;
+ [GUI] SpinButton _systemTimeMinuteSpin;
+ [GUI] Adjustment _systemTimeYearSpinAdjustment;
+ [GUI] Adjustment _systemTimeMonthSpinAdjustment;
+ [GUI] Adjustment _systemTimeDaySpinAdjustment;
+ [GUI] Adjustment _systemTimeHourSpinAdjustment;
+ [GUI] Adjustment _systemTimeMinuteSpinAdjustment;
[GUI] CheckButton _custThemeToggle;
[GUI] Entry _custThemePath;
[GUI] ToggleButton _browseThemePath;
@@ -248,6 +260,7 @@ namespace Ryujinx.Ui
_custThemePath.Buffer.Text = ConfigurationState.Instance.Ui.CustomThemePath;
_graphicsShadersDumpPath.Buffer.Text = ConfigurationState.Instance.Graphics.ShadersDumpPath;
_fsLogSpinAdjustment.Value = ConfigurationState.Instance.System.FsGlobalAccessLogMode;
+ _systemTimeOffset = ConfigurationState.Instance.System.SystemTimeOffset;
_gameDirsBox.AppendColumn("", new CellRendererText(), "text", 0);
_gameDirsBoxStore = new ListStore(typeof(string));
@@ -266,9 +279,71 @@ namespace Ryujinx.Ui
}
_listeningForKeypress = false;
+
+ //Setup system time spinners
+ UpdateSystemTimeSpinners();
+ }
+
+ private void UpdateSystemTimeSpinners()
+ {
+ //Unbind system time spin events
+ _systemTimeYearSpin.ValueChanged -= SystemTimeSpin_ValueChanged;
+ _systemTimeMonthSpin.ValueChanged -= SystemTimeSpin_ValueChanged;
+ _systemTimeDaySpin.ValueChanged -= SystemTimeSpin_ValueChanged;
+ _systemTimeHourSpin.ValueChanged -= SystemTimeSpin_ValueChanged;
+ _systemTimeMinuteSpin.ValueChanged -= SystemTimeSpin_ValueChanged;
+
+ //Apply actual system time + SystemTimeOffset to system time spin buttons
+ DateTime systemTime = DateTime.Now.AddSeconds(_systemTimeOffset);
+
+ _systemTimeYearSpinAdjustment.Value = systemTime.Year;
+ _systemTimeMonthSpinAdjustment.Value = systemTime.Month;
+ _systemTimeDaySpinAdjustment.Value = systemTime.Day;
+ _systemTimeHourSpinAdjustment.Value = systemTime.Hour;
+ _systemTimeMinuteSpinAdjustment.Value = systemTime.Minute;
+
+ //Format spin buttons text to include leading zeros
+ _systemTimeYearSpin.Text = systemTime.Year.ToString("0000");
+ _systemTimeMonthSpin.Text = systemTime.Month.ToString("00");
+ _systemTimeDaySpin.Text = systemTime.Day.ToString("00");
+ _systemTimeHourSpin.Text = systemTime.Hour.ToString("00");
+ _systemTimeMinuteSpin.Text = systemTime.Minute.ToString("00");
+
+ //Bind system time spin button events
+ _systemTimeYearSpin.ValueChanged += SystemTimeSpin_ValueChanged;
+ _systemTimeMonthSpin.ValueChanged += SystemTimeSpin_ValueChanged;
+ _systemTimeDaySpin.ValueChanged += SystemTimeSpin_ValueChanged;
+ _systemTimeHourSpin.ValueChanged += SystemTimeSpin_ValueChanged;
+ _systemTimeMinuteSpin.ValueChanged += SystemTimeSpin_ValueChanged;
}
//Events
+ private void SystemTimeSpin_ValueChanged(Object sender, EventArgs e)
+ {
+ int year = _systemTimeYearSpin.ValueAsInt;
+ int month = _systemTimeMonthSpin.ValueAsInt;
+ int day = _systemTimeDaySpin.ValueAsInt;
+ int hour = _systemTimeHourSpin.ValueAsInt;
+ int minute = _systemTimeMinuteSpin.ValueAsInt;
+
+ if (!DateTime.TryParse(year + "-" + month + "-" + day + " " + hour + ":" + minute, out DateTime newTime))
+ {
+ UpdateSystemTimeSpinners();
+
+ return;
+ }
+
+ newTime = newTime.AddSeconds(DateTime.Now.Second).AddMilliseconds(DateTime.Now.Millisecond);
+
+ long systemTimeOffset = (long)Math.Ceiling((newTime - DateTime.Now).TotalMinutes) * 60L;
+
+ if (_systemTimeOffset != systemTimeOffset)
+ {
+ _systemTimeOffset = systemTimeOffset;
+ UpdateSystemTimeSpinners();
+ }
+ }
+
private void Button_Pressed(object sender, EventArgs args, ToggleButton button)
{
if (_listeningForKeypress == false)
@@ -467,7 +542,8 @@ namespace Ryujinx.Ui
ConfigurationState.Instance.Ui.GameDirs.Value = gameDirs;
ConfigurationState.Instance.System.FsGlobalAccessLogMode.Value = (int)_fsLogSpinAdjustment.Value;
- ConfigurationState.Instance.System.TimeZone.Value = _systemTimeZoneSelect.ActiveId;
+ ConfigurationState.Instance.System.TimeZone.Value = _systemTimeZoneSelect.ActiveId;
+ ConfigurationState.Instance.System.SystemTimeOffset.Value = _systemTimeOffset;
MainWindow.SaveConfig();
MainWindow.ApplyTheme();
diff --git a/Ryujinx/Ui/SwitchSettings.glade b/Ryujinx/Ui/SwitchSettings.glade
index f9c8b1c9..7415e76e 100644
--- a/Ryujinx/Ui/SwitchSettings.glade
+++ b/Ryujinx/Ui/SwitchSettings.glade
@@ -7,6 +7,36 @@
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
+ <object class="GtkAdjustment" id="_systemTimeYearSpinAdjustment">
+ <property name="lower">2000</property>
+ <property name="upper">2060</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="_systemTimeMonthSpinAdjustment">
+ <property name="lower">1</property>
+ <property name="upper">12</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">5</property>
+ </object>
+ <object class="GtkAdjustment" id="_systemTimeDaySpinAdjustment">
+ <property name="lower">1</property>
+ <property name="upper">31</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">5</property>
+ </object>
+ <object class="GtkAdjustment" id="_systemTimeHourSpinAdjustment">
+ <property name="lower">0</property>
+ <property name="upper">23</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">5</property>
+ </object>
+ <object class="GtkAdjustment" id="_systemTimeMinuteSpinAdjustment">
+ <property name="lower">0</property>
+ <property name="upper">59</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">5</property>
+ </object>
<object class="GtkDialog" id="_settingsWin">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Ryujinx - Settings</property>
@@ -261,6 +291,148 @@
</packing>
</child>
<child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">System Time:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="_systemTimeYearSpin">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">5</property>
+ <property name="orientation">vertical</property>
+ <property name="adjustment">_systemTimeYearSpinAdjustment</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="no">-</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="_systemTimeMonthSpin">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">0</property>
+ <property name="orientation">vertical</property>
+ <property name="adjustment">_systemTimeMonthSpinAdjustment</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="no">-</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="_systemTimeDaySpin">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">0</property>
+ <property name="orientation">vertical</property>
+ <property name="adjustment">_systemTimeDaySpinAdjustment</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="_systemTimeHourSpin">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">25</property>
+ <property name="orientation">vertical</property>
+ <property name="adjustment">_systemTimeHourSpinAdjustment</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="no">:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="_systemTimeMinuteSpin">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">0</property>
+ <property name="orientation">vertical</property>
+ <property name="adjustment">_systemTimeMinuteSpinAdjustment</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">8</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
<object class="GtkCheckButton" id="_discordToggle">
<property name="label" translatable="yes">Enable Discord Rich Presence</property>
<property name="visible">True</property>
@@ -274,7 +446,7 @@
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">5</property>
- <property name="position">2</property>
+ <property name="position">3</property>
</packing>
</child>
</object>
diff --git a/Ryujinx/_schema.json b/Ryujinx/_schema.json
index 143716b6..f075b608 100644
--- a/Ryujinx/_schema.json
+++ b/Ryujinx/_schema.json
@@ -422,6 +422,18 @@
"USA"
]
},
+ "system_time_offset": {
+ "$id": "#/properties/system_time_offset",
+ "type": "integer",
+ "title": "System Time Offset",
+ "description": "System time offset in seconds.",
+ "default": 0,
+ "examples": [
+ -3600,
+ 0,
+ 3600
+ ]
+ },
"docked_mode": {
"$id": "#/properties/docked_mode",
"type": "boolean",