HLE: move SharedPage into Kernel

similar to config_mem, kernel is responsible for setting up this
This commit is contained in:
Weiyi Wang 2018-10-25 11:23:52 -04:00
parent 773ec47629
commit 263290d48c
12 changed files with 32 additions and 23 deletions

View file

@ -8,9 +8,9 @@
#include "core/hle/kernel/memory.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/shared_page.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/timer.h"
#include "core/hle/shared_page.h"
namespace Kernel {
@ -64,4 +64,12 @@ const TimerManager& KernelSystem::GetTimerManager() const {
return *timer_manager;
}
SharedPage::Handler& KernelSystem::GetSharedPageHandler() {
return *shared_page_handler;
}
const SharedPage::Handler& KernelSystem::GetSharedPageHandler() const {
return *shared_page_handler;
}
} // namespace Kernel

View file

@ -16,6 +16,10 @@ namespace ConfigMem {
class Handler;
}
namespace SharedPage {
class Handler;
}
namespace Kernel {
class AddressArbiter;
@ -202,6 +206,9 @@ public:
void MapSharedPages(VMManager& address_space);
SharedPage::Handler& GetSharedPageHandler();
const SharedPage::Handler& GetSharedPageHandler() const;
private:
void MemoryInit(u32 mem_type);
@ -221,6 +228,7 @@ private:
std::unique_ptr<TimerManager> timer_manager;
std::unique_ptr<ConfigMem::Handler> config_mem_handler;
std::unique_ptr<SharedPage::Handler> shared_page_handler;
};
} // namespace Kernel

View file

@ -14,6 +14,7 @@
#include "core/core.h"
#include "core/hle/kernel/config_mem.h"
#include "core/hle/kernel/memory.h"
#include "core/hle/kernel/shared_page.h"
#include "core/hle/kernel/vm_manager.h"
#include "core/hle/result.h"
#include "core/memory.h"
@ -72,6 +73,8 @@ void KernelSystem::MemoryInit(u32 mem_type) {
config_mem.app_mem_alloc = memory_region_sizes[mem_type][0];
config_mem.sys_mem_alloc = memory_regions[1].size;
config_mem.base_mem_alloc = memory_regions[2].size;
shared_page_handler = std::make_unique<SharedPage::Handler>();
}
void MemoryShutdown() {
@ -164,11 +167,9 @@ void KernelSystem::MapSharedPages(VMManager& address_space) {
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)
.MapBackingMemory(Memory::SHARED_PAGE_VADDR,
reinterpret_cast<u8*>(&shared_page_handler->GetSharedPage()),
Memory::SHARED_PAGE_SIZE, MemoryState::Shared)
.Unwrap();
address_space.Reprotect(shared_page_vma, VMAPermission::Read);
}

View file

@ -0,0 +1,126 @@
// Copyright 2015 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <chrono>
#include <cstring>
#include "core/core_timing.h"
#include "core/hle/kernel/shared_page.h"
#include "core/hle/service/ptm/ptm.h"
#include "core/movie.h"
#include "core/settings.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
namespace SharedPage {
static std::chrono::seconds GetInitTime() {
u64 override_init_time = Core::Movie::GetInstance().GetOverrideInitTime();
if (override_init_time) {
// Override the clock init time with the one in the movie
return std::chrono::seconds(override_init_time);
}
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);
}
}
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.
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.
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;
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.count() > epoch) {
console_time += (now.count() - epoch);
}
return console_time;
}
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;
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 Handler::SetMacAddress(const MacAddress& addr) {
std::memcpy(shared_page.wifi_macaddr, addr.data(), sizeof(MacAddress));
}
void Handler::SetWifiLinkLevel(WifiLinkLevel level) {
shared_page.wifi_link_level = static_cast<u8>(level);
}
void Handler::Set3DLed(u8 state) {
shared_page.ledstate_3d = state;
}
SharedPageDef& Handler::GetSharedPage() {
return shared_page;
}
} // namespace SharedPage

View file

@ -0,0 +1,105 @@
// Copyright 2015 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
/**
* The shared page stores various runtime configuration settings. This memory page is
* read-only for user processes (there is a bit in the header that grants the process
* 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"
#include "common/swap.h"
#include "core/memory.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
namespace CoreTiming {
struct EventType;
}
namespace SharedPage {
// See http://3dbrew.org/wiki/Configuration_Memory#Shared_Memory_Page_For_ARM11_Processes
struct DateTime {
u64_le date_time; // 0
u64_le update_tick; // 8
u64_le tick_to_second_coefficient; // 10
u64_le tick_offset; // 18
};
static_assert(sizeof(DateTime) == 0x20, "Datetime size is wrong");
union BatteryState {
u8 raw;
BitField<0, 1, u8> is_adapter_connected;
BitField<1, 1, u8> is_charging;
BitField<2, 3, u8> charge_level;
};
using MacAddress = std::array<u8, 6>;
// Default MAC address in the Nintendo 3DS range
constexpr MacAddress DefaultMac = {0x40, 0xF4, 0x07, 0x00, 0x00, 0x00};
enum class WifiLinkLevel : u8 {
OFF = 0,
POOR = 1,
GOOD = 2,
BEST = 3,
};
struct SharedPageDef {
// Most of these names are taken from the 3dbrew page linked above.
u32_le date_time_counter; // 0
u8 running_hw; // 4
/// "Microcontroller hardware info"
u8 mcu_hw_info; // 5
INSERT_PADDING_BYTES(0x20 - 0x6); // 6
DateTime date_time_0; // 20
DateTime date_time_1; // 40
u8 wifi_macaddr[6]; // 60
u8 wifi_link_level; // 66
u8 wifi_unknown2; // 67
INSERT_PADDING_BYTES(0x80 - 0x68); // 68
float_le sliderstate_3d; // 80
u8 ledstate_3d; // 84
BatteryState battery_state; // 85
u8 unknown_value; // 86
INSERT_PADDING_BYTES(0xA0 - 0x87); // 87
u64_le menu_title_id; // A0
u64_le active_menu_title_id; // A8
INSERT_PADDING_BYTES(0x1000 - 0xB0); // B0
};
static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE,
"Shared page structure size is wrong");
class Handler {
public:
Handler();
void SetMacAddress(const MacAddress&);
void SetWifiLinkLevel(WifiLinkLevel);
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

View file

@ -12,7 +12,6 @@
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/timer.h"
#include "core/hle/shared_page.h"
namespace Kernel {