summaryrefslogtreecommitdiffstats
path: root/src/core/core.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/core.cpp')
-rw-r--r--src/core/core.cpp115
1 files changed, 74 insertions, 41 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 54ebed2c1..3c75f42ae 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -139,27 +139,47 @@ struct System::Impl {
: kernel{system}, fs_controller{system}, memory{system},
cpu_manager{system}, reporter{system}, applet_manager{system}, time_manager{system} {}
- ResultStatus Run() {
- status = ResultStatus::Success;
+ SystemResultStatus Run() {
+ std::unique_lock<std::mutex> lk(suspend_guard);
+ status = SystemResultStatus::Success;
kernel.Suspend(false);
core_timing.SyncPause(false);
cpu_manager.Pause(false);
+ is_paused = false;
return status;
}
- ResultStatus Pause() {
- status = ResultStatus::Success;
+ SystemResultStatus Pause() {
+ std::unique_lock<std::mutex> lk(suspend_guard);
+ status = SystemResultStatus::Success;
core_timing.SyncPause(true);
kernel.Suspend(true);
cpu_manager.Pause(true);
+ is_paused = true;
return status;
}
- ResultStatus Init(System& system, Frontend::EmuWindow& emu_window) {
+ std::unique_lock<std::mutex> StallCPU() {
+ std::unique_lock<std::mutex> lk(suspend_guard);
+ kernel.Suspend(true);
+ core_timing.SyncPause(true);
+ cpu_manager.Pause(true);
+ return lk;
+ }
+
+ void UnstallCPU() {
+ if (!is_paused) {
+ core_timing.SyncPause(false);
+ kernel.Suspend(false);
+ cpu_manager.Pause(false);
+ }
+ }
+
+ SystemResultStatus Init(System& system, Frontend::EmuWindow& emu_window) {
LOG_DEBUG(Core, "initialized OK");
device_memory = std::make_unique<Core::DeviceMemory>();
@@ -176,8 +196,9 @@ struct System::Impl {
cpu_manager.Initialize();
core_timing.Initialize([&system]() { system.RegisterHostThread(); });
- const auto current_time = std::chrono::duration_cast<std::chrono::seconds>(
- std::chrono::system_clock::now().time_since_epoch());
+ const auto posix_time = std::chrono::system_clock::now().time_since_epoch();
+ const auto current_time =
+ std::chrono::duration_cast<std::chrono::seconds>(posix_time).count();
Settings::values.custom_rtc_differential =
Settings::values.custom_rtc.value_or(current_time) - current_time;
@@ -197,7 +218,7 @@ struct System::Impl {
gpu_core = VideoCore::CreateGPU(emu_window, system);
if (!gpu_core) {
- return ResultStatus::ErrorVideoCore;
+ return SystemResultStatus::ErrorVideoCore;
}
service_manager = std::make_shared<Service::SM::ServiceManager>(kernel);
@@ -217,21 +238,22 @@ struct System::Impl {
LOG_DEBUG(Core, "Initialized OK");
- return ResultStatus::Success;
+ return SystemResultStatus::Success;
}
- ResultStatus Load(System& system, Frontend::EmuWindow& emu_window, const std::string& filepath,
- u64 program_id, std::size_t program_index) {
+ SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
+ const std::string& filepath, u64 program_id,
+ std::size_t program_index) {
app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath),
program_id, program_index);
if (!app_loader) {
LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
- return ResultStatus::ErrorGetLoader;
+ return SystemResultStatus::ErrorGetLoader;
}
- ResultStatus init_result{Init(system, emu_window)};
- if (init_result != ResultStatus::Success) {
+ SystemResultStatus init_result{Init(system, emu_window)};
+ if (init_result != SystemResultStatus::Success) {
LOG_CRITICAL(Core, "Failed to initialize system (Error {})!",
static_cast<int>(init_result));
Shutdown();
@@ -249,8 +271,8 @@ struct System::Impl {
LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result);
Shutdown();
- return static_cast<ResultStatus>(static_cast<u32>(ResultStatus::ErrorLoader) +
- static_cast<u32>(load_result));
+ return static_cast<SystemResultStatus>(
+ static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result));
}
AddGlueRegistrationForProcess(*app_loader, *main_process);
kernel.MakeCurrentProcess(main_process.get());
@@ -282,7 +304,7 @@ struct System::Impl {
GetAndResetPerfStats();
perf_stats->BeginSystemFrame();
- status = ResultStatus::Success;
+ status = SystemResultStatus::Success;
return status;
}
@@ -305,7 +327,6 @@ struct System::Impl {
is_powered_on = false;
exit_lock = false;
- gpu_core.reset();
services.reset();
service_manager.reset();
cheat_engine.reset();
@@ -315,6 +336,7 @@ struct System::Impl {
core_timing.Shutdown();
app_loader.reset();
perf_stats.reset();
+ gpu_core.reset();
kernel.Shutdown();
memory.Reset();
applet_manager.ClearAll();
@@ -355,7 +377,7 @@ struct System::Impl {
arp_manager.Register(launch.title_id, launch, std::move(nacp_data));
}
- void SetStatus(ResultStatus new_status, const char* details = nullptr) {
+ void SetStatus(SystemResultStatus new_status, const char* details = nullptr) {
status = new_status;
if (details) {
status_details = details;
@@ -366,6 +388,9 @@ struct System::Impl {
return perf_stats->GetAndResetStats(core_timing.GetGlobalTimeUs());
}
+ std::mutex suspend_guard;
+ bool is_paused{};
+
Timing::CoreTiming core_timing;
Kernel::KernelCore kernel;
/// RealVfsFilesystem instance
@@ -411,7 +436,7 @@ struct System::Impl {
/// Network instance
Network::NetworkInstance network_instance;
- ResultStatus status = ResultStatus::Success;
+ SystemResultStatus status = SystemResultStatus::Success;
std::string status_details = "";
std::unique_ptr<Core::PerfStats> perf_stats;
@@ -421,27 +446,15 @@ struct System::Impl {
bool is_async_gpu{};
ExecuteProgramCallback execute_program_callback;
+ ExitCallback exit_callback;
std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_dynarmic{};
};
System::System() : impl{std::make_unique<Impl>(*this)} {}
-System::~System() = default;
-
-System& System::GetInstance() {
- if (!s_instance) {
- throw std::runtime_error("Using System instance before its initialization");
- }
- return *s_instance;
-}
-void System::InitializeGlobalInstance() {
- if (s_instance) {
- throw std::runtime_error("Reinitializing Global System instance.");
- }
- s_instance = std::unique_ptr<System>(new System);
-}
+System::~System() = default;
CpuManager& System::GetCpuManager() {
return impl->cpu_manager;
@@ -451,16 +464,16 @@ const CpuManager& System::GetCpuManager() const {
return impl->cpu_manager;
}
-System::ResultStatus System::Run() {
+SystemResultStatus System::Run() {
return impl->Run();
}
-System::ResultStatus System::Pause() {
+SystemResultStatus System::Pause() {
return impl->Pause();
}
-System::ResultStatus System::SingleStep() {
- return ResultStatus::Success;
+SystemResultStatus System::SingleStep() {
+ return SystemResultStatus::Success;
}
void System::InvalidateCpuInstructionCaches() {
@@ -475,8 +488,16 @@ void System::Shutdown() {
impl->Shutdown();
}
-System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath,
- u64 program_id, std::size_t program_index) {
+std::unique_lock<std::mutex> System::StallCPU() {
+ return impl->StallCPU();
+}
+
+void System::UnstallCPU() {
+ impl->UnstallCPU();
+}
+
+SystemResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath,
+ u64 program_id, std::size_t program_index) {
return impl->Load(*this, emu_window, filepath, program_id, program_index);
}
@@ -636,7 +657,7 @@ Loader::ResultStatus System::GetGameName(std::string& out) const {
return impl->GetGameName(out);
}
-void System::SetStatus(ResultStatus new_status, const char* details) {
+void System::SetStatus(SystemResultStatus new_status, const char* details) {
impl->SetStatus(new_status, details);
}
@@ -798,6 +819,18 @@ void System::ExecuteProgram(std::size_t program_index) {
}
}
+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() {
if (IsPoweredOn()) {
Renderer().RefreshBaseSettings();