// Copyright 2014 Citra Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #pragma once #include #include #include "common/common_types.h" #include "core/memory.h" #include "core/perf_stats.h" class EmuWindow; class ARM_Interface; namespace Loader { class AppLoader; } namespace Core { 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 }; /** * 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 cpu_core != nullptr; } /// Prepare the core emulation for a reschedule void PrepareReschedule(); PerfStats::Results GetAndResetPerfStats(); /** * Gets a reference to the emulated CPU. * @returns A reference to the emulated CPU. */ ARM_Interface& CPU() { return *cpu_core; } PerfStats perf_stats; FrameLimiter frame_limiter; private: /** * 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); /// Reschedule the core emulation void Reschedule(); /// AppLoader used to load the current executing application std::unique_ptr app_loader; ///< ARM11 CPU core std::unique_ptr cpu_core; /// When true, signals that a reschedule should happen bool reschedule_pending{}; static System s_instance; }; inline ARM_Interface& CPU() { return System::GetInstance().CPU(); } } // namespace Core