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:
parent
3b6ffd9c27
commit
64062162c6
|
@ -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] =
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Reference in New Issue