feat: add system time offset setting (#6139)

* Add setting for system time offset

Add a setting to displace citra system time by days, hours, minutes
or seconds
Add UI for the setting which is only visible when clock is set to
system time
Change core/settings.h to include the setting

* Add system time offset to kernel

Actually makes use of the time offset.

* Fix time offset calculatioon in core/movie.cpp

* Replace C++20 chrono::days with seconds

Hopefully fixes the build.
This commit is contained in:
DaemonTsun 2022-11-20 16:34:53 +01:00 committed by GitHub
parent 3b6ffd9c27
commit 64062162c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 138 additions and 11 deletions

View File

@ -242,6 +242,58 @@ void Config::ReadValues() {
.count(); .count();
} }
{
constexpr const char* default_init_time_offset = "0 00:00:00";
std::string offset_string =
sdl2_config->GetString("System", "init_time_offset", default_init_time_offset);
size_t sep_index = offset_string.find(' ');
if (sep_index == std::string::npos) {
LOG_ERROR(Config, "Failed to parse init_time_offset. Using 0 00:00:00");
offset_string = default_init_time_offset;
sep_index = offset_string.find(' ');
}
std::string day_string = offset_string.substr(0, sep_index);
long long days = 0;
try {
days = std::stoll(day_string);
} catch (std::exception& e) {
LOG_ERROR(Config, "Failed to parse days in init_time_offset. Using 0");
days = 0;
}
long long days_in_seconds = days * 86400;
std::tm t;
t.tm_sec = 0;
t.tm_min = 0;
t.tm_hour = 0;
t.tm_mday = 1;
t.tm_mon = 0;
t.tm_year = 100;
t.tm_isdst = 0;
std::istringstream string_stream(offset_string.substr(sep_index + 1));
string_stream >> std::get_time(&t, "%H:%M:%S");
if (string_stream.fail()) {
LOG_ERROR(Config,
"Failed to parse hours, minutes and seconds in init_time_offset. 00:00:00");
}
auto time_offset =
std::chrono::system_clock::from_time_t(std::mktime(&t)).time_since_epoch();
auto secs = std::chrono::duration_cast<std::chrono::seconds>(time_offset).count();
Settings::values.init_time_offset = static_cast<long long>(secs) + days_in_seconds;
}
// Camera // Camera
using namespace Service::CAM; using namespace Service::CAM;
Settings::values.camera_name[OuterRightCamera] = Settings::values.camera_name[OuterRightCamera] =

View File

@ -547,6 +547,8 @@ void Config::ReadSystemValues() {
.toInt()); .toInt());
Settings::values.init_time = Settings::values.init_time =
ReadSetting(QStringLiteral("init_time"), 946681277ULL).toULongLong(); ReadSetting(QStringLiteral("init_time"), 946681277ULL).toULongLong();
Settings::values.init_time_offset =
ReadSetting(QStringLiteral("init_time_offset"), 0LL).toLongLong();
qt_config->endGroup(); qt_config->endGroup();
} }
@ -1057,6 +1059,8 @@ void Config::SaveSystemValues() {
static_cast<u32>(Settings::InitClock::SystemTime)); static_cast<u32>(Settings::InitClock::SystemTime));
WriteSetting(QStringLiteral("init_time"), WriteSetting(QStringLiteral("init_time"),
static_cast<unsigned long long>(Settings::values.init_time), 946681277ULL); static_cast<unsigned long long>(Settings::values.init_time), 946681277ULL);
WriteSetting(QStringLiteral("init_time_offset"),
static_cast<long long>(Settings::values.init_time_offset), 0LL);
qt_config->endGroup(); qt_config->endGroup();
} }

View File

