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 | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #include <iomanip> | ||||
| #include <memory> | ||||
| #include <sstream> | ||||
| #include <unordered_map> | ||||
| #include <SDL.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.region_value = | ||||
|         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 | ||||
|     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 | ||||
| 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] | ||||
| # Which camera engine to use for the right outer camera | ||||
| # 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.region_value = | ||||
|         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->beginGroup("Miscellaneous"); | ||||
| @@ -409,6 +412,10 @@ void Config::SaveValues() { | ||||
|     qt_config->beginGroup("System"); | ||||
|     WriteSetting("is_new_3ds", Settings::values.is_new_3ds, false); | ||||
|     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->beginGroup("Miscellaneous"); | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
| #include "core/core.h" | ||||
| #include "core/hle/service/cfg/cfg.h" | ||||
| #include "core/hle/service/fs/archive.h" | ||||
| #include "core/settings.h" | ||||
| #include "ui_configure_system.h" | ||||
|  | ||||
| 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, | ||||
|             static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, | ||||
|             &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, | ||||
|             &ConfigureSystem::refreshConsoleID); | ||||
|     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() {} | ||||
| @@ -236,6 +240,11 @@ ConfigureSystem::~ConfigureSystem() {} | ||||
| void ConfigureSystem::setConfiguration() { | ||||
|     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) { | ||||
|         cfg = Service::CFG::GetCurrentModule(); | ||||
|         ReadSystemSettings(); | ||||
| @@ -334,6 +343,11 @@ void ConfigureSystem::applyConfiguration() { | ||||
|     // update the config savegame if any item is modified. | ||||
|     if (modified) | ||||
|         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) { | ||||
| @@ -361,6 +375,24 @@ void ConfigureSystem::updateBirthdayComboBox(int birthmonth_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() { | ||||
|     QMessageBox::StandardButton reply; | ||||
|     QString warning_text = tr("This will replace your current virtual 3DS with a new one. " | ||||
|   | ||||
| @@ -31,10 +31,12 @@ public: | ||||
|  | ||||
| public slots: | ||||
|     void updateBirthdayComboBox(int birthmonth_index); | ||||
|     void updateInitTime(int init_clock); | ||||
|     void refreshConsoleID(); | ||||
|  | ||||
| private: | ||||
|     void ReadSystemSettings(); | ||||
|     void ConfigureTime(); | ||||
|  | ||||
|     std::unique_ptr<Ui::ConfigureSystem> ui; | ||||
|     bool enabled; | ||||
|   | ||||
| @@ -232,13 +232,45 @@ | ||||
|          </widget> | ||||
|         </item> | ||||
|         <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"> | ||||
|           <property name="text"> | ||||
|            <string>Console ID:</string> | ||||
|           </property> | ||||
|          </widget> | ||||
|         </item> | ||||
|         <item row="5" column="1"> | ||||
|         <item row="7" column="1"> | ||||
|          <widget class="QPushButton" name="button_regenerate_console_id"> | ||||
|           <property name="sizePolicy"> | ||||
|            <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>(); | ||||
|     service_manager = std::make_shared<Service::SM::ServiceManager>(); | ||||
|     shared_page_handler = std::make_shared<SharedPage::Handler>(); | ||||
|  | ||||
|     HW::Init(); | ||||
|     Kernel::Init(system_mode); | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
| #include <string> | ||||
| #include "common/common_types.h" | ||||
| #include "core/frontend/applets/swkbd.h" | ||||
| #include "core/hle/shared_page.h" | ||||
| #include "core/loader/loader.h" | ||||
| #include "core/memory.h" | ||||
| #include "core/perf_stats.h" | ||||
| @@ -163,6 +164,10 @@ public: | ||||
|         return registered_swkbd; | ||||
|     } | ||||
|  | ||||
|     std::shared_ptr<SharedPage::Handler> GetSharedPageHandler() const { | ||||
|         return shared_page_handler; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     /** | ||||
|      * Initialize the emulated system. | ||||
| @@ -196,6 +201,9 @@ private: | ||||
|     /// Frontend applets | ||||
|     std::shared_ptr<Frontend::SoftwareKeyboard> registered_swkbd; | ||||
|  | ||||
|     /// Shared Page | ||||
|     std::shared_ptr<SharedPage::Handler> shared_page_handler; | ||||
|  | ||||
|     static System s_instance; | ||||
|  | ||||
|     ResultStatus status = ResultStatus::Success; | ||||
|   | ||||
| @@ -19,7 +19,6 @@ unsigned int Object::next_object_id; | ||||
| /// Initialize the kernel | ||||
| void Init(u32 system_mode) { | ||||
|     ConfigMem::Init(); | ||||
|     SharedPage::Init(); | ||||
|  | ||||
|     Kernel::MemoryInit(system_mode); | ||||
|  | ||||
|   | ||||
| @@ -11,11 +11,11 @@ | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "core/core.h" | ||||
| #include "core/hle/config_mem.h" | ||||
| #include "core/hle/kernel/memory.h" | ||||
| #include "core/hle/kernel/vm_manager.h" | ||||
| #include "core/hle/result.h" | ||||
| #include "core/hle/shared_page.h" | ||||
| #include "core/memory.h" | ||||
| #include "core/memory_setup.h" | ||||
|  | ||||
| @@ -160,9 +160,12 @@ void MapSharedPages(VMManager& address_space) { | ||||
|                            .Unwrap(); | ||||
|     address_space.Reprotect(cfg_mem_vma, VMAPermission::Read); | ||||
|  | ||||
|     auto shared_page_vma = address_space | ||||
|                                .MapBackingMemory(Memory::SHARED_PAGE_VADDR, | ||||
|                                                  reinterpret_cast<u8*>(&SharedPage::shared_page), | ||||
|     auto shared_page_vma = | ||||
|         address_space | ||||
|             .MapBackingMemory( | ||||
|                 Memory::SHARED_PAGE_VADDR, | ||||
|                 reinterpret_cast<u8*>( | ||||
|                     &Core::System::GetInstance().GetSharedPageHandler()->GetSharedPage()), | ||||
|                 Memory::SHARED_PAGE_SIZE, MemoryState::Shared) | ||||
|             .Unwrap(); | ||||
|     address_space.Reprotect(shared_page_vma, VMAPermission::Read); | ||||
|   | ||||
| @@ -13,7 +13,6 @@ | ||||
| #include "core/hle/kernel/shared_memory.h" | ||||
| #include "core/hle/result.h" | ||||
| #include "core/hle/service/gsp/gsp_gpu.h" | ||||
| #include "core/hle/shared_page.h" | ||||
| #include "core/hw/gpu.h" | ||||
| #include "core/hw/hw.h" | ||||
| #include "core/hw/lcd.h" | ||||
| @@ -732,7 +731,8 @@ void GSP_GPU::SetLedForceOff(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp(ctx, 0x1C, 1, 0); | ||||
|  | ||||
|     u8 state = rp.Pop<u8>(); | ||||
|     SharedPage::Set3DLed(state); | ||||
|  | ||||
|     Core::System::GetInstance().GetSharedPageHandler()->Set3DLed(state); | ||||
|  | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|   | ||||
| @@ -14,6 +14,7 @@ | ||||
| #include <cryptopp/osrng.h> | ||||
| #include "common/common_types.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "core/core.h" | ||||
| #include "core/core_timing.h" | ||||
| #include "core/hle/ipc_helpers.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_connection.h" | ||||
| #include "core/hle/service/nwm/uds_data.h" | ||||
| #include "core/hle/shared_page.h" | ||||
| #include "core/memory.h" | ||||
| #include "network/network.h" | ||||
|  | ||||
| @@ -1334,8 +1334,10 @@ NWM_UDS::NWM_UDS() : ServiceFramework("nwm::UDS") { | ||||
|             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() { | ||||
|   | ||||
| @@ -4,7 +4,6 @@ | ||||
|  | ||||
| #include <chrono> | ||||
| #include <cstring> | ||||
| #include <ctime> | ||||
| #include "core/core_timing.h" | ||||
| #include "core/hle/service/ptm/ptm.h" | ||||
| #include "core/hle/shared_page.h" | ||||
| @@ -14,13 +13,53 @@ | ||||
|  | ||||
| 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. | ||||
| static u64 GetSystemTime() { | ||||
|     auto now = std::chrono::system_clock::now(); | ||||
| u64 Handler::GetSystemTime() const { | ||||
|     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, | ||||
|     // 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_year = 100; | ||||
|     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, | ||||
|     // so we use the milliseconds between 1900 and 2000 as base console time | ||||
|     u64 console_time = 3155673600000ULL; | ||||
|  | ||||
|     // Only when system time is after 2000, we set it as 3DS system time | ||||
|     if (now > epoch) { | ||||
|         console_time += std::chrono::duration_cast<std::chrono::milliseconds>(now - epoch).count(); | ||||
|     if (now.count() > epoch) { | ||||
|         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; | ||||
| } | ||||
|  | ||||
| static void UpdateTimeCallback(u64 userdata, s64 cycles_late) { | ||||
| void Handler::UpdateTimeCallback(u64 userdata, int cycles_late) { | ||||
|     DateTime& date_time = | ||||
|         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); | ||||
| } | ||||
|  | ||||
| void Init() { | ||||
|     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) { | ||||
| void Handler::SetMacAddress(const MacAddress& addr) { | ||||
|     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); | ||||
| } | ||||
|  | ||||
| void Set3DLed(u8 state) { | ||||
| void Handler::Set3DLed(u8 state) { | ||||
|     shared_page.ledstate_3d = state; | ||||
| } | ||||
|  | ||||
| SharedPageDef& Handler::GetSharedPage() { | ||||
|     return shared_page; | ||||
| } | ||||
|  | ||||
| } // namespace SharedPage | ||||
|   | ||||
| @@ -10,6 +10,9 @@ | ||||
|  * write access, according to 3dbrew; this is not emulated) | ||||
|  */ | ||||
|  | ||||
| #include <chrono> | ||||
| #include <ctime> | ||||
| #include <memory> | ||||
| #include "common/bit_field.h" | ||||
| #include "common/common_funcs.h" | ||||
| #include "common/common_types.h" | ||||
| @@ -18,6 +21,10 @@ | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| namespace CoreTiming { | ||||
| struct EventType; | ||||
| } | ||||
|  | ||||
| namespace SharedPage { | ||||
|  | ||||
| // See http://3dbrew.org/wiki/Configuration_Memory#Shared_Memory_Page_For_ARM11_Processes | ||||
| @@ -74,14 +81,25 @@ struct SharedPageDef { | ||||
| static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE, | ||||
|               "Shared page structure size is wrong"); | ||||
|  | ||||
| extern SharedPageDef shared_page; | ||||
| class Handler { | ||||
| public: | ||||
|     Handler(); | ||||
|  | ||||
| void Init(); | ||||
|     void SetMacAddress(const MacAddress&); | ||||
|  | ||||
| void SetMacAddress(const MacAddress&); | ||||
|     void SetWifiLinkLevel(WifiLinkLevel); | ||||
|  | ||||
| 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 | ||||
|   | ||||
| @@ -12,6 +12,11 @@ | ||||
|  | ||||
| namespace Settings { | ||||
|  | ||||
| enum class InitClock { | ||||
|     SystemTime = 0, | ||||
|     FixedTime = 1, | ||||
| }; | ||||
|  | ||||
| enum class LayoutOption { | ||||
|     Default, | ||||
|     SingleScreen, | ||||
| @@ -106,8 +111,10 @@ struct Values { | ||||
|     // Data Storage | ||||
|     bool use_virtual_sd; | ||||
|  | ||||
|     // System Region | ||||
|     // System | ||||
|     int region_value; | ||||
|     InitClock init_clock; | ||||
|     u64 init_time; | ||||
|  | ||||
|     // Renderer | ||||
|     bool use_hw_renderer; | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
| #include <catch2/catch.hpp> | ||||
| #include "core/hle/kernel/memory.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/hle/shared_page.h" | ||||
| #include "core/memory.h" | ||||
|  | ||||
| TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory]") { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user