1
0
Fork 0
forked from suyu/suyu
suyu/src/core/core.cpp

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

995 lines
30 KiB
C++
Raw Normal View History

chore: make yuzu REUSE compliant [REUSE] is a specification that aims at making file copyright information consistent, so that it can be both human and machine readable. It basically requires that all files have a header containing copyright and licensing information. When this isn't possible, like when dealing with binary assets, generated files or embedded third-party dependencies, it is permitted to insert copyright information in the `.reuse/dep5` file. Oh, and it also requires that all the licenses used in the project are present in the `LICENSES` folder, that's why the diff is so huge. This can be done automatically with `reuse download --all`. The `reuse` tool also contains a handy subcommand that analyzes the project and tells whether or not the project is (still) compliant, `reuse lint`. Following REUSE has a few advantages over the current approach: - Copyright information is easy to access for users / downstream - Files like `dist/license.md` do not need to exist anymore, as `.reuse/dep5` is used instead - `reuse lint` makes it easy to ensure that copyright information of files like binary assets / images is always accurate and up to date To add copyright information of files that didn't have it I looked up who committed what and when, for each file. As yuzu contributors do not have to sign a CLA or similar I couldn't assume that copyright ownership was of the "yuzu Emulator Project", so I used the name and/or email of the commit author instead. [REUSE]: https://reuse.software Follow-up to 01cf05bc75b1e47beb08937439f3ed9339e7b254
2022-05-15 02:06:02 +02:00
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <array>
#include <atomic>
#include <memory>
#include <utility>
2022-07-17 00:48:45 +02:00
#include "audio_core/audio_core.h"
common: fs: Rework the Common Filesystem interface to make use of std::filesystem (#6270) * common: fs: fs_types: Create filesystem types Contains various filesystem types used by the Common::FS library * common: fs: fs_util: Add std::string to std::u8string conversion utility * common: fs: path_util: Add utlity functions for paths Contains various utility functions for getting or manipulating filesystem paths used by the Common::FS library * common: fs: file: Rewrite the IOFile implementation * common: fs: Reimplement Common::FS library using std::filesystem * common: fs: fs_paths: Add fs_paths to replace common_paths * common: fs: path_util: Add the rest of the path functions * common: Remove the previous Common::FS implementation * general: Remove unused fs includes * string_util: Remove unused function and include * nvidia_flags: Migrate to the new Common::FS library * settings: Migrate to the new Common::FS library * logging: backend: Migrate to the new Common::FS library * core: Migrate to the new Common::FS library * perf_stats: Migrate to the new Common::FS library * reporter: Migrate to the new Common::FS library * telemetry_session: Migrate to the new Common::FS library * key_manager: Migrate to the new Common::FS library * bis_factory: Migrate to the new Common::FS library * registered_cache: Migrate to the new Common::FS library * xts_archive: Migrate to the new Common::FS library * service: acc: Migrate to the new Common::FS library * applets/profile: Migrate to the new Common::FS library * applets/web: Migrate to the new Common::FS library * service: filesystem: Migrate to the new Common::FS library * loader: Migrate to the new Common::FS library * gl_shader_disk_cache: Migrate to the new Common::FS library * nsight_aftermath_tracker: Migrate to the new Common::FS library * vulkan_library: Migrate to the new Common::FS library * configure_debug: Migrate to the new Common::FS library * game_list_worker: Migrate to the new Common::FS library * config: Migrate to the new Common::FS library * configure_filesystem: Migrate to the new Common::FS library * configure_per_game_addons: Migrate to the new Common::FS library * configure_profile_manager: Migrate to the new Common::FS library * configure_ui: Migrate to the new Common::FS library * input_profiles: Migrate to the new Common::FS library * yuzu_cmd: config: Migrate to the new Common::FS library * yuzu_cmd: Migrate to the new Common::FS library * vfs_real: Migrate to the new Common::FS library * vfs: Migrate to the new Common::FS library * vfs_libzip: Migrate to the new Common::FS library * service: bcat: Migrate to the new Common::FS library * yuzu: main: Migrate to the new Common::FS library * vfs_real: Delete the contents of an existing file in CreateFile Current usages of CreateFile expect to delete the contents of an existing file, retain this behavior for now. * input_profiles: Don't iterate the input profile dir if it does not exist Silences an error produced in the log if the directory does not exist. * game_list_worker: Skip parsing file if the returned VfsFile is nullptr Prevents crashes in GetLoader when the virtual file is nullptr * common: fs: Validate paths for path length * service: filesystem: Open the mod load directory as read only
2021-05-26 01:32:56 +02:00
#include "common/fs/fs.h"
2015-05-06 09:06:12 +02:00
#include "common/logging/log.h"
#include "common/microprofile.h"
#include "common/settings.h"
#include "common/settings_enums.h"
#include "common/string_util.h"
#include "core/arm/exclusive_monitor.h"
#include "core/core.h"
#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"
#include "core/file_sys/romfs_factory.h"
#include "core/file_sys/savedata_factory.h"
#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"
#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"
#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-08 23:44:03 +01:00
#include "core/hle/service/am/process_creation.h"
#include "core/hle/service/apm/apm_controller.h"
#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"
#include "core/internal_network/network.h"
#include "core/loader/loader.h"
#include "core/memory.h"
#include "core/memory/cheat_engine.h"
#include "core/perf_stats.h"
#include "core/reporter.h"
#include "core/tools/freezer.h"
2023-09-10 22:26:09 +02:00
#include "core/tools/renderdoc.h"
#include "hid_core/hid_core.h"
#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 14:56:38 +02:00
MICROPROFILE_DEFINE(ARM_CPU0, "ARM", "CPU 0", MP_RGB(255, 64, 64));
MICROPROFILE_DEFINE(ARM_CPU1, "ARM", "CPU 1", MP_RGB(255, 64, 64));
MICROPROFILE_DEFINE(ARM_CPU2, "ARM", "CPU 2", MP_RGB(255, 64, 64));
MICROPROFILE_DEFINE(ARM_CPU3, "ARM", "CPU 3", MP_RGB(255, 64, 64));
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));
}
common: fs: Rework the Common Filesystem interface to make use of std::filesystem (#6270) * common: fs: fs_types: Create filesystem types Contains various filesystem types used by the Common::FS library * common: fs: fs_util: Add std::string to std::u8string conversion utility * common: fs: path_util: Add utlity functions for paths Contains various utility functions for getting or manipulating filesystem paths used by the Common::FS library * common: fs: file: Rewrite the IOFile implementation * common: fs: Reimplement Common::FS library using std::filesystem * common: fs: fs_paths: Add fs_paths to replace common_paths * common: fs: path_util: Add the rest of the path functions * common: Remove the previous Common::FS implementation * general: Remove unused fs includes * string_util: Remove unused function and include * nvidia_flags: Migrate to the new Common::FS library * settings: Migrate to the new Common::FS library * logging: backend: Migrate to the new Common::FS library * core: Migrate to the new Common::FS library * perf_stats: Migrate to the new Common::FS library * reporter: Migrate to the new Common::FS library * telemetry_session: Migrate to the new Common::FS library * key_manager: Migrate to the new Common::FS library * bis_factory: Migrate to the new Common::FS library * registered_cache: Migrate to the new Common::FS library * xts_archive: Migrate to the new Common::FS library * service: acc: Migrate to the new Common::FS library * applets/profile: Migrate to the new Common::FS library * applets/web: Migrate to the new Common::FS library * service: filesystem: Migrate to the new Common::FS library * loader: Migrate to the new Common::FS library * gl_shader_disk_cache: Migrate to the new Common::FS library * nsight_aftermath_tracker: Migrate to the new Common::FS library * vulkan_library: Migrate to the new Common::FS library * configure_debug: Migrate to the new Common::FS library * game_list_worker: Migrate to the new Common::FS library * config: Migrate to the new Common::FS library * configure_filesystem: Migrate to the new Common::FS library * configure_per_game_addons: Migrate to the new Common::FS library * configure_profile_manager: Migrate to the new Common::FS library * configure_ui: Migrate to the new Common::FS library * input_profiles: Migrate to the new Common::FS library * yuzu_cmd: config: Migrate to the new Common::FS library * yuzu_cmd: Migrate to the new Common::FS library * vfs_real: Migrate to the new Common::FS library * vfs: Migrate to the new Common::FS library * vfs_libzip: Migrate to the new Common::FS library * service: bcat: Migrate to the new Common::FS library * yuzu: main: Migrate to the new Common::FS library * vfs_real: Delete the contents of an existing file in CreateFile Current usages of CreateFile expect to delete the contents of an existing file, retain this behavior for now. * input_profiles: Don't iterate the input profile dir if it does not exist Silences an error produced in the log if the directory does not exist. * game_list_worker: Skip parsing file if the returned VfsFile is nullptr Prevents crashes in GetLoader when the virtual file is nullptr * common: fs: Validate paths for path length * service: filesystem: Open the mod load directory as read only
2021-05-26 01:32:56 +02:00
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)
: kernel{system}, fs_controller{system}, hid_core{}, room_network{}, cpu_manager{system},
reporter{system}, applet_manager{system}, frontend_applets{system}, profile_manager{} {}
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-19 04:12:18 +02:00
if (virtual_filesystem == nullptr) {
virtual_filesystem = std::make_shared<FileSys::RealVfsFilesystem>();
2022-10-19 04:12:18 +02:00
}
if (content_provider == nullptr) {
content_provider = std::make_unique<FileSys::ContentProviderUnion>();
2022-10-19 04:12:18 +02: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;
static_service_a->GetStandardUserSystemClock(&user_clock);
std::shared_ptr<Service::PSC::Time::SystemClock> local_clock;
static_service_a->GetStandardLocalSystemClock(&local_clock);
std::shared_ptr<Service::PSC::Time::SystemClock> network_clock;
static_service_s->GetStandardNetworkSystemClock(&network_clock);
std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service;
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()));
timezone_service->SetDeviceLocationName(name);
u64 time_offset = 0;
if (Settings::values.custom_rtc_enabled) {
time_offset = Settings::values.custom_rtc_offset.GetValue();
}
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);
network_clock->GetSystemClockContext(&context);
settings_service->SetNetworkSystemClockContext(context);
network_clock->SetCurrentTime(new_time);
}
2022-12-17 20:34:03 +01:00
void Run() {
2021-10-05 23:54:33 +02:00
std::unique_lock<std::mutex> lk(suspend_guard);
kernel.SuspendEmulation(false);
core_timing.SyncPause(false);
is_paused.store(false, std::memory_order_relaxed);
}
2022-12-17 20:34:03 +01:00
void Pause() {
2021-10-05 23:54:33 +02:00
std::unique_lock<std::mutex> lk(suspend_guard);
core_timing.SyncPause(true);
kernel.SuspendEmulation(true);
is_paused.store(true, std::memory_order_relaxed);
2015-09-02 14:56:38 +02:00
}
2022-07-17 00:48:45 +02:00
bool IsPaused() const {
return is_paused.load(std::memory_order_relaxed);
2022-07-17 00:48:45 +02:00
}
std::unique_lock<std::mutex> StallApplication() {
2021-10-16 00:20:19 +02:00
std::unique_lock<std::mutex> lk(suspend_guard);
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);
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);
kernel.Initialize();
cpu_manager.Initialize();
}
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-31 07:16:35 +01:00
gpu_core = VideoCore::CreateGPU(emu_window, system);
if (!gpu_core) {
return SystemResultStatus::ErrorVideoCore;
2020-10-31 07:16:35 +01:00
}
2022-07-17 00:48:45 +02: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;
microprofile_cpu[0] = MICROPROFILE_TOKEN(ARM_CPU0);
microprofile_cpu[1] = MICROPROFILE_TOKEN(ARM_CPU1);
microprofile_cpu[2] = MICROPROFILE_TOKEN(ARM_CPU2);
microprofile_cpu[3] = MICROPROFILE_TOKEN(ARM_CPU3);
2023-09-10 22:26:09 +02:00
if (Settings::values.enable_renderdoc_hotkey) {
renderdoc_api = std::make_unique<Tools::RenderdocAPI>();
}
LOG_DEBUG(Core, "Initialized OK");
return SystemResultStatus::Success;
}
SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
const std::string& filepath,
Service::AM::FrontendAppletParameters& params) {
2024-03-08 23:44:03 +01: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);
return SystemResultStatus::ErrorGetLoader;
}
if (app_loader->ReadProgramId(params.program_id) != Loader::ResultStatus::Success) {
2024-03-08 23:44:03 +01: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-08 23:44:03 +01:00
LOG_INFO(Core, "Loading {} ({:016X}) ...", name, params.program_id);
2024-03-08 23:44:03 +01: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-08 23:44:03 +01: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);
if (Settings::values.gamecard_inserted) {
if (Settings::values.gamecard_current_game) {
fs_controller.SetGameCard(GetGameFileFromPath(virtual_filesystem, filepath));
} else if (!Settings::values.gamecard_path.GetValue().empty()) {
2022-07-17 00:48:45 +02:00
const auto& gamecard_path = Settings::values.gamecard_path.GetValue();
fs_controller.SetGameCard(GetGameFileFromPath(virtual_filesystem, gamecard_path));
}
}
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 (auto room_member = room_network.GetRoomMember().lock()) {
Network::GameInfo game_info;
game_info.name = name;
game_info.id = params.program_id;
game_info.version = title_version;
room_member->SendGameInfo(game_info);
}
status = SystemResultStatus::Success;
return status;
}
void ShutdownMainProcess() {
2022-07-17 00:48:45 +02:00
SetShuttingDown(true);
is_powered_on = false;
exit_locked = false;
exit_requested = false;
if (gpu_core != nullptr) {
gpu_core->NotifyShutdown();
}
stop_event.request_stop();
2024-02-14 17:39:42 +01:00
core_timing.SyncPause(false);
Network::CancelPendingSocketOperations();
kernel.SuspendEmulation(true);
2022-07-17 00:48:45 +02:00
kernel.CloseServices();
2023-10-22 02:35:18 +02:00
kernel.ShutdownCores();
services.reset();
service_manager.reset();
fs_controller.Reset();
cheat_engine.reset();
core_timing.ClearPendingEvents();
app_loader.reset();
2022-07-17 00:48:45 +02:00
audio_core.reset();
gpu_core.reset();
2022-01-30 10:31:13 +01:00
host1x_core.reset();
perf_stats.reset();
2023-02-16 00:16:04 +01:00
cpu_manager.Shutdown();
debugger.reset();
kernel.Shutdown();
stop_event = {};
Network::RestartSocketOperations();
if (auto room_member = room_network.GetRoomMember().lock()) {
Network::GameInfo game_info{};
room_member->SendGameInfo(game_info);
}
2024-03-08 23:44:03 +01:00
// Reset all glue registrations
arp_manager.ResetAll();
LOG_DEBUG(Core, "Shutdown OK");
}
2022-07-17 00:48:45 +02: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);
}
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-17 00:48:45 +02:00
mutable std::mutex suspend_guard;
std::atomic_bool is_paused{};
2022-07-17 00:48:45 +02: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;
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-17 00:48:45 +02:00
std::unique_ptr<AudioCore::AudioCore> audio_core;
2021-09-21 02:44:34 +02:00
Core::HID::HIDCore hid_core;
Network::RoomNetwork room_network;
CpuManager cpu_manager;
std::atomic_bool is_powered_on{};
bool exit_locked = false;
bool exit_requested = false;
bool nvdec_active{};
Reporter reporter;
std::unique_ptr<Memory::CheatEngine> cheat_engine;
std::unique_ptr<Tools::Freezer> memory_freezer;
std::array<u8, 0x20> build_id{};
2023-09-10 22:26:09 +02:00
std::unique_ptr<Tools::RenderdocAPI> renderdoc_api;
/// Applets
Service::AM::AppletManager applet_manager;
Service::AM::Frontend::FrontendAppletHolder frontend_applets;
2019-06-29 04:46:31 +02:00
/// APM (Performance) services
Service::APM::Controller apm_controller{core_timing};
/// 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;
/// Network instance
Network::NetworkInstance network_instance;
/// Debugger
std::unique_ptr<Core::Debugger> debugger;
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;
ExitCallback exit_callback;
std::stop_source stop_event;
std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_cpu{};
std::array<Core::GPUDirtyMemoryManager, Core::Hardware::NUM_CPU_CORES>
gpu_dirty_memory_managers;
std::deque<std::vector<u8>> user_channel;
};
System::System() : impl{std::make_unique<Impl>(*this)} {}
2021-10-14 20:21:15 +02:00
System::~System() = default;
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 20:34:03 +01:00
void System::Run() {
impl->Run();
}
2022-12-17 20:34:03 +01:00
void System::Pause() {
impl->Pause();
}
2022-07-17 00:48:45 +02:00
bool System::IsPaused() const {
return impl->IsPaused();
}
void System::ShutdownMainProcess() {
impl->ShutdownMainProcess();
}
2022-07-17 00:48:45 +02: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());
}
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 {
return impl->is_powered_on.load(std::memory_order::relaxed);
}
2019-06-19 15:11:18 +02:00
void System::PrepareReschedule(const u32 core_index) {
impl->kernel.PrepareReschedule(core_index);
2019-04-02 15:22:53 +02: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;
}
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();
}
Kernel::PhysicalCore& System::CurrentPhysicalCore() {
return impl->kernel.CurrentPhysicalCore();
}
const Kernel::PhysicalCore& System::CurrentPhysicalCore() const {
return impl->kernel.CurrentPhysicalCore();
}
/// Gets the global scheduler
Kernel::GlobalSchedulerContext& System::GlobalSchedulerContext() {
return impl->kernel.GlobalSchedulerContext();
}
/// Gets the global scheduler
const Kernel::GlobalSchedulerContext& System::GlobalSchedulerContext() const {
return impl->kernel.GlobalSchedulerContext();
}
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();
}
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;
}
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() {
return impl->gpu_core->Renderer();
}
const VideoCore::RendererBase& System::Renderer() const {
return impl->gpu_core->Renderer();
}
Kernel::KernelCore& System::Kernel() {
return impl->kernel;
}
const Kernel::KernelCore& System::Kernel() const {
return impl->kernel;
}
2021-09-21 02:44:34 +02:00
HID::HIDCore& System::HIDCore() {
return impl->hid_core;
}
const HID::HIDCore& System::HIDCore() const {
return impl->hid_core;
}
2022-07-17 00:48:45 +02: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 22:45:13 +01:00
return impl->kernel.ApplicationProcess()->GetProgramId();
}
Loader::ResultStatus System::GetGameName(std::string& out) const {
return impl->GetGameName(out);
}
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;
}
void System::SetFilesystem(FileSys::VirtualFilesystem vfs) {
impl->virtual_filesystem = std::move(vfs);
}
FileSys::VirtualFilesystem System::GetFilesystem() const {
return impl->virtual_filesystem;
}
void System::RegisterCheatList(const std::vector<Memory::CheatEntry>& list,
const std::array<u8, 32>& build_id, u64 main_region_begin,
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;
}
const Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() const {
return impl->frontend_applets;
}
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-22 01:22:14 +02:00
FileSys::ContentProviderUnion& System::GetContentProviderUnion() {
return *impl->content_provider;
}
const FileSys::ContentProviderUnion& System::GetContentProviderUnion() const {
return *impl->content_provider;
}
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-29 04:46:31 +02: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;
}
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;
}
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();
}
void System::EnterCPUProfile() {
std::size_t core = impl->kernel.GetCurrentHostThreadID();
impl->dynarmic_ticks[core] = MicroProfileEnter(impl->microprofile_cpu[core]);
}
void System::ExitCPUProfile() {
std::size_t core = impl->kernel.GetCurrentHostThreadID();
MicroProfileLeave(impl->microprofile_cpu[core], impl->dynarmic_ticks[core]);
}
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;
}
Network::RoomNetwork& System::GetRoomNetwork() {
return impl->room_network;
}
const Network::RoomNetwork& System::GetRoomNetwork() const {
return impl->room_network;
}
2023-09-10 22:26:09 +02:00
Tools::RenderdocAPI& System::GetRenderdocAPI() {
return *impl->renderdoc_api;
}
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");
}
}
std::deque<std::vector<u8>>& System::GetUserChannel() {
return impl->user_channel;
}
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");
}
}
void System::ApplySettings() {
impl->RefreshTime(*this);
if (IsPoweredOn()) {
Renderer().RefreshBaseSettings();
}
}
} // namespace Core