@ -266,6 +266,14 @@ void ConfigureSystem::SetConfiguration() {
date_time.setTime_t(Settings::values.init_time); date_time.setTime_t(Settings::values.init_time);
ui->edit_init_time->setDateTime(date_time); ui->edit_init_time->setDateTime(date_time);
long long init_time_offset = Settings::values.init_time_offset;
long long days_offset = init_time_offset / 86400;
ui->edit_init_time_offset_days->setValue(days_offset);
unsigned long long time_offset = std::abs(init_time_offset) - std::abs(days_offset * 86400);
QTime time = QTime::fromMSecsSinceStartOfDay(time_offset * 1000);
ui->edit_init_time_offset_time->setTime(time);
if (!enabled) { if (!enabled) {
cfg = Service::CFG::GetModule(Core::System::GetInstance()); cfg = Service::CFG::GetModule(Core::System::GetInstance());
ASSERT_MSG(cfg, "CFG Module missing!"); ASSERT_MSG(cfg, "CFG Module missing!");
@ -382,6 +390,14 @@ void ConfigureSystem::ApplyConfiguration() {
static_cast<Settings::InitClock>(ui->combo_init_clock->currentIndex()); static_cast<Settings::InitClock>(ui->combo_init_clock->currentIndex());
Settings::values.init_time = ui->edit_init_time->dateTime().toTime_t(); Settings::values.init_time = ui->edit_init_time->dateTime().toTime_t();
s64 time_offset_time = ui->edit_init_time_offset_time->time().msecsSinceStartOfDay() / 1000;
s64 time_offset_days = ui->edit_init_time_offset_days->value() * 86400;
if (time_offset_days < 0) {
time_offset_time = -time_offset_time;
}
Settings::values.init_time_offset = time_offset_days + time_offset_time;
Settings::values.is_new_3ds = ui->toggle_new_3ds->isChecked(); Settings::values.is_new_3ds = ui->toggle_new_3ds->isChecked();
} }
@ -415,10 +431,10 @@ void ConfigureSystem::UpdateBirthdayComboBox(int birthmonth_index) {
} }
void ConfigureSystem::ConfigureTime() { void ConfigureSystem::ConfigureTime() {
ui->edit_init_time->setCalendarPopup(true);
QDateTime dt; QDateTime dt;
dt.fromString(QStringLiteral("2000-01-01 00:00:01"), QStringLiteral("yyyy-MM-dd hh:mm:ss")); dt.fromString(QStringLiteral("2000-01-01 00:00:01"), QStringLiteral("yyyy-MM-dd hh:mm:ss"));
ui->edit_init_time->setMinimumDateTime(dt); ui->edit_init_time->setMinimumDateTime(dt);
ui->edit_init_time->setCalendarPopup(true);
SetConfiguration(); SetConfiguration();
@ -428,8 +444,13 @@ void ConfigureSystem::ConfigureTime() {
void ConfigureSystem::UpdateInitTime(int init_clock) { void ConfigureSystem::UpdateInitTime(int init_clock) {
const bool is_fixed_time = const bool is_fixed_time =
static_cast<Settings::InitClock>(init_clock) == Settings::InitClock::FixedTime; static_cast<Settings::InitClock>(init_clock) == Settings::InitClock::FixedTime;
ui->label_init_time->setVisible(is_fixed_time); ui->label_init_time->setVisible(is_fixed_time);
ui->edit_init_time->setVisible(is_fixed_time); ui->edit_init_time->setVisible(is_fixed_time);
ui->label_init_time_offset->setVisible(!is_fixed_time);
ui->edit_init_time_offset_days->setVisible(!is_fixed_time);
ui->edit_init_time_offset_time->setVisible(!is_fixed_time);
} }
void ConfigureSystem::RefreshConsoleID() { void ConfigureSystem::RefreshConsoleID() {

View File

@ -258,6 +258,44 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="1">
<widget class="QDateTimeEdit" name="edit_init_time">
<property name="displayFormat">
<string>yyyy-MM-ddTHH:mm:ss</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_init_time_offset">
<property name="text">
<string>Offset time</string>
</property>
</widget>
</item>
<item row="8" column="1">
<layout class="QGridLayout" name="edit_init_time_offset_grid">
<item column="0">
<widget class="QSpinBox" name="edit_init_time_offset_days">
<property name="suffix">
<string> days</string>
</property>
<property name="minimum">
<number>-2147483648</number>
</property>
<property name="maximum">
<number>2147483647</number>
</property>
</widget>
</item>
<item column="1">
<widget class="QTimeEdit" name="edit_init_time_offset_time">
<property name="displayFormat">
<string>HH:mm:ss</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="9" column="1"> <item row="9" column="1">
<widget class="QSpinBox" name="spinBox_play_coins"> <widget class="QSpinBox" name="spinBox_play_coins">
<property name="maximum"> <property name="maximum">
@ -295,13 +333,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="1">
<widget class="QDateTimeEdit" name="edit_init_time">
<property name="displayFormat">
<string>yyyy-MM-ddTHH:mm:ss</string>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QCheckBox" name="toggle_new_3ds"> <widget class="QCheckBox" name="toggle_new_3ds">
<property name="text"> <property name="text">

View File

@ -45,6 +45,16 @@ static std::chrono::seconds GetInitTime() {
std::tm* now_tm = std::localtime(&now_time_t); std::tm* now_tm = std::localtime(&now_time_t);
if (now_tm && now_tm->tm_isdst > 0) if (now_tm && now_tm->tm_isdst > 0)
now = now + std::chrono::hours(1); now = now + std::chrono::hours(1);
// add the offset
s64 init_time_offset = Settings::values.init_time_offset;
long long days_offset = init_time_offset / 86400;
long long days_offset_in_seconds = days_offset * 86400; // h/m/s truncated
unsigned long long seconds_offset =
std::abs(init_time_offset) - std::abs(days_offset_in_seconds);
now = now + std::chrono::seconds(seconds_offset);
now = now + std::chrono::seconds(days_offset_in_seconds);
return std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()); return std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch());
} }
case Settings::InitClock::FixedTime: case Settings::InitClock::FixedTime:

View File

@ -601,9 +601,17 @@ void Movie::PrepareForPlayback(const std::string& movie_file) {
} }
void Movie::PrepareForRecording() { void Movie::PrepareForRecording() {
init_time = (Settings::values.init_clock == Settings::InitClock::SystemTime if (Settings::values.init_clock == Settings::InitClock::SystemTime) {
? Common::Timer::GetTimeSinceJan1970().count() long long init_time_offset = Settings::values.init_time_offset;
: Settings::values.init_time); long long days_offset = init_time_offset / 86400;
unsigned long long seconds_offset =
std::abs(init_time_offset) - std::abs(days_offset * 86400);
init_time =
Common::Timer::GetTimeSinceJan1970().count() + seconds_offset + (days_offset * 86400);
} else {
init_time = Settings::values.init_time;
}
} }
Movie::ValidationResult Movie::ValidateMovie(const std::string& movie_file) const { Movie::ValidationResult Movie::ValidateMovie(const std::string& movie_file) const {

View File

@ -163,6 +163,7 @@ struct Values {
int region_value; int region_value;
InitClock init_clock; InitClock init_clock;
u64 init_time; u64 init_time;
s64 init_time_offset;
// Renderer // Renderer
bool use_gles; bool use_gles;