mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	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:
		
							parent
							
								
									13262c187c
								
							
						
					
					
						commit
						b20607dfc6
					
				
					 16 changed files with 220 additions and 61 deletions
				
			
		|  | @ -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,11 +160,14 @@ 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), | ||||
|                                                  Memory::SHARED_PAGE_SIZE, MemoryState::Shared) | ||||
|                                .Unwrap(); | ||||
|     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
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue