Files
eden/src/core/core.cpp
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

1025 lines
31 KiB
C++
Raw Normal View History

2025-06-09 01:40:21 +00:00
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
2013-09-05 18:33:46 -04:00
#include <array>
2021-06-22 04:22:19 -03:00
#include <atomic>
#include <memory>
2017-03-08 20:21:31 -05:00
#include <utility>
#include "game_settings.h"
2022-07-16 23:48:45 +01:00
#include "audio_core/audio_core.h"
#include "common/fs/fs.h"
2015-05-06 04:06:12 -03:00
#include "common/logging/log.h"
2021-04-14 16:07:40 -07:00
#include "common/settings.h"
#include "common/settings_enums.h"
2018-08-09 21:33:13 -04:00
#include "common/string_util.h"
#include "core/arm/exclusive_monitor.h"
#include "core/core.h"
2016-09-01 23:18:01 -04:00
#include "core/core_timing.h"
#include "core/cpu_manager.h"
#include "core/debugger/debugger.h"
#include "core/device_memory.h"
2024-01-18 21:31:41 +01:00
#include "core/file_sys/fs_filesystem.h"
#include "core/file_sys/patch_manager.h"
#include "core/file_sys/registered_cache.h"
2019-04-23 08:35:33 -04:00
#include "core/file_sys/romfs_factory.h"
#include "core/file_sys/savedata_factory.h"
2024-01-16 06:23:01 +01:00
#include "core/file_sys/vfs/vfs_concat.h"
#include "core/file_sys/vfs/vfs_real.h"
#include "core/gpu_dirty_memory_manager.h"
#include "core/hle/kernel/k_memory_manager.h"
2021-04-23 22:04:28 -07:00
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/kernel.h"
2020-01-25 18:55:32 -04:00
#include "core/hle/kernel/physical_core.h"
#include "core/hle/service/acc/profile_manager.h"
#include "core/hle/service/am/applet_manager.h"
#include "core/hle/service/am/frontend/applets.h"
2024-03-03 13:02:50 +00:00
#include "core/hle/service/am/process_creation.h"
#include "core/hle/service/apm/apm_controller.h"
2019-04-23 08:35:33 -04:00
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/glue/glue_manager.h"
#include "core/hle/service/glue/time/static.h"
#include "core/hle/service/psc/time/static.h"
#include "core/hle/service/psc/time/steady_clock.h"
#include "core/hle/service/psc/time/system_clock.h"
#include "core/hle/service/psc/time/time_zone_service.h"
#include "core/hle/service/service.h"
#include "core/hle/service/services.h"
#include "core/hle/service/set/system_settings_server.h"
#include "core/hle/service/sm/sm.h"
2021-12-25 20:27:52 +01:00
#include "core/internal_network/network.h"
#include "core/loader/loader.h"
#include "core/memory.h"
2019-05-30 19:36:18 -04:00
#include "core/memory/cheat_engine.h"
#include "core/perf_stats.h"
#include "core/reporter.h"
2019-06-07 11:11:11 -04:00
#include "core/tools/freezer.h"
2023-09-10 23:26:09 +03:00
#include "core/tools/renderdoc.h"
2024-01-04 20:37:43 -06:00
#include "hid_core/hid_core.h"
2021-12-25 20:27:52 +01:00
#include "network/network.h"
2022-01-30 10:31:13 +01:00
#include "video_core/host1x/host1x.h"
#include "video_core/renderer_base.h"
#include "video_core/video_core.h"
2015-09-02 08:56:38 -04:00
2013-09-05 18:33:46 -04:00
namespace Core {
FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
const std::string& path) {
// To account for split 00+01+etc files.
std::string dir_name;
std::string filename;
Common::SplitPath(path, &dir_name, &filename, nullptr);
if (filename == "00") {
2024-01-18 21:31:41 +01:00
const auto dir = vfs->OpenDirectory(dir_name, FileSys::OpenMode::Read);
std::vector<FileSys::VirtualFile> concat;
for (u32 i = 0; i < 0x10; ++i) {
const auto file_name = fmt::format("{:02X}", i);
auto next = dir->GetFile(file_name);
if (next != nullptr) {
concat.push_back(std::move(next));
} else {
next = dir->GetFile(file_name);
if (next == nullptr) {
break;
}
concat.push_back(std::move(next));
}
}
return FileSys::ConcatenatedVfsFile::MakeConcatenatedFile(dir->GetName(),
std::move(concat));
}
if (Common::FS::IsDir(path)) {
2024-01-18 21:31:41 +01:00
return vfs->OpenFile(path + "/main", FileSys::OpenMode::Read);
}
2024-01-18 21:31:41 +01:00
return vfs->OpenFile(path, FileSys::OpenMode::Read);
}
struct System::Impl {
explicit Impl(System& system)
2025-06-05 18:59:47 +00:00
: kernel{system}, fs_controller{system}, hid_core{}, cpu_manager{system},
reporter{system}, applet_manager{system}, frontend_applets{system}, profile_manager{} {}
u64 program_id;
void Initialize(System& system) {
device_memory = std::make_unique<Core::DeviceMemory>();
is_multicore = Settings::values.use_multi_core.GetValue();
extended_memory_layout =
Settings::values.memory_layout_mode.GetValue() != Settings::MemoryLayout::Memory_4Gb;
core_timing.SetMulticore(is_multicore);
core_timing.Initialize([&system]() { system.RegisterHostThread(); });
// Create a default fs if one doesn't already exist.
2022-10-18 19:12:18 -07:00
if (virtual_filesystem == nullptr) {
virtual_filesystem = std::make_shared<FileSys::RealVfsFilesystem>();
2022-10-18 19:12:18 -07:00
}
if (content_provider == nullptr) {
content_provider = std::make_unique<FileSys::ContentProviderUnion>();
2022-10-18 19:12:18 -07:00
}
// Create default implementations of applets if one is not provided.
frontend_applets.SetDefaultAppletsIfMissing();
is_async_gpu = Settings::values.use_asynchronous_gpu_emulation.GetValue();
kernel.SetMulticore(is_multicore);
cpu_manager.SetMulticore(is_multicore);
cpu_manager.SetAsyncGpu(is_async_gpu);
}
void ReinitializeIfNecessary(System& system) {
const bool must_reinitialize =
is_multicore != Settings::values.use_multi_core.GetValue() ||
extended_memory_layout != (Settings::values.memory_layout_mode.GetValue() !=
Settings::MemoryLayout::Memory_4Gb);
if (!must_reinitialize) {
return;
}
LOG_DEBUG(Kernel, "Re-initializing");
is_multicore = Settings::values.use_multi_core.GetValue();
extended_memory_layout =
Settings::values.memory_layout_mode.GetValue() != Settings::MemoryLayout::Memory_4Gb;
Initialize(system);
}
void RefreshTime(System& system) {
if (!system.IsPoweredOn()) {
return;
}
auto settings_service =
system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys",
true);
auto static_service_a =
system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:a", true);
auto static_service_s =
system.ServiceManager().GetService<Service::PSC::Time::StaticService>("time:s", true);
std::shared_ptr<Service::PSC::Time::SystemClock> user_clock;
2024-01-26 15:29:04 +00:00
static_service_a->GetStandardUserSystemClock(&user_clock);
std::shared_ptr<Service::PSC::Time::SystemClock> local_clock;
2024-01-26 15:29:04 +00:00
static_service_a->GetStandardLocalSystemClock(&local_clock);
std::shared_ptr<Service::PSC::Time::SystemClock> network_clock;
2024-01-26 15:29:04 +00:00
static_service_s->GetStandardNetworkSystemClock(&network_clock);
std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service;
2024-01-26 15:29:04 +00:00
static_service_a->GetTimeZoneService(&timezone_service);
Service::PSC::Time::LocationName name{};
auto new_name = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue());
std::memcpy(name.data(), new_name.data(), (std::min)(name.size(), new_name.size()));
2024-01-26 15:29:04 +00:00
timezone_service->SetDeviceLocationName(name);
u64 time_offset = 0;
if (Settings::values.custom_rtc_enabled) {
time_offset = Settings::values.custom_rtc_offset.GetValue();
}
2023-05-10 17:57:25 -04:00
const auto posix_time = std::chrono::system_clock::now().time_since_epoch();
const u64 current_time =
+std::chrono::duration_cast<std::chrono::seconds>(posix_time).count();
const u64 new_time = current_time + time_offset;
Service::PSC::Time::SystemClockContext context{};
settings_service->SetUserSystemClockContext(context);
user_clock->SetCurrentTime(new_time);
local_clock->SetCurrentTime(new_time);
2024-01-26 15:29:04 +00:00
network_clock->GetSystemClockContext(&context);
settings_service->SetNetworkSystemClockContext(context);
network_clock->SetCurrentTime(new_time);
2023-05-10 17:57:25 -04:00
}
2022-12-17 14:34:03 -05:00
void Run() {
2021-10-05 23:54:33 +02:00
std::unique_lock<std::mutex> lk(suspend_guard);
2024-02-14 16:57:20 -05:00
kernel.SuspendEmulation(false);
core_timing.SyncPause(false);
is_paused.store(false, std::memory_order_relaxed);
}
2022-12-17 14:34:03 -05:00
void Pause() {
2021-10-05 23:54:33 +02:00
std::unique_lock<std::mutex> lk(suspend_guard);
core_timing.SyncPause(true);
2024-02-14 16:57:20 -05:00
kernel.SuspendEmulation(true);
is_paused.store(true, std::memory_order_relaxed);
2015-09-02 08:56:38 -04:00
}
2022-07-16 23:48:45 +01:00
bool IsPaused() const {
return is_paused.load(std::memory_order_relaxed);
2022-07-16 23:48:45 +01:00
}
std::unique_lock<std::mutex> StallApplication() {
2021-10-16 00:20:19 +02:00
std::unique_lock<std::mutex> lk(suspend_guard);
2024-02-14 16:57:20 -05:00
kernel.SuspendEmulation(true);
2021-10-16 00:20:19 +02:00
core_timing.SyncPause(true);
return lk;
}
void UnstallApplication() {
if (!IsPaused()) {
2021-10-16 00:20:19 +02:00
core_timing.SyncPause(false);
2024-02-14 16:57:20 -05:00
kernel.SuspendEmulation(false);
2021-10-05 23:54:33 +02:00
}
}
void SetNVDECActive(bool is_nvdec_active) {
nvdec_active = is_nvdec_active;
}
bool GetNVDECActive() {
return nvdec_active;
}
void InitializeDebugger(System& system, u16 port) {
debugger = std::make_unique<Debugger>(system, port);
}
void InitializeKernel(System& system) {
LOG_DEBUG(Core, "initialized OK");
// Setting changes may require a full system reinitialization (e.g., disabling multicore).
ReinitializeIfNecessary(system);
2020-03-08 22:39:41 -04:00
kernel.Initialize();
cpu_manager.Initialize();
}
2018-11-11 16:39:25 -05:00
SystemResultStatus SetupForApplicationProcess(System& system, Frontend::EmuWindow& emu_window) {
2022-01-30 22:26:01 +01:00
host1x_core = std::make_unique<Tegra::Host1x::Host1x>(system);
2020-10-30 23:16:35 -07:00
gpu_core = VideoCore::CreateGPU(emu_window, system);
if (!gpu_core) {
2021-10-14 18:14:40 -04:00
return SystemResultStatus::ErrorVideoCore;
2020-10-30 23:16:35 -07:00
}
2022-07-16 23:48:45 +01:00
audio_core = std::make_unique<AudioCore::AudioCore>(system);
service_manager = std::make_shared<Service::SM::ServiceManager>(kernel);
services =
std::make_unique<Service::Services>(service_manager, system, stop_event.get_token());
is_powered_on = true;
exit_locked = false;
exit_requested = false;
2023-09-10 23:26:09 +03:00
if (Settings::values.enable_renderdoc_hotkey) {
renderdoc_api = std::make_unique<Tools::RenderdocAPI>();
}
LOG_DEBUG(Core, "Initialized OK");
2021-10-14 18:14:40 -04:00
return SystemResultStatus::Success;
}
2021-10-14 18:14:40 -04:00
SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
const std::string& filepath,
Service::AM::FrontendAppletParameters& params) {
2024-03-03 13:02:50 +00:00
InitializeKernel(system);
const auto file = GetGameFileFromPath(virtual_filesystem, filepath);
// Create the application process
Loader::ResultStatus load_result{};
std::vector<u8> control;
auto process =
Service::AM::CreateApplicationProcess(control, app_loader, load_result, system, file,
params.program_id, params.program_index);
if (load_result != Loader::ResultStatus::Success) {
LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result);
ShutdownMainProcess();
return static_cast<SystemResultStatus>(
static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result));
}
if (!app_loader) {
LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
2021-10-14 18:14:40 -04:00
return SystemResultStatus::ErrorGetLoader;
}
if (app_loader->ReadProgramId(params.program_id) != Loader::ResultStatus::Success) {
2024-03-03 13:02:50 +00:00
LOG_ERROR(Core, "Failed to find program id for ROM!");
}
std::string name = "Unknown program";
if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) {
LOG_ERROR(Core, "Failed to read title for ROM!");
}
2024-03-03 13:02:50 +00:00
LOG_INFO(Core, "Loading {} ({:016X}) ...", name, params.program_id);
2024-03-03 13:02:50 +00:00
// Make the process created be the application
kernel.MakeApplicationProcess(process->GetHandle());
// Set up the rest of the system.
SystemResultStatus init_result{SetupForApplicationProcess(system, emu_window)};
if (init_result != SystemResultStatus::Success) {
LOG_CRITICAL(Core, "Failed to initialize system (Error {})!",
static_cast<int>(init_result));
ShutdownMainProcess();
return init_result;
}
// Initialize cheat engine
if (cheat_engine) {
cheat_engine->Initialize();
}
2024-03-03 13:02:50 +00:00
// Register with applet manager
// All threads are started, begin main process execution, now that we're in the clear
applet_manager.CreateAndInsertByFrontendAppletParameters(std::move(process), params);
2019-04-23 08:35:33 -04:00
if (Settings::values.gamecard_inserted) {
if (Settings::values.gamecard_current_game) {
fs_controller.SetGameCard(GetGameFileFromPath(virtual_filesystem, filepath));
2021-06-28 15:58:16 -04:00
} else if (!Settings::values.gamecard_path.GetValue().empty()) {
2022-07-16 23:48:45 +01:00
const auto& gamecard_path = Settings::values.gamecard_path.GetValue();
2021-07-08 14:07:10 -04:00
fs_controller.SetGameCard(GetGameFileFromPath(virtual_filesystem, gamecard_path));
2019-04-23 08:35:33 -04:00
}
}
perf_stats = std::make_unique<PerfStats>(params.program_id);
// Reset counters and set time origin to current frame
GetAndResetPerfStats();
perf_stats->BeginSystemFrame();
std::string title_version;
const FileSys::PatchManager pm(params.program_id, system.GetFileSystemController(),
system.GetContentProvider());
const auto metadata = pm.GetControlMetadata();
if (metadata.first != nullptr) {
title_version = metadata.first->GetVersionString();
}
if (app_loader->ReadProgramId(program_id) != Loader::ResultStatus::Success) {
LOG_ERROR(Core, "Failed to find program id for ROM");
}
GameSettings::LoadOverrides(program_id, gpu_core->Renderer());
2025-06-05 18:59:47 +00:00
if (auto room_member = Network::GetRoomMember().lock()) {
2021-12-25 20:27:52 +01:00
Network::GameInfo game_info;
game_info.name = name;
game_info.id = params.program_id;
game_info.version = title_version;
2021-12-25 20:27:52 +01:00
room_member->SendGameInfo(game_info);
}
2021-10-14 18:14:40 -04:00
status = SystemResultStatus::Success;
return status;
}
void ShutdownMainProcess() {
2022-07-16 23:48:45 +01:00
SetShuttingDown(true);
// Reset per-game flags
Settings::values.use_squashed_iterated_blend = false;
is_powered_on = false;
exit_locked = false;
exit_requested = false;
2022-03-07 01:39:16 -05:00
if (gpu_core != nullptr) {
gpu_core->NotifyShutdown();
}
stop_event.request_stop();
2024-02-14 11:39:42 -05:00
core_timing.SyncPause(false);
Network::CancelPendingSocketOperations();
2024-02-14 16:57:20 -05:00
kernel.SuspendEmulation(true);
2022-07-16 23:48:45 +01:00
kernel.CloseServices();
2023-10-21 20:35:18 -04:00
kernel.ShutdownCores();
services.reset();
service_manager.reset();
fs_controller.Reset();
cheat_engine.reset();
core_timing.ClearPendingEvents();
app_loader.reset();
2022-07-16 23:48:45 +01:00
audio_core.reset();
gpu_core.reset();
2022-01-30 10:31:13 +01:00
host1x_core.reset();
perf_stats.reset();
2023-02-15 18:16:04 -05:00
cpu_manager.Shutdown();
debugger.reset();
kernel.Shutdown();
stop_event = {};
Network::RestartSocketOperations();
2025-06-05 18:59:47 +00:00
if (auto room_member = Network::GetRoomMember().lock()) {
2021-12-25 20:27:52 +01:00
Network::GameInfo game_info{};
room_member->SendGameInfo(game_info);
}
2024-03-03 13:02:50 +00:00
// Reset all glue registrations
arp_manager.ResetAll();
LOG_DEBUG(Core, "Shutdown OK");
}
2022-07-16 23:48:45 +01:00
bool IsShuttingDown() const {
return is_shutting_down;
}
void SetShuttingDown(bool shutting_down) {
is_shutting_down = shutting_down;
}
Loader::ResultStatus GetGameName(std::string& out) const {
if (app_loader == nullptr)
return Loader::ResultStatus::ErrorNotInitialized;
return app_loader->ReadTitle(out);
}
2021-10-14 18:14:40 -04:00
void SetStatus(SystemResultStatus new_status, const char* details = nullptr) {
status = new_status;
if (details) {
status_details = details;
}
}
PerfStatsResults GetAndResetPerfStats() {
return perf_stats->GetAndResetStats(core_timing.GetGlobalTimeUs());
}
2022-07-16 23:48:45 +01:00
mutable std::mutex suspend_guard;
std::atomic_bool is_paused{};
2022-07-16 23:48:45 +01:00
std::atomic<bool> is_shutting_down{};
2021-10-05 23:54:33 +02:00
Timing::CoreTiming core_timing;
Kernel::KernelCore kernel;
/// RealVfsFilesystem instance
FileSys::VirtualFilesystem virtual_filesystem;
/// ContentProviderUnion instance
std::unique_ptr<FileSys::ContentProviderUnion> content_provider;
2019-04-23 08:35:33 -04:00
Service::FileSystem::FileSystemController fs_controller;
/// AppLoader used to load the current executing application
std::unique_ptr<Loader::AppLoader> app_loader;
std::unique_ptr<Tegra::GPU> gpu_core;
2022-01-30 10:31:13 +01:00
std::unique_ptr<Tegra::Host1x::Host1x> host1x_core;
std::unique_ptr<Core::DeviceMemory> device_memory;
2022-07-16 23:48:45 +01:00
std::unique_ptr<AudioCore::AudioCore> audio_core;
2021-09-20 19:44:34 -05:00
Core::HID::HIDCore hid_core;
CpuManager cpu_manager;
2021-06-22 04:22:19 -03:00
std::atomic_bool is_powered_on{};
bool exit_locked = false;
bool exit_requested = false;
bool nvdec_active{};
2019-06-29 17:17:35 -04:00
Reporter reporter;
2019-05-30 19:36:18 -04:00
std::unique_ptr<Memory::CheatEngine> cheat_engine;
2019-06-07 11:11:11 -04:00
std::unique_ptr<Tools::Freezer> memory_freezer;
std::array<u8, 0x20> build_id{};
2023-09-10 23:26:09 +03:00
std::unique_ptr<Tools::RenderdocAPI> renderdoc_api;
/// Applets
Service::AM::AppletManager applet_manager;
Service::AM::Frontend::FrontendAppletHolder frontend_applets;
2018-11-11 16:39:25 -05:00
2019-06-28 22:46:31 -04:00
/// APM (Performance) services
Service::APM::Controller apm_controller{core_timing};
2019-06-29 17:17:35 -04:00
/// Service State
Service::Glue::ARPManager arp_manager;
Service::Account::ProfileManager profile_manager;
/// Service manager
std::shared_ptr<Service::SM::ServiceManager> service_manager;
/// Services
std::unique_ptr<Service::Services> services;
2020-07-11 21:42:56 -03:00
/// Network instance
Network::NetworkInstance network_instance;
/// Debugger
std::unique_ptr<Core::Debugger> debugger;
2021-10-14 18:14:40 -04:00
SystemResultStatus status = SystemResultStatus::Success;
std::string status_details = "";
std::unique_ptr<Core::PerfStats> perf_stats;
Core::SpeedLimiter speed_limiter;
bool is_multicore{};
bool is_async_gpu{};
bool extended_memory_layout{};
ExecuteProgramCallback execute_program_callback;
2021-09-25 23:14:49 -04:00
ExitCallback exit_callback;
std::stop_source stop_event;
std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
std::array<Core::GPUDirtyMemoryManager, Core::Hardware::NUM_CPU_CORES>
gpu_dirty_memory_managers;
2023-09-10 02:36:26 +02:00
std::deque<std::vector<u8>> user_channel;
std::mutex general_channel_mutex;
std::deque<std::vector<u8>> general_channel;
std::unique_ptr<Service::KernelHelpers::ServiceContext> general_channel_context; // lazy
std::unique_ptr<Service::Event> general_channel_event; // lazy
bool general_channel_initialized{false};
void EnsureGeneralChannelInitialized(System& system) {
if (general_channel_initialized) {
return;
}
general_channel_context = std::make_unique<Service::KernelHelpers::ServiceContext>(system, "GeneralChannel");
general_channel_event = std::make_unique<Service::Event>(*general_channel_context);
general_channel_initialized = true;
}
};
System::System() : impl{std::make_unique<Impl>(*this)} {}
2021-10-14 14:21:15 -04:00
System::~System() = default;
2021-08-13 18:39:45 +00:00
CpuManager& System::GetCpuManager() {
return impl->cpu_manager;
}
const CpuManager& System::GetCpuManager() const {
return impl->cpu_manager;
}
void System::Initialize() {
impl->Initialize(*this);
}
2022-12-17 14:34:03 -05:00
void System::Run() {
impl->Run();
}
2022-12-17 14:34:03 -05:00
void System::Pause() {
impl->Pause();
}
2022-07-16 23:48:45 +01:00
bool System::IsPaused() const {
return impl->IsPaused();
}
void System::ShutdownMainProcess() {
impl->ShutdownMainProcess();
}
2022-07-16 23:48:45 +01:00
bool System::IsShuttingDown() const {
return impl->IsShuttingDown();
}
void System::SetShuttingDown(bool shutting_down) {
impl->SetShuttingDown(shutting_down);
}
void System::DetachDebugger() {
if (impl->debugger) {
impl->debugger->NotifyShutdown();
}
}
std::unique_lock<std::mutex> System::StallApplication() {
return impl->StallApplication();
2021-10-16 00:20:19 +02:00
}
void System::UnstallApplication() {
impl->UnstallApplication();
2021-10-05 23:54:33 +02:00
}
void System::SetNVDECActive(bool is_nvdec_active) {
impl->SetNVDECActive(is_nvdec_active);
}
bool System::GetNVDECActive() {
return impl->GetNVDECActive();
}
void System::InitializeDebugger() {
impl->InitializeDebugger(*this, Settings::values.gdbstub_port.GetValue());
}
2021-10-14 18:14:40 -04:00
SystemResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath,
Service::AM::FrontendAppletParameters& params) {
return impl->Load(*this, emu_window, filepath, params);
}
bool System::IsPoweredOn() const {
2021-06-22 04:22:19 -03:00
return impl->is_powered_on.load(std::memory_order::relaxed);
2013-09-05 18:33:46 -04:00
}
2019-06-19 09:11:18 -04:00
void System::PrepareReschedule(const u32 core_index) {
impl->kernel.PrepareReschedule(core_index);
2019-04-02 09:22:53 -04:00
}
2023-04-30 17:14:06 +02:00
size_t System::GetCurrentHostThreadID() const {
return impl->kernel.GetCurrentHostThreadID();
}
std::span<GPUDirtyMemoryManager> System::GetGPUDirtyMemoryManager() {
return impl->gpu_dirty_memory_managers;
}
2023-12-25 07:32:16 +01:00
void System::GatherGPUDirtyMemory(std::function<void(PAddr, size_t)>& callback) {
for (auto& manager : impl->gpu_dirty_memory_managers) {
manager.Gather(callback);
}
}
PerfStatsResults System::GetAndResetPerfStats() {
return impl->GetAndResetPerfStats();
2017-02-19 14:34:47 -08:00
}
Kernel::PhysicalCore& System::CurrentPhysicalCore() {
2020-03-01 12:14:17 -04:00
return impl->kernel.CurrentPhysicalCore();
}
const Kernel::PhysicalCore& System::CurrentPhysicalCore() const {
2020-03-01 12:14:17 -04:00
return impl->kernel.CurrentPhysicalCore();
}
2019-03-29 17:02:57 -04:00
/// Gets the global scheduler
Kernel::GlobalSchedulerContext& System::GlobalSchedulerContext() {
return impl->kernel.GlobalSchedulerContext();
2019-03-29 17:02:57 -04:00
}
/// Gets the global scheduler
const Kernel::GlobalSchedulerContext& System::GlobalSchedulerContext() const {
return impl->kernel.GlobalSchedulerContext();
2019-03-29 17:02:57 -04:00
}
Kernel::KProcess* System::ApplicationProcess() {
return impl->kernel.ApplicationProcess();
}
Core::DeviceMemory& System::DeviceMemory() {
return *impl->device_memory;
}
const Core::DeviceMemory& System::DeviceMemory() const {
return *impl->device_memory;
}
const Kernel::KProcess* System::ApplicationProcess() const {
return impl->kernel.ApplicationProcess();
2018-08-28 12:30:33 -04:00
}
Memory::Memory& System::ApplicationMemory() {
return impl->kernel.ApplicationProcess()->GetMemory();
}
const Core::Memory::Memory& System::ApplicationMemory() const {
return impl->kernel.ApplicationProcess()->GetMemory();
}
Tegra::GPU& System::GPU() {
return *impl->gpu_core;
}
2018-02-21 16:37:48 +00:00
const Tegra::GPU& System::GPU() const {
return *impl->gpu_core;
}
2022-01-30 10:31:13 +01:00
Tegra::Host1x::Host1x& System::Host1x() {
return *impl->host1x_core;
}
const Tegra::Host1x::Host1x& System::Host1x() const {
return *impl->host1x_core;
}
VideoCore::RendererBase& System::Renderer() {
2020-03-24 20:58:49 -06:00
return impl->gpu_core->Renderer();
}
const VideoCore::RendererBase& System::Renderer() const {
2020-03-24 20:58:49 -06:00
return impl->gpu_core->Renderer();
}
Kernel::KernelCore& System::Kernel() {
return impl->kernel;
}
const Kernel::KernelCore& System::Kernel() const {
return impl->kernel;
}
2021-09-20 19:44:34 -05:00
HID::HIDCore& System::HIDCore() {
return impl->hid_core;
}
const HID::HIDCore& System::HIDCore() const {
return impl->hid_core;
}
2022-07-16 23:48:45 +01:00
AudioCore::AudioCore& System::AudioCore() {
return *impl->audio_core;
}
const AudioCore::AudioCore& System::AudioCore() const {
return *impl->audio_core;
}
Timing::CoreTiming& System::CoreTiming() {
return impl->core_timing;
}
const Timing::CoreTiming& System::CoreTiming() const {
return impl->core_timing;
}
Core::PerfStats& System::GetPerfStats() {
return *impl->perf_stats;
}
const Core::PerfStats& System::GetPerfStats() const {
return *impl->perf_stats;
}
Core::SpeedLimiter& System::SpeedLimiter() {
return impl->speed_limiter;
}
const Core::SpeedLimiter& System::SpeedLimiter() const {
return impl->speed_limiter;
}
u64 System::GetApplicationProcessProgramID() const {
2023-03-07 16:45:13 -05:00
return impl->kernel.ApplicationProcess()->GetProgramId();
}
Loader::ResultStatus System::GetGameName(std::string& out) const {
return impl->GetGameName(out);
}
2017-02-19 14:34:47 -08:00
2021-10-14 18:14:40 -04:00
void System::SetStatus(SystemResultStatus new_status, const char* details) {
impl->SetStatus(new_status, details);
}
const std::string& System::GetStatusDetails() const {
return impl->status_details;
}
Loader::AppLoader& System::GetAppLoader() {
return *impl->app_loader;
}
const Loader::AppLoader& System::GetAppLoader() const {
return *impl->app_loader;
}
2018-02-21 16:37:48 +00:00
void System::SetFilesystem(FileSys::VirtualFilesystem vfs) {
impl->virtual_filesystem = std::move(vfs);
}
FileSys::VirtualFilesystem System::GetFilesystem() const {
return impl->virtual_filesystem;
}
2019-05-30 19:36:18 -04:00
void System::RegisterCheatList(const std::vector<Memory::CheatEntry>& list,
2023-03-17 21:26:04 -04:00
const std::array<u8, 32>& build_id, u64 main_region_begin,
2019-05-30 19:36:18 -04:00
u64 main_region_size) {
impl->cheat_engine = std::make_unique<Memory::CheatEngine>(*this, list, build_id);
impl->cheat_engine->SetMainMemoryParameters(main_region_begin, main_region_size);
}
void System::SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set) {
impl->frontend_applets.SetFrontendAppletSet(std::move(set));
}
Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() {
return impl->frontend_applets;
2018-11-11 16:39:25 -05:00
}
const Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() const {
return impl->frontend_applets;
2018-11-11 16:39:25 -05:00
}
Service::AM::AppletManager& System::GetAppletManager() {
return impl->applet_manager;
}
void System::SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider) {
impl->content_provider = std::move(provider);
}
FileSys::ContentProvider& System::GetContentProvider() {
return *impl->content_provider;
}
const FileSys::ContentProvider& System::GetContentProvider() const {
return *impl->content_provider;
}
2023-07-21 19:22:14 -04:00
FileSys::ContentProviderUnion& System::GetContentProviderUnion() {
return *impl->content_provider;
}
const FileSys::ContentProviderUnion& System::GetContentProviderUnion() const {
return *impl->content_provider;
}
2019-04-23 08:35:33 -04:00
Service::FileSystem::FileSystemController& System::GetFileSystemController() {
return impl->fs_controller;
}
const Service::FileSystem::FileSystemController& System::GetFileSystemController() const {
return impl->fs_controller;
}
void System::RegisterContentProvider(FileSys::ContentProviderUnionSlot slot,
FileSys::ContentProvider* provider) {
impl->content_provider->SetSlot(slot, provider);
}
void System::ClearContentProvider(FileSys::ContentProviderUnionSlot slot) {
impl->content_provider->ClearSlot(slot);
}
const Reporter& System::GetReporter() const {
return impl->reporter;
}
Service::Glue::ARPManager& System::GetARPManager() {
return impl->arp_manager;
}
const Service::Glue::ARPManager& System::GetARPManager() const {
return impl->arp_manager;
}
2019-06-28 22:46:31 -04:00
Service::APM::Controller& System::GetAPMController() {
return impl->apm_controller;
}
const Service::APM::Controller& System::GetAPMController() const {
return impl->apm_controller;
}
Service::Account::ProfileManager& System::GetProfileManager() {
return impl->profile_manager;
}
const Service::Account::ProfileManager& System::GetProfileManager() const {
return impl->profile_manager;
}
void System::SetExitLocked(bool locked) {
impl->exit_locked = locked;
2019-07-06 13:08:33 -04:00
}
bool System::GetExitLocked() const {
return impl->exit_locked;
}
void System::SetExitRequested(bool requested) {
impl->exit_requested = requested;
}
bool System::GetExitRequested() const {
return impl->exit_requested;
2019-07-06 13:08:33 -04:00
}
void System::SetApplicationProcessBuildID(const CurrentBuildProcessID& id) {
impl->build_id = id;
}
const System::CurrentBuildProcessID& System::GetApplicationProcessBuildID() const {
return impl->build_id;
}
Service::SM::ServiceManager& System::ServiceManager() {
return *impl->service_manager;
}
const Service::SM::ServiceManager& System::ServiceManager() const {
return *impl->service_manager;
}
void System::RegisterCoreThread(std::size_t id) {
impl->kernel.RegisterCoreThread(id);
}
void System::RegisterHostThread() {
impl->kernel.RegisterHostThread();
}
bool System::IsMulticore() const {
return impl->is_multicore;
}
bool System::DebuggerEnabled() const {
return Settings::values.use_gdbstub.GetValue();
}
Core::Debugger& System::GetDebugger() {
return *impl->debugger;
}
const Core::Debugger& System::GetDebugger() const {
return *impl->debugger;
}
2023-09-10 23:26:09 +03:00
Tools::RenderdocAPI& System::GetRenderdocAPI() {
return *impl->renderdoc_api;
}
2023-02-18 16:26:48 -05:00
void System::RunServer(std::unique_ptr<Service::ServerManager>&& server_manager) {
return impl->kernel.RunServer(std::move(server_manager));
}
void System::RegisterExecuteProgramCallback(ExecuteProgramCallback&& callback) {
impl->execute_program_callback = std::move(callback);
}
void System::ExecuteProgram(std::size_t program_index) {
if (impl->execute_program_callback) {
impl->execute_program_callback(program_index);
} else {
LOG_CRITICAL(Core, "execute_program_callback must be initialized by the frontend");
}
}
2023-09-10 02:36:26 +02:00
std::deque<std::vector<u8>>& System::GetUserChannel() {
return impl->user_channel;
}
std::deque<std::vector<u8>>& System::GetGeneralChannel() {
return impl->general_channel;
}
void System::PushGeneralChannelData(std::vector<u8>&& data) {
std::scoped_lock lk{impl->general_channel_mutex};
impl->EnsureGeneralChannelInitialized(*this);
const bool was_empty = impl->general_channel.empty();
impl->general_channel.push_back(std::move(data));
if (was_empty) {
impl->general_channel_event->Signal();
}
}
bool System::TryPopGeneralChannel(std::vector<u8>& out_data) {
std::scoped_lock lk{impl->general_channel_mutex};
if (!impl->general_channel_initialized || impl->general_channel.empty()) {
return false;
}
out_data = std::move(impl->general_channel.back());
impl->general_channel.pop_back();
if (impl->general_channel.empty()) {
impl->general_channel_event->Clear();
}
return true;
}
Service::Event& System::GetGeneralChannelEvent() {
std::scoped_lock lk{impl->general_channel_mutex};
impl->EnsureGeneralChannelInitialized(*this);
return *impl->general_channel_event;
}
2021-09-25 23:14:49 -04:00
void System::RegisterExitCallback(ExitCallback&& callback) {
impl->exit_callback = std::move(callback);
}
void System::Exit() {
if (impl->exit_callback) {
impl->exit_callback();
} else {
LOG_CRITICAL(Core, "exit_callback must be initialized by the frontend");
}
}
2021-04-14 16:07:40 -07:00
void System::ApplySettings() {
impl->RefreshTime(*this);
2023-05-10 17:57:25 -04:00
2021-04-14 16:07:40 -07:00
if (IsPoweredOn()) {
Renderer().RefreshBaseSettings();
}
}
} // namespace Core