Add system time configuration (#4043)
* Add setting to switch between a fixed start time and the system time Add clock settings to SDL Make clock configureable in qt Add a SharedPage handler class Init shared_page_handler for tests
This commit is contained in:
		| @@ -2,7 +2,9 @@ | |||||||
| // Licensed under GPLv2 or any later version | // Licensed under GPLv2 or any later version | ||||||
| // Refer to the license.txt file included. | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #include <iomanip> | ||||||
| #include <memory> | #include <memory> | ||||||
|  | #include <sstream> | ||||||
| #include <unordered_map> | #include <unordered_map> | ||||||
| #include <SDL.h> | #include <SDL.h> | ||||||
| #include <inih/cpp/INIReader.h> | #include <inih/cpp/INIReader.h> | ||||||
| @@ -167,6 +169,28 @@ void Config::ReadValues() { | |||||||
|     Settings::values.is_new_3ds = sdl2_config->GetBoolean("System", "is_new_3ds", false); |     Settings::values.is_new_3ds = sdl2_config->GetBoolean("System", "is_new_3ds", false); | ||||||
|     Settings::values.region_value = |     Settings::values.region_value = | ||||||
|         sdl2_config->GetInteger("System", "region_value", Settings::REGION_VALUE_AUTO_SELECT); |         sdl2_config->GetInteger("System", "region_value", Settings::REGION_VALUE_AUTO_SELECT); | ||||||
|  |     Settings::values.init_clock = | ||||||
|  |         static_cast<Settings::InitClock>(sdl2_config->GetInteger("System", "init_clock", 1)); | ||||||
|  |     { | ||||||
|  |         std::tm t; | ||||||
|  |         t.tm_sec = 1; | ||||||
|  |         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( | ||||||
|  |             sdl2_config->Get("System", "init_time", "2000-01-01 00:00:01")); | ||||||
|  |         string_stream >> std::get_time(&t, "%Y-%m-%d %H:%M:%S"); | ||||||
|  |         if (string_stream.fail()) { | ||||||
|  |             LOG_ERROR(Config, "Failed To parse init_time. Using 2000-01-01 00:00:01"); | ||||||
|  |         } | ||||||
|  |         Settings::values.init_time = | ||||||
|  |             std::chrono::duration_cast<std::chrono::seconds>( | ||||||
|  |                 std::chrono::system_clock::from_time_t(std::mktime(&t)).time_since_epoch()) | ||||||
|  |                 .count(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // Camera |     // Camera | ||||||
|     using namespace Service::CAM; |     using namespace Service::CAM; | ||||||
|   | |||||||
| @@ -199,6 +199,15 @@ is_new_3ds = | |||||||
| # -1: Auto-select (default), 0: Japan, 1: USA, 2: Europe, 3: Australia, 4: China, 5: Korea, 6: Taiwan | # -1: Auto-select (default), 0: Japan, 1: USA, 2: Europe, 3: Australia, 4: China, 5: Korea, 6: Taiwan | ||||||
| region_value = | region_value = | ||||||
|  |  | ||||||
|  | # The clock to use when citra starts | ||||||
|  | # 0: System clock (default), 1: fixed time | ||||||
|  | init_clock = | ||||||
|  |  | ||||||
|  | # Time used when init_clock is set to fixed_time in the format %Y-%m-%d %H:%M:%S | ||||||
|  | # set to fixed time. Default 2000-01-01 00:00:01 | ||||||
|  | # Note: 3DS can only handle times later then Jan 1 2000 | ||||||
|  | init_time = | ||||||
|  |  | ||||||
| [Camera] | [Camera] | ||||||
| # Which camera engine to use for the right outer camera | # Which camera engine to use for the right outer camera | ||||||
| # blank (default): a dummy camera that always returns black image | # blank (default): a dummy camera that always returns black image | ||||||
|   | |||||||
| @@ -168,6 +168,9 @@ void Config::ReadValues() { | |||||||
|     Settings::values.is_new_3ds = ReadSetting("is_new_3ds", false).toBool(); |     Settings::values.is_new_3ds = ReadSetting("is_new_3ds", false).toBool(); | ||||||
|     Settings::values.region_value = |     Settings::values.region_value = | ||||||
|         ReadSetting("region_value", Settings::REGION_VALUE_AUTO_SELECT).toInt(); |         ReadSetting("region_value", Settings::REGION_VALUE_AUTO_SELECT).toInt(); | ||||||
|  |     Settings::values.init_clock = static_cast<Settings::InitClock>( | ||||||
|  |         ReadSetting("init_clock", static_cast<u32>(Settings::InitClock::SystemTime)).toInt()); | ||||||
|  |     Settings::values.init_time = ReadSetting("init_time", 946681277ULL).toULongLong(); | ||||||
|     qt_config->endGroup(); |     qt_config->endGroup(); | ||||||
|  |  | ||||||
|     qt_config->beginGroup("Miscellaneous"); |     qt_config->beginGroup("Miscellaneous"); | ||||||
| @@ -409,6 +412,10 @@ void Config::SaveValues() { | |||||||
|     qt_config->beginGroup("System"); |     qt_config->beginGroup("System"); | ||||||
|     WriteSetting("is_new_3ds", Settings::values.is_new_3ds, false); |     WriteSetting("is_new_3ds", Settings::values.is_new_3ds, false); | ||||||
|     WriteSetting("region_value", Settings::values.region_value, Settings::REGION_VALUE_AUTO_SELECT); |     WriteSetting("region_value", Settings::values.region_value, Settings::REGION_VALUE_AUTO_SELECT); | ||||||
|  |     WriteSetting("init_clock", static_cast<u32>(Settings::values.init_clock), | ||||||
|  |                  static_cast<u32>(Settings::InitClock::SystemTime)); | ||||||
|  |     WriteSetting("init_time", static_cast<unsigned long long>(Settings::values.init_time), | ||||||
|  |                  946681277ULL); | ||||||
|     qt_config->endGroup(); |     qt_config->endGroup(); | ||||||
|  |  | ||||||
|     qt_config->beginGroup("Miscellaneous"); |     qt_config->beginGroup("Miscellaneous"); | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ | |||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/hle/service/cfg/cfg.h" | #include "core/hle/service/cfg/cfg.h" | ||||||
| #include "core/hle/service/fs/archive.h" | #include "core/hle/service/fs/archive.h" | ||||||
|  | #include "core/settings.h" | ||||||
| #include "ui_configure_system.h" | #include "ui_configure_system.h" | ||||||
|  |  | ||||||
| static const std::array<int, 12> days_in_month = {{ | static const std::array<int, 12> days_in_month = {{ | ||||||
| @@ -220,6 +221,9 @@ ConfigureSystem::ConfigureSystem(QWidget* parent) : QWidget(parent), ui(new Ui:: | |||||||
|     connect(ui->combo_birthmonth, |     connect(ui->combo_birthmonth, | ||||||
|             static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, |             static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, | ||||||
|             &ConfigureSystem::updateBirthdayComboBox); |             &ConfigureSystem::updateBirthdayComboBox); | ||||||
|  |     connect(ui->combo_init_clock, | ||||||
|  |             static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, | ||||||
|  |             &ConfigureSystem::updateInitTime); | ||||||
|     connect(ui->button_regenerate_console_id, &QPushButton::clicked, this, |     connect(ui->button_regenerate_console_id, &QPushButton::clicked, this, | ||||||
|             &ConfigureSystem::refreshConsoleID); |             &ConfigureSystem::refreshConsoleID); | ||||||
|     for (u8 i = 0; i < country_names.size(); i++) { |     for (u8 i = 0; i < country_names.size(); i++) { | ||||||
| @@ -228,7 +232,7 @@ ConfigureSystem::ConfigureSystem(QWidget* parent) : QWidget(parent), ui(new Ui:: | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     this->setConfiguration(); |     ConfigureTime(); | ||||||
| } | } | ||||||
|  |  | ||||||
| ConfigureSystem::~ConfigureSystem() {} | ConfigureSystem::~ConfigureSystem() {} | ||||||
| @@ -236,6 +240,11 @@ ConfigureSystem::~ConfigureSystem() {} | |||||||
| void ConfigureSystem::setConfiguration() { | void ConfigureSystem::setConfiguration() { | ||||||
|     enabled = !Core::System::GetInstance().IsPoweredOn(); |     enabled = !Core::System::GetInstance().IsPoweredOn(); | ||||||
|  |  | ||||||
|  |     ui->combo_init_clock->setCurrentIndex(static_cast<u8>(Settings::values.init_clock)); | ||||||
|  |     QDateTime date_time; | ||||||
|  |     date_time.setTime_t(Settings::values.init_time); | ||||||
|  |     ui->edit_init_time->setDateTime(date_time); | ||||||
|  |  | ||||||
|     if (!enabled) { |     if (!enabled) { | ||||||
|         cfg = Service::CFG::GetCurrentModule(); |         cfg = Service::CFG::GetCurrentModule(); | ||||||
|         ReadSystemSettings(); |         ReadSystemSettings(); | ||||||
| @@ -334,6 +343,11 @@ void ConfigureSystem::applyConfiguration() { | |||||||
|     // update the config savegame if any item is modified. |     // update the config savegame if any item is modified. | ||||||
|     if (modified) |     if (modified) | ||||||
|         cfg->UpdateConfigNANDSavegame(); |         cfg->UpdateConfigNANDSavegame(); | ||||||
|  |  | ||||||
|  |     Settings::values.init_clock = | ||||||
|  |         static_cast<Settings::InitClock>(ui->combo_init_clock->currentIndex()); | ||||||
|  |     Settings::values.init_time = ui->edit_init_time->dateTime().toTime_t(); | ||||||
|  |     Settings::Apply(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void ConfigureSystem::updateBirthdayComboBox(int birthmonth_index) { | void ConfigureSystem::updateBirthdayComboBox(int birthmonth_index) { | ||||||
| @@ -361,6 +375,24 @@ void ConfigureSystem::updateBirthdayComboBox(int birthmonth_index) { | |||||||
|     ui->combo_birthday->setCurrentIndex(birthday_index); |     ui->combo_birthday->setCurrentIndex(birthday_index); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void ConfigureSystem::ConfigureTime() { | ||||||
|  |     ui->edit_init_time->setCalendarPopup(true); | ||||||
|  |     QDateTime dt; | ||||||
|  |     dt.fromString("2000-01-01 00:00:01", "yyyy-MM-dd hh:mm:ss"); | ||||||
|  |     ui->edit_init_time->setMinimumDateTime(dt); | ||||||
|  |  | ||||||
|  |     this->setConfiguration(); | ||||||
|  |  | ||||||
|  |     updateInitTime(ui->combo_init_clock->currentIndex()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ConfigureSystem::updateInitTime(int init_clock) { | ||||||
|  |     const bool is_fixed_time = | ||||||
|  |         static_cast<Settings::InitClock>(init_clock) == Settings::InitClock::FixedTime; | ||||||
|  |     ui->label_init_time->setVisible(is_fixed_time); | ||||||
|  |     ui->edit_init_time->setVisible(is_fixed_time); | ||||||
|  | } | ||||||
|  |  | ||||||
| void ConfigureSystem::refreshConsoleID() { | void ConfigureSystem::refreshConsoleID() { | ||||||
|     QMessageBox::StandardButton reply; |     QMessageBox::StandardButton reply; | ||||||
|     QString warning_text = tr("This will replace your current virtual 3DS with a new one. " |     QString warning_text = tr("This will replace your current virtual 3DS with a new one. " | ||||||
|   | |||||||
| @@ -31,10 +31,12 @@ public: | |||||||
|  |  | ||||||
| public slots: | public slots: | ||||||
|     void updateBirthdayComboBox(int birthmonth_index); |     void updateBirthdayComboBox(int birthmonth_index); | ||||||
|  |     void updateInitTime(int init_clock); | ||||||
|     void refreshConsoleID(); |     void refreshConsoleID(); | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     void ReadSystemSettings(); |     void ReadSystemSettings(); | ||||||
|  |     void ConfigureTime(); | ||||||
|  |  | ||||||
|     std::unique_ptr<Ui::ConfigureSystem> ui; |     std::unique_ptr<Ui::ConfigureSystem> ui; | ||||||
|     bool enabled; |     bool enabled; | ||||||
|   | |||||||
| @@ -232,13 +232,45 @@ | |||||||
|          </widget> |          </widget> | ||||||
|         </item> |         </item> | ||||||
|         <item row="5" column="0"> |         <item row="5" column="0"> | ||||||
|  |          <widget class="QLabel" name="label_init_clock"> | ||||||
|  |           <property name="text"> | ||||||
|  |            <string>Clock</string> | ||||||
|  |           </property> | ||||||
|  |          </widget> | ||||||
|  |         </item> | ||||||
|  |         <item row="5" column="1"> | ||||||
|  |          <widget class="QComboBox" name="combo_init_clock"> | ||||||
|  |           <item> | ||||||
|  |            <property name="text"> | ||||||
|  |             <string>System Clock</string> | ||||||
|  |            </property> | ||||||
|  |           </item> | ||||||
|  |           <item> | ||||||
|  |            <property name="text"> | ||||||
|  |             <string>Fixed Time</string> | ||||||
|  |            </property> | ||||||
|  |           </item> | ||||||
|  |          </widget> | ||||||
|  |         </item> | ||||||
|  |         <item row="6" column="0"> | ||||||
|  |          <widget class="QLabel" name="label_init_time"> | ||||||
|  |           <property name="text"> | ||||||
|  |            <string>Startup time</string> | ||||||
|  |           </property> | ||||||
|  |          </widget> | ||||||
|  |         </item> | ||||||
|  |         <item row="6" column="1"> | ||||||
|  |          <widget class="QDateTimeEdit" name="edit_init_time"> | ||||||
|  |          </widget> | ||||||
|  |         </item> | ||||||
|  |         <item row="7" column="0"> | ||||||
|          <widget class="QLabel" name="label_console_id"> |          <widget class="QLabel" name="label_console_id"> | ||||||
|           <property name="text"> |           <property name="text"> | ||||||
|            <string>Console ID:</string> |            <string>Console ID:</string> | ||||||
|           </property> |           </property> | ||||||
|          </widget> |          </widget> | ||||||
|         </item> |         </item> | ||||||
|         <item row="5" column="1"> |         <item row="7" column="1"> | ||||||
|          <widget class="QPushButton" name="button_regenerate_console_id"> |          <widget class="QPushButton" name="button_regenerate_console_id"> | ||||||
|           <property name="sizePolicy"> |           <property name="sizePolicy"> | ||||||
|            <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> |            <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||||||
|   | |||||||
| @@ -174,6 +174,7 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { | |||||||
|  |  | ||||||
|     telemetry_session = std::make_unique<Core::TelemetrySession>(); |     telemetry_session = std::make_unique<Core::TelemetrySession>(); | ||||||
|     service_manager = std::make_shared<Service::SM::ServiceManager>(); |     service_manager = std::make_shared<Service::SM::ServiceManager>(); | ||||||
|  |     shared_page_handler = std::make_shared<SharedPage::Handler>(); | ||||||
|  |  | ||||||
|     HW::Init(); |     HW::Init(); | ||||||
|     Kernel::Init(system_mode); |     Kernel::Init(system_mode); | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ | |||||||
| #include <string> | #include <string> | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "core/frontend/applets/swkbd.h" | #include "core/frontend/applets/swkbd.h" | ||||||
|  | #include "core/hle/shared_page.h" | ||||||
| #include "core/loader/loader.h" | #include "core/loader/loader.h" | ||||||
| #include "core/memory.h" | #include "core/memory.h" | ||||||
| #include "core/perf_stats.h" | #include "core/perf_stats.h" | ||||||
| @@ -163,6 +164,10 @@ public: | |||||||
|         return registered_swkbd; |         return registered_swkbd; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     std::shared_ptr<SharedPage::Handler> GetSharedPageHandler() const { | ||||||
|  |         return shared_page_handler; | ||||||
|  |     } | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     /** |     /** | ||||||
|      * Initialize the emulated system. |      * Initialize the emulated system. | ||||||
| @@ -196,6 +201,9 @@ private: | |||||||
|     /// Frontend applets |     /// Frontend applets | ||||||
|     std::shared_ptr<Frontend::SoftwareKeyboard> registered_swkbd; |     std::shared_ptr<Frontend::SoftwareKeyboard> registered_swkbd; | ||||||
|  |  | ||||||
|  |     /// Shared Page | ||||||
|  |     std::shared_ptr<SharedPage::Handler> shared_page_handler; | ||||||
|  |  | ||||||
|     static System s_instance; |     static System s_instance; | ||||||
|  |  | ||||||
|     ResultStatus status = ResultStatus::Success; |     ResultStatus status = ResultStatus::Success; | ||||||
|   | |||||||
| @@ -19,7 +19,6 @@ unsigned int Object::next_object_id; | |||||||
| /// Initialize the kernel | /// Initialize the kernel | ||||||
| void Init(u32 system_mode) { | void Init(u32 system_mode) { | ||||||
|     ConfigMem::Init(); |     ConfigMem::Init(); | ||||||
|     SharedPage::Init(); |  | ||||||
|  |  | ||||||
|     Kernel::MemoryInit(system_mode); |     Kernel::MemoryInit(system_mode); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,11 +11,11 @@ | |||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | #include "core/core.h" | ||||||
| #include "core/hle/config_mem.h" | #include "core/hle/config_mem.h" | ||||||
| #include "core/hle/kernel/memory.h" | #include "core/hle/kernel/memory.h" | ||||||
| #include "core/hle/kernel/vm_manager.h" | #include "core/hle/kernel/vm_manager.h" | ||||||
| #include "core/hle/result.h" | #include "core/hle/result.h" | ||||||
| #include "core/hle/shared_page.h" |  | ||||||
| #include "core/memory.h" | #include "core/memory.h" | ||||||
| #include "core/memory_setup.h" | #include "core/memory_setup.h" | ||||||
|  |  | ||||||
| @@ -160,9 +160,12 @@ void MapSharedPages(VMManager& address_space) { | |||||||
|                            .Unwrap(); |                            .Unwrap(); | ||||||
|     address_space.Reprotect(cfg_mem_vma, VMAPermission::Read); |     address_space.Reprotect(cfg_mem_vma, VMAPermission::Read); | ||||||
|  |  | ||||||
|     auto shared_page_vma = address_space |     auto shared_page_vma = | ||||||
|                                .MapBackingMemory(Memory::SHARED_PAGE_VADDR, |         address_space | ||||||
|                                                  reinterpret_cast<u8*>(&SharedPage::shared_page), |             .MapBackingMemory( | ||||||
|  |                 Memory::SHARED_PAGE_VADDR, | ||||||
|  |                 reinterpret_cast<u8*>( | ||||||
|  |                     &Core::System::GetInstance().GetSharedPageHandler()->GetSharedPage()), | ||||||
|                 Memory::SHARED_PAGE_SIZE, MemoryState::Shared) |                 Memory::SHARED_PAGE_SIZE, MemoryState::Shared) | ||||||
|             .Unwrap(); |             .Unwrap(); | ||||||
|     address_space.Reprotect(shared_page_vma, VMAPermission::Read); |     address_space.Reprotect(shared_page_vma, VMAPermission::Read); | ||||||
|   | |||||||
| @@ -13,7 +13,6 @@ | |||||||
| #include "core/hle/kernel/shared_memory.h" | #include "core/hle/kernel/shared_memory.h" | ||||||
| #include "core/hle/result.h" | #include "core/hle/result.h" | ||||||
| #include "core/hle/service/gsp/gsp_gpu.h" | #include "core/hle/service/gsp/gsp_gpu.h" | ||||||
| #include "core/hle/shared_page.h" |  | ||||||
| #include "core/hw/gpu.h" | #include "core/hw/gpu.h" | ||||||
| #include "core/hw/hw.h" | #include "core/hw/hw.h" | ||||||
| #include "core/hw/lcd.h" | #include "core/hw/lcd.h" | ||||||
| @@ -732,7 +731,8 @@ void GSP_GPU::SetLedForceOff(Kernel::HLERequestContext& ctx) { | |||||||
|     IPC::RequestParser rp(ctx, 0x1C, 1, 0); |     IPC::RequestParser rp(ctx, 0x1C, 1, 0); | ||||||
|  |  | ||||||
|     u8 state = rp.Pop<u8>(); |     u8 state = rp.Pop<u8>(); | ||||||
|     SharedPage::Set3DLed(state); |  | ||||||
|  |     Core::System::GetInstance().GetSharedPageHandler()->Set3DLed(state); | ||||||
|  |  | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|   | |||||||
| @@ -14,6 +14,7 @@ | |||||||
| #include <cryptopp/osrng.h> | #include <cryptopp/osrng.h> | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | #include "core/core.h" | ||||||
| #include "core/core_timing.h" | #include "core/core_timing.h" | ||||||
| #include "core/hle/ipc_helpers.h" | #include "core/hle/ipc_helpers.h" | ||||||
| #include "core/hle/kernel/event.h" | #include "core/hle/kernel/event.h" | ||||||
| @@ -24,7 +25,6 @@ | |||||||
| #include "core/hle/service/nwm/uds_beacon.h" | #include "core/hle/service/nwm/uds_beacon.h" | ||||||
| #include "core/hle/service/nwm/uds_connection.h" | #include "core/hle/service/nwm/uds_connection.h" | ||||||
| #include "core/hle/service/nwm/uds_data.h" | #include "core/hle/service/nwm/uds_data.h" | ||||||
| #include "core/hle/shared_page.h" |  | ||||||
| #include "core/memory.h" | #include "core/memory.h" | ||||||
| #include "network/network.h" | #include "network/network.h" | ||||||
|  |  | ||||||
| @@ -1334,8 +1334,10 @@ NWM_UDS::NWM_UDS() : ServiceFramework("nwm::UDS") { | |||||||
|             mac = room_member->GetMacAddress(); |             mac = room_member->GetMacAddress(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     SharedPage::SetMacAddress(mac); |  | ||||||
|     SharedPage::SetWifiLinkLevel(SharedPage::WifiLinkLevel::BEST); |     Core::System::GetInstance().GetSharedPageHandler()->SetMacAddress(mac); | ||||||
|  |     Core::System::GetInstance().GetSharedPageHandler()->SetWifiLinkLevel( | ||||||
|  |         SharedPage::WifiLinkLevel::BEST); | ||||||
| } | } | ||||||
|  |  | ||||||
| NWM_UDS::~NWM_UDS() { | NWM_UDS::~NWM_UDS() { | ||||||
|   | |||||||
| @@ -4,7 +4,6 @@ | |||||||
|  |  | ||||||
| #include <chrono> | #include <chrono> | ||||||
| #include <cstring> | #include <cstring> | ||||||
| #include <ctime> |  | ||||||
| #include "core/core_timing.h" | #include "core/core_timing.h" | ||||||
| #include "core/hle/service/ptm/ptm.h" | #include "core/hle/service/ptm/ptm.h" | ||||||
| #include "core/hle/shared_page.h" | #include "core/hle/shared_page.h" | ||||||
| @@ -14,13 +13,53 @@ | |||||||
|  |  | ||||||
| namespace SharedPage { | namespace SharedPage { | ||||||
|  |  | ||||||
| SharedPageDef shared_page; | static std::chrono::seconds GetInitTime() { | ||||||
|  |     switch (Settings::values.init_clock) { | ||||||
|  |     case Settings::InitClock::SystemTime: { | ||||||
|  |         auto now = std::chrono::system_clock::now(); | ||||||
|  |         // If the system time is in daylight saving, we give an additional hour to console time | ||||||
|  |         std::time_t now_time_t = std::chrono::system_clock::to_time_t(now); | ||||||
|  |         std::tm* now_tm = std::localtime(&now_time_t); | ||||||
|  |         if (now_tm && now_tm->tm_isdst > 0) | ||||||
|  |             now = now + std::chrono::hours(1); | ||||||
|  |         return std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()); | ||||||
|  |     } | ||||||
|  |     case Settings::InitClock::FixedTime: | ||||||
|  |         return std::chrono::seconds(Settings::values.init_time); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| static CoreTiming::EventType* update_time_event; | Handler::Handler() { | ||||||
|  |     std::memset(&shared_page, 0, sizeof(shared_page)); | ||||||
|  |  | ||||||
|  |     shared_page.running_hw = 0x1; // product | ||||||
|  |  | ||||||
|  |     // Some games wait until this value becomes 0x1, before asking running_hw | ||||||
|  |     shared_page.unknown_value = 0x1; | ||||||
|  |  | ||||||
|  |     // Set to a completely full battery | ||||||
|  |     shared_page.battery_state.charge_level.Assign( | ||||||
|  |         static_cast<u8>(Service::PTM::ChargeLevels::CompletelyFull)); | ||||||
|  |     shared_page.battery_state.is_adapter_connected.Assign(1); | ||||||
|  |     shared_page.battery_state.is_charging.Assign(1); | ||||||
|  |  | ||||||
|  |     init_time = GetInitTime(); | ||||||
|  |  | ||||||
|  |     using namespace std::placeholders; | ||||||
|  |     update_time_event = CoreTiming::RegisterEvent( | ||||||
|  |         "SharedPage::UpdateTimeCallback", std::bind(&Handler::UpdateTimeCallback, this, _1, _2)); | ||||||
|  |     CoreTiming::ScheduleEvent(0, update_time_event); | ||||||
|  |  | ||||||
|  |     float slidestate = | ||||||
|  |         Settings::values.toggle_3d ? (float_le)Settings::values.factor_3d / 100 : 0.0f; | ||||||
|  |     shared_page.sliderstate_3d = slidestate; | ||||||
|  | } | ||||||
|  |  | ||||||
| /// Gets system time in 3DS format. The epoch is Jan 1900, and the unit is millisecond. | /// Gets system time in 3DS format. The epoch is Jan 1900, and the unit is millisecond. | ||||||
| static u64 GetSystemTime() { | u64 Handler::GetSystemTime() const { | ||||||
|     auto now = std::chrono::system_clock::now(); |     std::chrono::milliseconds now = | ||||||
|  |         init_time + | ||||||
|  |         std::chrono::duration_cast<std::chrono::milliseconds>(CoreTiming::GetGlobalTimeUs()); | ||||||
|  |  | ||||||
|     // 3DS system does't allow user to set a time before Jan 1 2000, |     // 3DS system does't allow user to set a time before Jan 1 2000, | ||||||
|     // so we use it as an auxiliary epoch to calculate the console time. |     // so we use it as an auxiliary epoch to calculate the console time. | ||||||
| @@ -32,27 +71,21 @@ static u64 GetSystemTime() { | |||||||
|     epoch_tm.tm_mon = 0; |     epoch_tm.tm_mon = 0; | ||||||
|     epoch_tm.tm_year = 100; |     epoch_tm.tm_year = 100; | ||||||
|     epoch_tm.tm_isdst = 0; |     epoch_tm.tm_isdst = 0; | ||||||
|     auto epoch = std::chrono::system_clock::from_time_t(std::mktime(&epoch_tm)); |     u64 epoch = std::mktime(&epoch_tm) * 1000; | ||||||
|  |  | ||||||
|     // 3DS console time uses Jan 1 1900 as internal epoch, |     // 3DS console time uses Jan 1 1900 as internal epoch, | ||||||
|     // so we use the milliseconds between 1900 and 2000 as base console time |     // so we use the milliseconds between 1900 and 2000 as base console time | ||||||
|     u64 console_time = 3155673600000ULL; |     u64 console_time = 3155673600000ULL; | ||||||
|  |  | ||||||
|     // Only when system time is after 2000, we set it as 3DS system time |     // Only when system time is after 2000, we set it as 3DS system time | ||||||
|     if (now > epoch) { |     if (now.count() > epoch) { | ||||||
|         console_time += std::chrono::duration_cast<std::chrono::milliseconds>(now - epoch).count(); |         console_time += (now.count() - epoch); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // If the system time is in daylight saving, we give an additional hour to console time |  | ||||||
|     std::time_t now_time_t = std::chrono::system_clock::to_time_t(now); |  | ||||||
|     std::tm* now_tm = std::localtime(&now_time_t); |  | ||||||
|     if (now_tm && now_tm->tm_isdst > 0) |  | ||||||
|         console_time += 60 * 60 * 1000; |  | ||||||
|  |  | ||||||
|     return console_time; |     return console_time; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void UpdateTimeCallback(u64 userdata, s64 cycles_late) { | void Handler::UpdateTimeCallback(u64 userdata, int cycles_late) { | ||||||
|     DateTime& date_time = |     DateTime& date_time = | ||||||
|         shared_page.date_time_counter % 2 ? shared_page.date_time_0 : shared_page.date_time_1; |         shared_page.date_time_counter % 2 ? shared_page.date_time_0 : shared_page.date_time_1; | ||||||
|  |  | ||||||
| @@ -67,39 +100,20 @@ static void UpdateTimeCallback(u64 userdata, s64 cycles_late) { | |||||||
|     CoreTiming::ScheduleEvent(msToCycles(60 * 60 * 1000) - cycles_late, update_time_event); |     CoreTiming::ScheduleEvent(msToCycles(60 * 60 * 1000) - cycles_late, update_time_event); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Init() { | void Handler::SetMacAddress(const MacAddress& addr) { | ||||||
|     std::memset(&shared_page, 0, sizeof(shared_page)); |  | ||||||
|  |  | ||||||
|     shared_page.running_hw = 0x1; // product |  | ||||||
|  |  | ||||||
|     // Some games wait until this value becomes 0x1, before asking running_hw |  | ||||||
|     shared_page.unknown_value = 0x1; |  | ||||||
|  |  | ||||||
|     // Set to a completely full battery |  | ||||||
|     shared_page.battery_state.charge_level.Assign( |  | ||||||
|         static_cast<u8>(Service::PTM::ChargeLevels::CompletelyFull)); |  | ||||||
|     shared_page.battery_state.is_adapter_connected.Assign(1); |  | ||||||
|     shared_page.battery_state.is_charging.Assign(1); |  | ||||||
|  |  | ||||||
|     update_time_event = |  | ||||||
|         CoreTiming::RegisterEvent("SharedPage::UpdateTimeCallback", UpdateTimeCallback); |  | ||||||
|     CoreTiming::ScheduleEvent(0, update_time_event); |  | ||||||
|  |  | ||||||
|     float slidestate = |  | ||||||
|         Settings::values.toggle_3d ? (float_le)Settings::values.factor_3d / 100 : 0.0f; |  | ||||||
|     shared_page.sliderstate_3d = slidestate; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void SetMacAddress(const MacAddress& addr) { |  | ||||||
|     std::memcpy(shared_page.wifi_macaddr, addr.data(), sizeof(MacAddress)); |     std::memcpy(shared_page.wifi_macaddr, addr.data(), sizeof(MacAddress)); | ||||||
| } | } | ||||||
|  |  | ||||||
| void SetWifiLinkLevel(WifiLinkLevel level) { | void Handler::SetWifiLinkLevel(WifiLinkLevel level) { | ||||||
|     shared_page.wifi_link_level = static_cast<u8>(level); |     shared_page.wifi_link_level = static_cast<u8>(level); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Set3DLed(u8 state) { | void Handler::Set3DLed(u8 state) { | ||||||
|     shared_page.ledstate_3d = state; |     shared_page.ledstate_3d = state; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | SharedPageDef& Handler::GetSharedPage() { | ||||||
|  |     return shared_page; | ||||||
|  | } | ||||||
|  |  | ||||||
| } // namespace SharedPage | } // namespace SharedPage | ||||||
|   | |||||||
| @@ -10,6 +10,9 @@ | |||||||
|  * write access, according to 3dbrew; this is not emulated) |  * write access, according to 3dbrew; this is not emulated) | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | #include <chrono> | ||||||
|  | #include <ctime> | ||||||
|  | #include <memory> | ||||||
| #include "common/bit_field.h" | #include "common/bit_field.h" | ||||||
| #include "common/common_funcs.h" | #include "common/common_funcs.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| @@ -18,6 +21,10 @@ | |||||||
|  |  | ||||||
| //////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  |  | ||||||
|  | namespace CoreTiming { | ||||||
|  | struct EventType; | ||||||
|  | } | ||||||
|  |  | ||||||
| namespace SharedPage { | namespace SharedPage { | ||||||
|  |  | ||||||
| // See http://3dbrew.org/wiki/Configuration_Memory#Shared_Memory_Page_For_ARM11_Processes | // See http://3dbrew.org/wiki/Configuration_Memory#Shared_Memory_Page_For_ARM11_Processes | ||||||
| @@ -74,9 +81,9 @@ struct SharedPageDef { | |||||||
| static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE, | static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE, | ||||||
|               "Shared page structure size is wrong"); |               "Shared page structure size is wrong"); | ||||||
|  |  | ||||||
| extern SharedPageDef shared_page; | class Handler { | ||||||
|  | public: | ||||||
| void Init(); |     Handler(); | ||||||
|  |  | ||||||
|     void SetMacAddress(const MacAddress&); |     void SetMacAddress(const MacAddress&); | ||||||
|  |  | ||||||
| @@ -84,4 +91,15 @@ void SetWifiLinkLevel(WifiLinkLevel); | |||||||
|  |  | ||||||
|     void Set3DLed(u8); |     void Set3DLed(u8); | ||||||
|  |  | ||||||
|  |     SharedPageDef& GetSharedPage(); | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     u64 GetSystemTime() const; | ||||||
|  |     void UpdateTimeCallback(u64 userdata, int cycles_late); | ||||||
|  |     CoreTiming::EventType* update_time_event; | ||||||
|  |     std::chrono::seconds init_time; | ||||||
|  |  | ||||||
|  |     SharedPageDef shared_page; | ||||||
|  | }; | ||||||
|  |  | ||||||
| } // namespace SharedPage | } // namespace SharedPage | ||||||
|   | |||||||
| @@ -12,6 +12,11 @@ | |||||||
|  |  | ||||||
| namespace Settings { | namespace Settings { | ||||||
|  |  | ||||||
|  | enum class InitClock { | ||||||
|  |     SystemTime = 0, | ||||||
|  |     FixedTime = 1, | ||||||
|  | }; | ||||||
|  |  | ||||||
| enum class LayoutOption { | enum class LayoutOption { | ||||||
|     Default, |     Default, | ||||||
|     SingleScreen, |     SingleScreen, | ||||||
| @@ -106,8 +111,10 @@ struct Values { | |||||||
|     // Data Storage |     // Data Storage | ||||||
|     bool use_virtual_sd; |     bool use_virtual_sd; | ||||||
|  |  | ||||||
|     // System Region |     // System | ||||||
|     int region_value; |     int region_value; | ||||||
|  |     InitClock init_clock; | ||||||
|  |     u64 init_time; | ||||||
|  |  | ||||||
|     // Renderer |     // Renderer | ||||||
|     bool use_hw_renderer; |     bool use_hw_renderer; | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ | |||||||
| #include <catch2/catch.hpp> | #include <catch2/catch.hpp> | ||||||
| #include "core/hle/kernel/memory.h" | #include "core/hle/kernel/memory.h" | ||||||
| #include "core/hle/kernel/process.h" | #include "core/hle/kernel/process.h" | ||||||
|  | #include "core/hle/shared_page.h" | ||||||
| #include "core/memory.h" | #include "core/memory.h" | ||||||
|  |  | ||||||
| TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory]") { | TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory]") { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user