mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	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
					
				
					 7 changed files with 138 additions and 11 deletions
				
			
		|  | @ -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; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue