Lime3DS/src/core/hle/shared_page.cpp
James Rowe ffe94421b2 UDS: Add non zero mac address to the shared page
Apparently several games check the shared page mac address and wifi
link level values, and will refuse to start UDS if they are not correct.
This change gives a default value (in case you aren't connected to a
network) and will read the value from Room if you are connected.
2018-02-22 10:17:38 -07:00

100 lines
3.3 KiB
C++

// Copyright 2015 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <chrono>
#include <cstring>
#include <ctime>
#include "core/core_timing.h"
#include "core/hle/service/ptm/ptm.h"
#include "core/hle/shared_page.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
namespace SharedPage {
SharedPageDef shared_page;
static CoreTiming::EventType* update_time_event;
/// 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();
// 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.
std::tm epoch_tm;
epoch_tm.tm_sec = 0;
epoch_tm.tm_min = 0;
epoch_tm.tm_hour = 0;
epoch_tm.tm_mday = 1;
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));
// 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 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, int cycles_late) {
DateTime& date_time =
shared_page.date_time_counter % 2 ? shared_page.date_time_0 : shared_page.date_time_1;
date_time.date_time = GetSystemTime();
date_time.update_tick = CoreTiming::GetTicks();
date_time.tick_to_second_coefficient = BASE_CLOCK_RATE_ARM11;
date_time.tick_offset = 0;
++shared_page.date_time_counter;
// system time is updated hourly
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);
SetWifiLinkLevel(WifiLinkLevel::POOR);
SetMacAddress(DefaultMac);
}
void SetMacAddress(const MacAddress& addr) {
std::memcpy(shared_page.wifi_macaddr, addr.data(), sizeof(MacAddress));
}
void SetWifiLinkLevel(WifiLinkLevel level) {
shared_page.wifi_link_level = static_cast<u8>(level);
}
} // namespace