diff options
Diffstat (limited to '')
-rw-r--r-- | src/citra/citra.cpp | 3 | ||||
-rw-r--r-- | src/citra_qt/bootmanager.cpp | 6 | ||||
-rw-r--r-- | src/citra_qt/configure_general.cpp | 2 | ||||
-rw-r--r-- | src/citra_qt/configure_graphics.cpp | 2 | ||||
-rw-r--r-- | src/citra_qt/configure_system.cpp | 1 | ||||
-rw-r--r-- | src/citra_qt/debugger/callstack.cpp | 2 | ||||
-rw-r--r-- | src/citra_qt/debugger/disassembler.cpp | 10 | ||||
-rw-r--r-- | src/citra_qt/debugger/registers.cpp | 16 | ||||
-rw-r--r-- | src/citra_qt/debugger/wait_tree.cpp | 2 | ||||
-rw-r--r-- | src/citra_qt/main.cpp | 1 | ||||
-rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/core/core.cpp | 112 | ||||
-rw-r--r-- | src/core/core.h | 132 | ||||
-rw-r--r-- | src/core/core_timing.cpp | 27 | ||||
-rw-r--r-- | src/core/gdbstub/gdbstub.cpp | 39 | ||||
-rw-r--r-- | src/core/hle/function_wrappers.h | 60 | ||||
-rw-r--r-- | src/core/hle/hle.cpp | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.cpp | 6 | ||||
-rw-r--r-- | src/core/hle/service/ldr_ro/ldr_ro.cpp | 8 | ||||
-rw-r--r-- | src/core/hle/svc.cpp | 12 | ||||
-rw-r--r-- | src/core/system.cpp | 90 | ||||
-rw-r--r-- | src/core/system.h | 83 |
22 files changed, 284 insertions, 336 deletions
diff --git a/src/citra/citra.cpp b/src/citra/citra.cpp index 5e2829b54..febfc5dc8 100644 --- a/src/citra/citra.cpp +++ b/src/citra/citra.cpp @@ -33,7 +33,6 @@ #include "core/gdbstub/gdbstub.h" #include "core/loader/loader.h" #include "core/settings.h" -#include "core/system.h" #include "video_core/video_core.h" static void PrintHelp(const char* argv0) { @@ -145,7 +144,7 @@ int main(int argc, char** argv) { } while (emu_window->IsOpen()) { - Core::RunLoop(); + system.RunLoop(); } return 0; diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp index 5e8ae3066..bb75633b6 100644 --- a/src/citra_qt/bootmanager.cpp +++ b/src/citra_qt/bootmanager.cpp @@ -14,8 +14,6 @@ #include "common/scm_rev.h" #include "common/string_util.h" #include "core/core.h" -#include "core/settings.h" -#include "core/system.h" #include "video_core/debug_utils/debug_utils.h" #include "video_core/video_core.h" @@ -38,7 +36,7 @@ void EmuThread::run() { if (!was_active) emit DebugModeLeft(); - Core::RunLoop(); + Core::System::GetInstance().RunLoop(); was_active = running || exec_step; if (!was_active && !stop_run) @@ -48,7 +46,7 @@ void EmuThread::run() { emit DebugModeLeft(); exec_step = false; - Core::SingleStep(); + Core::System::GetInstance().SingleStep(); emit DebugModeEntered(); yieldCurrentThread(); diff --git a/src/citra_qt/configure_general.cpp b/src/citra_qt/configure_general.cpp index f576f6f7a..03cd8835b 100644 --- a/src/citra_qt/configure_general.cpp +++ b/src/citra_qt/configure_general.cpp @@ -4,8 +4,8 @@ #include "citra_qt/configure_general.h" #include "citra_qt/ui_settings.h" +#include "core/core.h" #include "core/settings.h" -#include "core/system.h" #include "ui_configure_general.h" ConfigureGeneral::ConfigureGeneral(QWidget* parent) diff --git a/src/citra_qt/configure_graphics.cpp b/src/citra_qt/configure_graphics.cpp index 1e6f7f880..cea7db388 100644 --- a/src/citra_qt/configure_graphics.cpp +++ b/src/citra_qt/configure_graphics.cpp @@ -3,8 +3,8 @@ // Refer to the license.txt file included. #include "citra_qt/configure_graphics.h" +#include "core/core.h" #include "core/settings.h" -#include "core/system.h" #include "ui_configure_graphics.h" ConfigureGraphics::ConfigureGraphics(QWidget* parent) diff --git a/src/citra_qt/configure_system.cpp b/src/citra_qt/configure_system.cpp index 545261c01..eb1276ef3 100644 --- a/src/citra_qt/configure_system.cpp +++ b/src/citra_qt/configure_system.cpp @@ -6,7 +6,6 @@ #include "citra_qt/ui_settings.h" #include "core/hle/service/cfg/cfg.h" #include "core/hle/service/fs/archive.h" -#include "core/system.h" #include "ui_configure_system.h" static const std::array<int, 12> days_in_month = {{ diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp index c66f2b96a..5e176be48 100644 --- a/src/citra_qt/debugger/callstack.cpp +++ b/src/citra_qt/debugger/callstack.cpp @@ -25,7 +25,7 @@ CallstackWidget::CallstackWidget(QWidget* parent) : QDockWidget(parent) { void CallstackWidget::OnDebugModeEntered() { // Stack pointer - const u32 sp = Core::g_app_core->GetReg(13); + const u32 sp = Core::AppCore().GetReg(13); Clear(); diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp index 1ee6bbd6a..712e35f7f 100644 --- a/src/citra_qt/debugger/disassembler.cpp +++ b/src/citra_qt/debugger/disassembler.cpp @@ -185,13 +185,13 @@ DisassemblerWidget::DisassemblerWidget(QWidget* parent, EmuThread* emu_thread) } void DisassemblerWidget::Init() { - model->ParseFromAddress(Core::g_app_core->GetPC()); + model->ParseFromAddress(Core::AppCore().GetPC()); disasm_ui.treeView->resizeColumnToContents(0); disasm_ui.treeView->resizeColumnToContents(1); disasm_ui.treeView->resizeColumnToContents(2); - QModelIndex model_index = model->IndexFromAbsoluteAddress(Core::g_app_core->GetPC()); + QModelIndex model_index = model->IndexFromAbsoluteAddress(Core::AppCore().GetPC()); disasm_ui.treeView->scrollTo(model_index); disasm_ui.treeView->selectionModel()->setCurrentIndex( model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); @@ -214,8 +214,8 @@ void DisassemblerWidget::OnPause() { emu_thread->SetRunning(false); // TODO: By now, the CPU might not have actually stopped... - if (Core::g_app_core) { - model->SetNextInstruction(Core::g_app_core->GetPC()); + if (Core::System::GetInstance().IsPoweredOn()) { + model->SetNextInstruction(Core::AppCore().GetPC()); } } @@ -224,7 +224,7 @@ void DisassemblerWidget::OnToggleStartStop() { } void DisassemblerWidget::OnDebugModeEntered() { - u32 next_instr = Core::g_app_core->GetPC(); + u32 next_instr = Core::AppCore().GetPC(); if (model->GetBreakPoints().IsAddressBreakPoint(next_instr)) emu_thread->SetRunning(false); diff --git a/src/citra_qt/debugger/registers.cpp b/src/citra_qt/debugger/registers.cpp index 4c529d3c3..d5b6542bd 100644 --- a/src/citra_qt/debugger/registers.cpp +++ b/src/citra_qt/debugger/registers.cpp @@ -58,16 +58,16 @@ RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent) { } void RegistersWidget::OnDebugModeEntered() { - if (!Core::g_app_core) + if (!Core::System::GetInstance().IsPoweredOn()) return; for (int i = 0; i < core_registers->childCount(); ++i) core_registers->child(i)->setText( - 1, QString("0x%1").arg(Core::g_app_core->GetReg(i), 8, 16, QLatin1Char('0'))); + 1, QString("0x%1").arg(Core::AppCore().GetReg(i), 8, 16, QLatin1Char('0'))); for (int i = 0; i < vfp_registers->childCount(); ++i) vfp_registers->child(i)->setText( - 1, QString("0x%1").arg(Core::g_app_core->GetVFPReg(i), 8, 16, QLatin1Char('0'))); + 1, QString("0x%1").arg(Core::AppCore().GetVFPReg(i), 8, 16, QLatin1Char('0'))); UpdateCPSRValues(); UpdateVFPSystemRegisterValues(); @@ -127,7 +127,7 @@ void RegistersWidget::CreateCPSRChildren() { } void RegistersWidget::UpdateCPSRValues() { - const u32 cpsr_val = Core::g_app_core->GetCPSR(); + const u32 cpsr_val = Core::AppCore().GetCPSR(); cpsr->setText(1, QString("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0'))); cpsr->child(0)->setText( @@ -191,10 +191,10 @@ void RegistersWidget::CreateVFPSystemRegisterChildren() { } void RegistersWidget::UpdateVFPSystemRegisterValues() { - const u32 fpscr_val = Core::g_app_core->GetVFPSystemReg(VFP_FPSCR); - const u32 fpexc_val = Core::g_app_core->GetVFPSystemReg(VFP_FPEXC); - const u32 fpinst_val = Core::g_app_core->GetVFPSystemReg(VFP_FPINST); - const u32 fpinst2_val = Core::g_app_core->GetVFPSystemReg(VFP_FPINST2); + const u32 fpscr_val = Core::AppCore().GetVFPSystemReg(VFP_FPSCR); + const u32 fpexc_val = Core::AppCore().GetVFPSystemReg(VFP_FPEXC); + const u32 fpinst_val = Core::AppCore().GetVFPSystemReg(VFP_FPINST); + const u32 fpinst2_val = Core::AppCore().GetVFPSystemReg(VFP_FPINST2); QTreeWidgetItem* const fpscr = vfp_system_registers->child(0); fpscr->setText(1, QString("0x%1").arg(fpscr_val, 8, 16, QLatin1Char('0'))); diff --git a/src/citra_qt/debugger/wait_tree.cpp b/src/citra_qt/debugger/wait_tree.cpp index 5a308bf7f..1d2de5185 100644 --- a/src/citra_qt/debugger/wait_tree.cpp +++ b/src/citra_qt/debugger/wait_tree.cpp @@ -391,7 +391,7 @@ WaitTreeWidget::WaitTreeWidget(QWidget* parent) : QDockWidget(tr("Wait Tree"), p } void WaitTreeWidget::OnDebugModeEntered() { - if (!Core::g_app_core) + if (!Core::System::GetInstance().IsPoweredOn()) return; model->InitItems(); view->setModel(model); diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 0c7723b0a..e27c09b53 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -46,7 +46,6 @@ #include "core/gdbstub/gdbstub.h" #include "core/loader/loader.h" #include "core/settings.h" -#include "core/system.h" #include "qhexedit.h" #include "video_core/video_core.h" diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index af224166a..d547b0746 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -155,7 +155,6 @@ set(SRCS tracer/recorder.cpp memory.cpp settings.cpp - system.cpp ) set(HEADERS @@ -325,7 +324,6 @@ set(HEADERS memory_setup.h mmio.h settings.h - system.h ) include_directories(../../externals/dynarmic/include) diff --git a/src/core/core.cpp b/src/core/core.cpp index 6efa18159..b4df90efd 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -3,6 +3,8 @@ // Refer to the license.txt file included. #include <memory> + +#include "audio_core/audio_core.h" #include "common/logging/log.h" #include "core/arm/arm_interface.h" #include "core/arm/dynarmic/arm_dynarmic.h" @@ -11,17 +13,23 @@ #include "core/core_timing.h" #include "core/gdbstub/gdbstub.h" #include "core/hle/hle.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/memory.h" #include "core/hle/kernel/thread.h" #include "core/hw/hw.h" +#include "core/loader/loader.h" #include "core/settings.h" +#include "video_core/video_core.h" namespace Core { -std::unique_ptr<ARM_Interface> g_app_core; ///< ARM11 application core -std::unique_ptr<ARM_Interface> g_sys_core; ///< ARM11 system (OS) core +/*static*/ System System::s_instance; + +System::ResultStatus System::RunLoop(int tight_loop) { + if (!app_core) { + return ResultStatus::ErrorNotInitialized; + } -/// Run the core CPU loop -void RunLoop(int tight_loop) { if (GDBStub::IsServerEnabled()) { GDBStub::HandlePacket(); @@ -32,7 +40,7 @@ void RunLoop(int tight_loop) { GDBStub::SetCpuStepFlag(false); tight_loop = 1; } else { - return; + return ResultStatus::Success; } } } @@ -45,46 +53,100 @@ void RunLoop(int tight_loop) { CoreTiming::Advance(); HLE::Reschedule(__func__); } else { - g_app_core->Run(tight_loop); + app_core->Run(tight_loop); } HW::Update(); if (HLE::IsReschedulePending()) { Kernel::Reschedule(); } -} -/// Step the CPU one instruction -void SingleStep() { - RunLoop(1); + return ResultStatus::Success; } -/// Halt the core -void Halt(const char* msg) { - // TODO(ShizZy): ImplementMe +System::ResultStatus System::SingleStep() { + return RunLoop(1); } -/// Kill the core -void Stop() { - // TODO(ShizZy): ImplementMe +System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& filepath) { + if (app_loader) { + app_loader.reset(); + } + + app_loader = Loader::GetLoader(filepath); + + if (!app_loader) { + LOG_CRITICAL(Core, "Failed to obtain loader for %s!", filepath.c_str()); + return ResultStatus::ErrorGetLoader; + } + + boost::optional<u32> system_mode{ app_loader->LoadKernelSystemMode() }; + if (!system_mode) { + LOG_CRITICAL(Core, "Failed to determine system mode!"); + return ResultStatus::ErrorSystemMode; + } + + ResultStatus init_result{ Init(emu_window, system_mode.get()) }; + if (init_result != ResultStatus::Success) { + LOG_CRITICAL(Core, "Failed to initialize system (Error %i)!", init_result); + System::Shutdown(); + return init_result; + } + + const Loader::ResultStatus load_result{ app_loader->Load() }; + if (Loader::ResultStatus::Success != load_result) { + LOG_CRITICAL(Core, "Failed to load ROM (Error %i)!", load_result); + System::Shutdown(); + + switch (load_result) { + case Loader::ResultStatus::ErrorEncrypted: + return ResultStatus::ErrorLoader_ErrorEncrypted; + case Loader::ResultStatus::ErrorInvalidFormat: + return ResultStatus::ErrorLoader_ErrorInvalidFormat; + default: + return ResultStatus::ErrorLoader; + } + } + return ResultStatus::Success; } -/// Initialize the core -void Init() { +System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { + if (app_core) { + app_core.reset(); + } + + Memory::Init(); + if (Settings::values.use_cpu_jit) { - g_sys_core = std::make_unique<ARM_Dynarmic>(USER32MODE); - g_app_core = std::make_unique<ARM_Dynarmic>(USER32MODE); + app_core = std::make_unique<ARM_Dynarmic>(USER32MODE); } else { - g_sys_core = std::make_unique<ARM_DynCom>(USER32MODE); - g_app_core = std::make_unique<ARM_DynCom>(USER32MODE); + app_core = std::make_unique<ARM_DynCom>(USER32MODE); + } + + CoreTiming::Init(); + HW::Init(); + Kernel::Init(system_mode); + HLE::Init(); + AudioCore::Init(); + GDBStub::Init(); + + if (!VideoCore::Init(emu_window)) { + return ResultStatus::ErrorVideoCore; } LOG_DEBUG(Core, "Initialized OK"); + + return ResultStatus::Success; } -void Shutdown() { - g_app_core.reset(); - g_sys_core.reset(); +void System::Shutdown() { + GDBStub::Shutdown(); + AudioCore::Shutdown(); + VideoCore::Shutdown(); + HLE::Shutdown(); + Kernel::Shutdown(); + HW::Shutdown(); + CoreTiming::Shutdown(); LOG_DEBUG(Core, "Shutdown OK"); } diff --git a/src/core/core.h b/src/core/core.h index ffbfa91c3..f4326161d 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -5,11 +5,17 @@ #pragma once #include <memory> +#include <string> + #include "common/common_types.h" +#include "core/memory.h" +class EmuWindow; class ARM_Interface; -//////////////////////////////////////////////////////////////////////////////////////////////////// +namespace Loader { +class AppLoader; +} namespace Core { @@ -24,37 +30,97 @@ struct ThreadContext { u32 fpexc; }; -extern std::unique_ptr<ARM_Interface> g_app_core; ///< ARM11 application core -extern std::unique_ptr<ARM_Interface> g_sys_core; ///< ARM11 system (OS) core - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/// Start the core -void Start(); - -/** - * Run the core CPU loop - * This function runs the core for the specified number of CPU instructions before trying to update - * hardware. This is much faster than SingleStep (and should be equivalent), as the CPU is not - * required to do a full dispatch with each instruction. NOTE: the number of instructions requested - * is not guaranteed to run, as this will be interrupted preemptively if a hardware update is - * requested (e.g. on a thread switch). - */ -void RunLoop(int tight_loop = 1000); - -/// Step the CPU one instruction -void SingleStep(); - -/// Halt the core -void Halt(const char* msg); - -/// Kill the core -void Stop(); - -/// Initialize the core -void Init(); +class System { +public: + /** + * Gets the instance of the System singleton class. + * @returns Reference to the instance of the System singleton class. + */ + static System& GetInstance() { + return s_instance; + } + + /// Enumeration representing the return values of the System Initialize and Load process. + enum class ResultStatus : u32 { + Success, ///< Succeeded + ErrorNotInitialized, ///< Error trying to use core prior to initialization + ErrorGetLoader, ///< Error finding the correct application loader + ErrorSystemMode, ///< Error determining the system mode + ErrorLoader, ///< Error loading the specified application + ErrorLoader_ErrorEncrypted, ///< Error loading the specified application due to encryption + ErrorLoader_ErrorInvalidFormat, ///< Error loading the specified application due to an invalid format + ErrorVideoCore, ///< Error in the video core + }; + + /** + * Initialize the emulated system. + * @param emu_window Pointer to the host-system window used for video output and keyboard input. + * @param system_mode The system mode. + * @return ResultStatus code, indicating if the operation succeeded. + */ + ResultStatus Init(EmuWindow* emu_window, u32 system_mode); + + /// Start the core + void Start(); + + /** + * Run the core CPU loop + * This function runs the core for the specified number of CPU instructions before trying to update + * hardware. This is much faster than SingleStep (and should be equivalent), as the CPU is not + * required to do a full dispatch with each instruction. NOTE: the number of instructions requested + * is not guaranteed to run, as this will be interrupted preemptively if a hardware update is + * requested (e.g. on a thread switch). + * @param tight_loop Number of instructions to execute. + * @return Result status, indicating whethor or not the operation succeeded. + */ + ResultStatus RunLoop(int tight_loop = 1000); + + /** + * Step the CPU one instruction + * @return Result status, indicating whethor or not the operation succeeded. + */ + ResultStatus SingleStep(); + + /// Shutdown the emulated system. + void Shutdown(); + + /** + * Load an executable application. + * @param emu_window Pointer to the host-system window used for video output and keyboard input. + * @param filepath String path to the executable application to load on the host file system. + * @returns ResultStatus code, indicating if the operation succeeded. + */ + ResultStatus Load(EmuWindow* emu_window, const std::string& filepath); + + /** + * Indicates if the emulated system is powered on (all subsystems initialized and able to run an + * application). + * @returns True if the emulated system is powered on, otherwise false. + */ + bool IsPoweredOn() const { + return app_core != nullptr; + } + + /** + * Gets a reference to the emulated AppCore CPU. + * @returns A reference to the emulated AppCore CPU. + */ + ARM_Interface& AppCore() { + return *app_core; + } + +private: + /// AppLoader used to load the current executing application + std::unique_ptr<Loader::AppLoader> app_loader; + + ///< ARM11 application core + std::unique_ptr<ARM_Interface> app_core; + + static System s_instance; +}; -/// Shutdown the core -void Shutdown(); +static ARM_Interface& AppCore() { + return System::GetInstance().AppCore(); +} -} // namespace +} // namespace Core diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 5220b55ea..9fe374795 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp @@ -130,7 +130,6 @@ int RegisterEvent(const char* name, TimedCallback callback) { static void AntiCrashCallback(u64 userdata, int cycles_late) { LOG_CRITICAL(Core_Timing, "Savestate broken: an unregistered event was called."); - Core::Halt("invalid timing events"); } void RestoreRegisterEvent(int event_type, const char* name, TimedCallback callback) { @@ -147,7 +146,7 @@ void UnregisterAllEvents() { } void Init() { - Core::g_app_core->down_count = INITIAL_SLICE_LENGTH; + Core::AppCore().down_count = INITIAL_SLICE_LENGTH; g_slice_length = INITIAL_SLICE_LENGTH; global_timer = 0; idled_cycles = 0; @@ -187,7 +186,7 @@ void Shutdown() { } u64 GetTicks() { - return (u64)global_timer + g_slice_length - Core::g_app_core->down_count; + return (u64)global_timer + g_slice_length - Core::AppCore().down_count; } u64 GetIdleTicks() { @@ -461,18 +460,18 @@ void MoveEvents() { } void ForceCheck() { - s64 cycles_executed = g_slice_length - Core::g_app_core->down_count; + s64 cycles_executed = g_slice_length - Core::AppCore().down_count; global_timer += cycles_executed; // This will cause us to check for new events immediately. - Core::g_app_core->down_count = 0; + Core::AppCore().down_count = 0; // But let's not eat a bunch more time in Advance() because of this. g_slice_length = 0; } void Advance() { - s64 cycles_executed = g_slice_length - Core::g_app_core->down_count; + s64 cycles_executed = g_slice_length - Core::AppCore().down_count; global_timer += cycles_executed; - Core::g_app_core->down_count = g_slice_length; + Core::AppCore().down_count = g_slice_length; if (has_ts_events) MoveEvents(); @@ -481,7 +480,7 @@ void Advance() { if (!first) { if (g_slice_length < 10000) { g_slice_length += 10000; - Core::g_app_core->down_count += g_slice_length; + Core::AppCore().down_count += g_slice_length; } } else { // Note that events can eat cycles as well. @@ -491,7 +490,7 @@ void Advance() { const int diff = target - g_slice_length; g_slice_length += diff; - Core::g_app_core->down_count += diff; + Core::AppCore().down_count += diff; } if (advance_callback) advance_callback(static_cast<int>(cycles_executed)); @@ -507,12 +506,12 @@ void LogPendingEvents() { } void Idle(int max_idle) { - s64 cycles_down = Core::g_app_core->down_count; + s64 cycles_down = Core::AppCore().down_count; if (max_idle != 0 && cycles_down > max_idle) cycles_down = max_idle; if (first && cycles_down > 0) { - s64 cycles_executed = g_slice_length - Core::g_app_core->down_count; + s64 cycles_executed = g_slice_length - Core::AppCore().down_count; s64 cycles_next_event = first->time - global_timer; if (cycles_next_event < cycles_executed + cycles_down) { @@ -527,9 +526,9 @@ void Idle(int max_idle) { cycles_down / (float)(g_clock_rate_arm11 * 0.001f)); idled_cycles += cycles_down; - Core::g_app_core->down_count -= cycles_down; - if (Core::g_app_core->down_count == 0) - Core::g_app_core->down_count = -1; + Core::AppCore().down_count -= cycles_down; + if (Core::AppCore().down_count == 0) + Core::AppCore().down_count = -1; } std::string GetScheduledEventsSummary() { diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index f96cbde64..9acdd402b 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp @@ -30,6 +30,7 @@ #include <unistd.h> #endif +#include "core/loader/loader.h" #include "common/logging/log.h" #include "common/string_util.h" #include "core/arm/arm_interface.h" @@ -450,8 +451,8 @@ static void SendSignal(u32 signal) { latest_signal = signal; std::string buffer = Common::StringFromFormat("T%02x%02x:%08x;%02x:%08x;", latest_signal, 15, - htonl(Core::g_app_core->GetPC()), 13, - htonl(Core::g_app_core->GetReg(13))); + htonl(Core::AppCore().GetPC()), 13, + htonl(Core::AppCore().GetReg(13))); LOG_DEBUG(Debug_GDBStub, "Response: %s", buffer.c_str()); SendReply(buffer.c_str()); } @@ -538,15 +539,15 @@ static void ReadRegister() { } if (id <= R15_REGISTER) { - IntToGdbHex(reply, Core::g_app_core->GetReg(id)); + IntToGdbHex(reply, Core::AppCore().GetReg(id)); } else if (id == CPSR_REGISTER) { - IntToGdbHex(reply, Core::g_app_core->GetCPSR()); + IntToGdbHex(reply, Core::AppCore().GetCPSR()); } else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) { - IntToGdbHex(reply, Core::g_app_core->GetVFPReg( + IntToGdbHex(reply, Core::AppCore().GetVFPReg( id - CPSR_REGISTER - 1)); // VFP registers should start at 26, so one after CSPR_REGISTER } else if (id == FPSCR_REGISTER) { - IntToGdbHex(reply, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR)); // Get FPSCR + IntToGdbHex(reply, Core::AppCore().GetVFPSystemReg(VFP_FPSCR)); // Get FPSCR IntToGdbHex(reply + 8, 0); } else { return SendReply("E01"); @@ -563,22 +564,22 @@ static void ReadRegisters() { u8* bufptr = buffer; for (int reg = 0; reg <= R15_REGISTER; reg++) { - IntToGdbHex(bufptr + reg * CHAR_BIT, Core::g_app_core->GetReg(reg)); + IntToGdbHex(bufptr + reg * CHAR_BIT, Core::AppCore().GetReg(reg)); } bufptr += (16 * CHAR_BIT); - IntToGdbHex(bufptr, Core::g_app_core->GetCPSR()); + IntToGdbHex(bufptr, Core::AppCore().GetCPSR()); bufptr += CHAR_BIT; for (int reg = 0; reg <= 31; reg++) { - IntToGdbHex(bufptr + reg * CHAR_BIT, Core::g_app_core->GetVFPReg(reg)); + IntToGdbHex(bufptr + reg * CHAR_BIT, Core::AppCore().GetVFPReg(reg)); } bufptr += (32 * CHAR_BIT); - IntToGdbHex(bufptr, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR)); + IntToGdbHex(bufptr, Core::AppCore().GetVFPSystemReg(VFP_FPSCR)); SendReply(reinterpret_cast<char*>(buffer)); } @@ -595,13 +596,13 @@ static void WriteRegister() { } if (id <= R15_REGISTER) { - Core::g_app_core->SetReg(id, GdbHexToInt(buffer_ptr)); + Core::AppCore().SetReg(id, GdbHexToInt(buffer_ptr)); } else if (id == CPSR_REGISTER) { - Core::g_app_core->SetCPSR(GdbHexToInt(buffer_ptr)); + Core::AppCore().SetCPSR(GdbHexToInt(buffer_ptr)); } else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) { - Core::g_app_core->SetVFPReg(id - CPSR_REGISTER - 1, GdbHexToInt(buffer_ptr)); + Core::AppCore().SetVFPReg(id - CPSR_REGISTER - 1, GdbHexToInt(buffer_ptr)); } else if (id == FPSCR_REGISTER) { - Core::g_app_core->SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr)); + Core::AppCore().SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr)); } else { return SendReply("E01"); } @@ -618,20 +619,20 @@ static void WriteRegisters() { for (int i = 0, reg = 0; reg <= FPSCR_REGISTER; i++, reg++) { if (reg <= R15_REGISTER) { - Core::g_app_core->SetReg(reg, GdbHexToInt(buffer_ptr + i * CHAR_BIT)); + Core::AppCore().SetReg(reg, GdbHexToInt(buffer_ptr + i * CHAR_BIT)); } else if (reg == CPSR_REGISTER) { - Core::g_app_core->SetCPSR(GdbHexToInt(buffer_ptr + i * CHAR_BIT)); + Core::AppCore().SetCPSR(GdbHexToInt(buffer_ptr + i * CHAR_BIT)); } else if (reg == CPSR_REGISTER - 1) { // Dummy FPA register, ignore } else if (reg < CPSR_REGISTER) { // Dummy FPA registers, ignore i += 2; } else if (reg > CPSR_REGISTER && reg < FPSCR_REGISTER) { - Core::g_app_core->SetVFPReg(reg - CPSR_REGISTER - 1, + Core::AppCore().SetVFPReg(reg - CPSR_REGISTER - 1, GdbHexToInt(buffer_ptr + i * CHAR_BIT)); i++; // Skip padding } else if (reg == FPSCR_REGISTER) { - Core::g_app_core->SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr + i * CHAR_BIT)); + Core::AppCore().SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr + i * CHAR_BIT)); } } @@ -908,7 +909,7 @@ void ToggleServer(bool status) { server_enabled = status; // Start server - if (!IsConnected() && Core::g_sys_core != nullptr) { + if (!IsConnected() && Core::System().GetInstance().IsPoweredOn()) { Init(); } } else { diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 8ce0f6d2b..0f2a04e30 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -14,7 +14,7 @@ namespace HLE { -#define PARAM(n) Core::g_app_core->GetReg(n) +#define PARAM(n) Core::AppCore().GetReg(n) /// An invalid result code that is meant to be overwritten when a thread resumes from waiting static const ResultCode RESULT_INVALID(0xDEADC0DE); @@ -24,7 +24,7 @@ static const ResultCode RESULT_INVALID(0xDEADC0DE); * @param res Result to return */ static inline void FuncReturn(u32 res) { - Core::g_app_core->SetReg(0, res); + Core::AppCore().SetReg(0, res); } /** @@ -33,8 +33,8 @@ static inline void FuncReturn(u32 res) { * @todo Verify that this function is correct */ static inline void FuncReturn64(u64 res) { - Core::g_app_core->SetReg(0, (u32)(res & 0xFFFFFFFF)); - Core::g_app_core->SetReg(1, (u32)((res >> 32) & 0xFFFFFFFF)); + Core::AppCore().SetReg(0, (u32)(res & 0xFFFFFFFF)); + Core::AppCore().SetReg(1, (u32)((res >> 32) & 0xFFFFFFFF)); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -49,7 +49,7 @@ template <ResultCode func(u32*, u32, u32, u32, u32, u32)> void Wrap() { u32 param_1 = 0; u32 retval = func(¶m_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; - Core::g_app_core->SetReg(1, param_1); + Core::AppCore().SetReg(1, param_1); FuncReturn(retval); } @@ -57,7 +57,7 @@ template <ResultCode func(u32*, s32, u32, u32, u32, s32)> void Wrap() { u32 param_1 = 0; u32 retval = func(¶m_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; - Core::g_app_core->SetReg(1, param_1); + Core::AppCore().SetReg(1, param_1); FuncReturn(retval); } @@ -69,7 +69,7 @@ void Wrap() { .raw; if (retval != RESULT_INVALID.raw) { - Core::g_app_core->SetReg(1, (u32)param_1); + Core::AppCore().SetReg(1, (u32)param_1); FuncReturn(retval); } } @@ -84,7 +84,7 @@ template <ResultCode func(u32*)> void Wrap() { u32 param_1 = 0; u32 retval = func(¶m_1).raw; - Core::g_app_core->SetReg(1, param_1); + Core::AppCore().SetReg(1, param_1); FuncReturn(retval); } @@ -102,11 +102,11 @@ void Wrap() { MemoryInfo memory_info = {}; PageInfo page_info = {}; u32 retval = func(&memory_info, &page_info, PARAM(2)).raw; - Core::g_app_core->SetReg(1, memory_info.base_address); - Core::g_app_core->SetReg(2, memory_info.size); - Core::g_app_core->SetReg(3, memory_info.permission); - Core::g_app_core->SetReg(4, memory_info.state); - Core::g_app_core->SetReg(5, page_info.flags); + Core::AppCore().SetReg(1, memory_info.base_address); + Core::AppCore().SetReg(2, memory_info.size); + Core::AppCore().SetReg(3, memory_info.permission); + Core::AppCore().SetReg(4, memory_info.state); + Core::AppCore().SetReg(5, page_info.flags); FuncReturn(retval); } @@ -115,11 +115,11 @@ void Wrap() { MemoryInfo memory_info = {}; PageInfo page_info = {}; u32 retval = func(&memory_info, &page_info, PARAM(2), PARAM(3)).raw; - Core::g_app_core->SetReg(1, memory_info.base_address); - Core::g_app_core->SetReg(2, memory_info.size); - Core::g_app_core->SetReg(3, memory_info.permission); - Core::g_app_core->SetReg(4, memory_info.state); - Core::g_app_core->SetReg(5, page_info.flags); + Core::AppCore().SetReg(1, memory_info.base_address); + Core::AppCore().SetReg(2, memory_info.size); + Core::AppCore().SetReg(3, memory_info.permission); + Core::AppCore().SetReg(4, memory_info.state); + Core::AppCore().SetReg(5, page_info.flags); FuncReturn(retval); } @@ -127,7 +127,7 @@ template <ResultCode func(s32*, u32)> void Wrap() { s32 param_1 = 0; u32 retval = func(¶m_1, PARAM(1)).raw; - Core::g_app_core->SetReg(1, param_1); + Core::AppCore().SetReg(1, param_1); FuncReturn(retval); } @@ -140,7 +140,7 @@ template <ResultCode func(u32*, u32)> void Wrap() { u32 param_1 = 0; u32 retval = func(¶m_1, PARAM(1)).raw; - Core::g_app_core->SetReg(1, param_1); + Core::AppCore().SetReg(1, param_1); FuncReturn(retval); } @@ -160,7 +160,7 @@ template <ResultCode func(u32*, const char*)> void Wrap() { u32 param_1 = 0; u32 retval = func(¶m_1, (char*)Memory::GetPointer(PARAM(1))).raw; - Core::g_app_core->SetReg(1, param_1); + Core::AppCore().SetReg(1, param_1); FuncReturn(retval); } @@ -168,7 +168,7 @@ template <ResultCode func(u32*, s32, s32)> void Wrap() { u32 param_1 = 0; u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw; - Core::g_app_core->SetReg(1, param_1); + Core::AppCore().SetReg(1, param_1); FuncReturn(retval); } @@ -176,7 +176,7 @@ template <ResultCode func(s32*, u32, s32)> void Wrap() { s32 param_1 = 0; u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw; - Core::g_app_core->SetReg(1, param_1); + Core::AppCore().SetReg(1, param_1); FuncReturn(retval); } @@ -184,8 +184,8 @@ template <ResultCode func(s64*, u32, s32)> void Wrap() { s64 param_1 = 0; u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw; - Core::g_app_core->SetReg(1, (u32)param_1); - Core::g_app_core->SetReg(2, (u32)(param_1 >> 32)); + Core::AppCore().SetReg(1, (u32)param_1); + Core::AppCore().SetReg(2, (u32)(param_1 >> 32)); FuncReturn(retval); } @@ -194,7 +194,7 @@ void Wrap() { u32 param_1 = 0; // The last parameter is passed in R0 instead of R4 u32 retval = func(¶m_1, PARAM(1), PARAM(2), PARAM(3), PARAM(0)).raw; - Core::g_app_core->SetReg(1, param_1); + Core::AppCore().SetReg(1, param_1); FuncReturn(retval); } @@ -209,8 +209,8 @@ template <ResultCode func(s64*, Handle, u32)> void Wrap() { s64 param_1 = 0; u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw; - Core::g_app_core->SetReg(1, (u32)param_1); - Core::g_app_core->SetReg(2, (u32)(param_1 >> 32)); + Core::AppCore().SetReg(1, (u32)param_1); + Core::AppCore().SetReg(2, (u32)(param_1 >> 32)); FuncReturn(retval); } @@ -227,8 +227,8 @@ void Wrap() { reinterpret_cast<const char*>(Memory::GetPointer(PARAM(2))), PARAM(3)) .raw; // The first out parameter is moved into R2 and the second is moved into R1. - Core::g_app_core->SetReg(1, param_2); - Core::g_app_core->SetReg(2, param_1); + Core::AppCore().SetReg(1, param_2); + Core::AppCore().SetReg(2, param_1); FuncReturn(retval); } diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp index 41b772163..d73d98a70 100644 --- a/src/core/hle/hle.cpp +++ b/src/core/hle/hle.cpp @@ -26,9 +26,9 @@ void Reschedule(const char* reason) { // routines. This simulates that time by artificially advancing the number of CPU "ticks". // The value was chosen empirically, it seems to work well enough for everything tested, but // is likely not ideal. We should find a more accurate way to simulate timing with HLE. - Core::g_app_core->AddTicks(4000); + Core::AppCore().AddTicks(4000); - Core::g_app_core->PrepareReschedule(); + Core::AppCore().PrepareReschedule(); reschedule = true; } diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 18b696f72..91c05fc42 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -188,7 +188,7 @@ static void SwitchContext(Thread* new_thread) { // Save context for previous thread if (previous_thread) { previous_thread->last_running_ticks = CoreTiming::GetTicks(); - Core::g_app_core->SaveContext(previous_thread->context); + Core::AppCore().SaveContext(previous_thread->context); if (previous_thread->status == THREADSTATUS_RUNNING) { // This is only the case when a reschedule is triggered without the current thread @@ -214,8 +214,8 @@ static void SwitchContext(Thread* new_thread) { // Restores thread to its nominal priority if it has been temporarily changed new_thread->current_priority = new_thread->nominal_priority; - Core::g_app_core->LoadContext(new_thread->context); - Core::g_app_core->SetCP15Register(CP15_THREAD_URO, new_thread->GetTLSAddress()); + Core::AppCore().LoadContext(new_thread->context); + Core::AppCore().SetCP15Register(CP15_THREAD_URO, new_thread->GetTLSAddress()); } else { current_thread = nullptr; } diff --git a/src/core/hle/service/ldr_ro/ldr_ro.cpp b/src/core/hle/service/ldr_ro/ldr_ro.cpp index 9e5d6a318..614f16d44 100644 --- a/src/core/hle/service/ldr_ro/ldr_ro.cpp +++ b/src/core/hle/service/ldr_ro/ldr_ro.cpp @@ -457,7 +457,7 @@ static void LoadCRO(Interface* self, bool link_on_load_bug_fix) { } } - Core::g_app_core->ClearInstructionCache(); + Core::AppCore().ClearInstructionCache(); LOG_INFO(Service_LDR, "CRO \"%s\" loaded at 0x%08X, fixed_end=0x%08X", cro.ModuleName().data(), cro_address, cro_address + fix_size); @@ -562,7 +562,7 @@ static void UnloadCRO(Interface* self) { memory_synchronizer.RemoveMemoryBlock(cro_address, cro_buffer_ptr); } - Core::g_app_core->ClearInstructionCache(); + Core::AppCore().ClearInstructionCache(); cmd_buff[1] = result.raw; } @@ -624,7 +624,7 @@ static void LinkCRO(Interface* self) { } memory_synchronizer.SynchronizeOriginalMemory(); - Core::g_app_core->ClearInstructionCache(); + Core::AppCore().ClearInstructionCache(); cmd_buff[1] = result.raw; } @@ -686,7 +686,7 @@ static void UnlinkCRO(Interface* self) { } memory_synchronizer.SynchronizeOriginalMemory(); - Core::g_app_core->ClearInstructionCache(); + Core::AppCore().ClearInstructionCache(); cmd_buff[1] = result.raw; } diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 5839d7230..b20f2aaa4 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -582,7 +582,7 @@ static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point /// Called when a thread exits static void ExitThread() { - LOG_TRACE(Kernel_SVC, "called, pc=0x%08X", Core::g_app_core->GetPC()); + LOG_TRACE(Kernel_SVC, "called, pc=0x%08X", Core::AppCore().GetPC()); Kernel::ExitCurrentThread(); } @@ -612,7 +612,7 @@ static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) { using Kernel::Mutex; SharedPtr<Mutex> mutex = Mutex::Create(initial_locked != 0); - mutex->name = Common::StringFromFormat("mutex-%08x", Core::g_app_core->GetReg(14)); + mutex->name = Common::StringFromFormat("mutex-%08x", Core::AppCore().GetReg(14)); CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex))); LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", @@ -683,7 +683,7 @@ static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max using Kernel::Semaphore; CASCADE_RESULT(SharedPtr<Semaphore> semaphore, Semaphore::Create(initial_count, max_count)); - semaphore->name = Common::StringFromFormat("semaphore-%08x", Core::g_app_core->GetReg(14)); + semaphore->name = Common::StringFromFormat("semaphore-%08x", Core::AppCore().GetReg(14)); CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(semaphore))); LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", @@ -740,7 +740,7 @@ static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) { using Kernel::Event; SharedPtr<Event> evt = Event::Create(static_cast<Kernel::ResetType>(reset_type)); - evt->name = Common::StringFromFormat("event-%08x", Core::g_app_core->GetReg(14)); + evt->name = Common::StringFromFormat("event-%08x", Core::AppCore().GetReg(14)); CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt))); LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type, @@ -787,7 +787,7 @@ static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) { using Kernel::Timer; SharedPtr<Timer> timer = Timer::Create(static_cast<Kernel::ResetType>(reset_type)); - timer->name = Common::StringFromFormat("timer-%08x", Core::g_app_core->GetReg(14)); + timer->name = Common::StringFromFormat("timer-%08x", Core::AppCore().GetReg(14)); CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer))); LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type, @@ -854,7 +854,7 @@ static void SleepThread(s64 nanoseconds) { static s64 GetSystemTick() { s64 result = CoreTiming::GetTicks(); // Advance time to defeat dumb games (like Cubic Ninja) that busy-wait for the frame to end. - Core::g_app_core->AddTicks( + Core::AppCore().AddTicks( 150); // Measured time between two calls on a 9.2 o3DS with Ninjhax 1.1b return result; } diff --git a/src/core/system.cpp b/src/core/system.cpp deleted file mode 100644 index fa8bd0317..000000000 --- a/src/core/system.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "audio_core/audio_core.h" -#include "core/core.h" -#include "core/core_timing.h" -#include "core/gdbstub/gdbstub.h" -#include "core/hle/hle.h" -#include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/memory.h" -#include "core/hw/hw.h" -#include "core/system.h" -#include "video_core/video_core.h" - -namespace Core { - -/*static*/ System System::s_instance; - -System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { - Core::Init(); - CoreTiming::Init(); - Memory::Init(); - HW::Init(); - Kernel::Init(system_mode); - HLE::Init(); - AudioCore::Init(); - GDBStub::Init(); - - if (!VideoCore::Init(emu_window)) { - return ResultStatus::ErrorVideoCore; - } - - is_powered_on = true; - - return ResultStatus::Success; -} - -void System::Shutdown() { - GDBStub::Shutdown(); - AudioCore::Shutdown(); - VideoCore::Shutdown(); - HLE::Shutdown(); - Kernel::Shutdown(); - HW::Shutdown(); - CoreTiming::Shutdown(); - Core::Shutdown(); - - is_powered_on = false; -} - -System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& filepath) { - state.app_loader = Loader::GetLoader(filepath); - - if (!state.app_loader) { - LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filepath.c_str()); - return ResultStatus::ErrorGetLoader; - } - - boost::optional<u32> system_mode{ state.app_loader->LoadKernelSystemMode() }; - if (!system_mode) { - LOG_CRITICAL(Frontend, "Failed to determine system mode!"); - return ResultStatus::ErrorSystemMode; - } - - ResultStatus init_result{ Init(emu_window, system_mode.get()) }; - if (init_result != ResultStatus::Success) { - LOG_CRITICAL(Frontend, "Failed to initialize system (Error %i)!", init_result); - System::Shutdown(); - return init_result; - } - - const Loader::ResultStatus load_result{ state.app_loader->Load() }; - if (Loader::ResultStatus::Success != load_result) { - LOG_CRITICAL(Frontend, "Failed to load ROM (Error %i)!", load_result); - System::Shutdown(); - - switch (load_result) { - case Loader::ResultStatus::ErrorEncrypted: - return ResultStatus::ErrorLoader_ErrorEncrypted; - case Loader::ResultStatus::ErrorInvalidFormat: - return ResultStatus::ErrorLoader_ErrorInvalidFormat; - default: - return ResultStatus::ErrorLoader; - } - } - return ResultStatus::Success; -} - -} // namespace Core diff --git a/src/core/system.h b/src/core/system.h deleted file mode 100644 index 192a9c447..000000000 --- a/src/core/system.h +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <string> - -#include "core/loader/loader.h" - -class EmuWindow; - -namespace Core { - -class System { -public: - struct State { - std::unique_ptr<Loader::AppLoader> app_loader; - }; - - /** - * Gets the instance of the System singleton class. - * @returns Reference to the instance of the System singleton class. - */ - static System& GetInstance() { - return s_instance; - } - - /// Enumeration representing the return values of the System Initialize and Load process. - enum class ResultStatus : u32 { - Success, ///< Succeeded - ErrorGetLoader, ///< Error finding the correct application loader - ErrorSystemMode, ///< Error determining the system mode - ErrorLoader, ///< Error loading the specified application - ErrorLoader_ErrorEncrypted, ///< Error loading the specified application due to encryption - ErrorLoader_ErrorInvalidFormat, ///< Error loading the specified application due to an invalid format - ErrorVideoCore, ///< Error in the video core - }; - - /** - * Initialize the emulated system. - * @param emu_window Pointer to the host-system window used for video output and keyboard input. - * @param system_mode The system mode. - * @returns ResultStatus code, indicating if the operation succeeded. - */ - ResultStatus Init(EmuWindow* emu_window, u32 system_mode); - - /// Shutdown the emulated system. - void Shutdown(); - - /** - * Load an executable application. - * @param emu_window Pointer to the host-system window used for video output and keyboard input. - * @param filepath String path to the executable application to load on the host file system. - * @returns ResultStatus code, indicating if the operation succeeded. - */ - ResultStatus Load(EmuWindow* emu_window, const std::string& filepath); - - /** - * Indicates if the emulated system is powered on (all subsystems initialized and able to run an - * application). - * @returns True if the emulated system is powered on, otherwise false. - */ - bool IsPoweredOn() const { - return is_powered_on; - } - - /** - * Gets the internal state of the emulated system. - * @returns The internal state of the emulated system - */ - State& GetState() { - return state; - } - -private: - bool is_powered_on{}; - State state; - - static System s_instance; -}; - -} // namespace Core |