| |
| |
| |
|
|
| #pragma once |
|
|
| #include <atomic> |
| #include <memory> |
| #include <mutex> |
| #include <string> |
| #include <boost/optional.hpp> |
| #include <boost/serialization/version.hpp> |
| #include "common/common_types.h" |
| #include "core/arm/arm_interface.h" |
| #include "core/cheats/cheats.h" |
| #include "core/hle/service/apt/applet_manager.h" |
| #include "core/hle/service/plgldr/plgldr.h" |
| #include "core/movie.h" |
| #include "core/perf_stats.h" |
|
|
| namespace Frontend { |
| class EmuWindow; |
| class ImageInterface; |
| class MiiSelector; |
| class SoftwareKeyboard; |
| } |
|
|
| namespace Memory { |
| class MemorySystem; |
| } |
|
|
| namespace AudioCore { |
| class DspInterface; |
| } |
|
|
| namespace Core::RPC { |
| class Server; |
| } |
|
|
| namespace Service { |
| namespace SM { |
| class ServiceManager; |
| } |
| namespace FS { |
| class ArchiveManager; |
| } |
| } |
|
|
| namespace Kernel { |
| class KernelSystem; |
| struct New3dsHwCapabilities; |
| enum class MemoryMode : u8; |
| } |
|
|
| namespace VideoDumper { |
| class Backend; |
| } |
|
|
| namespace VideoCore { |
| class CustomTexManager; |
| class GPU; |
| } |
|
|
| namespace Pica { |
| class DebugContext; |
| } |
|
|
| namespace Loader { |
| class AppLoader; |
| } |
|
|
| namespace Core { |
|
|
| class ARM_Interface; |
| class TelemetrySession; |
| class ExclusiveMonitor; |
| class Timing; |
|
|
| class System { |
| public: |
| |
| |
| |
| |
| [[nodiscard]] static System& GetInstance() { |
| return s_instance; |
| } |
|
|
| |
| enum class ResultStatus : u32 { |
| Success, |
| ErrorNotInitialized, |
| ErrorGetLoader, |
| ErrorSystemMode, |
| ErrorLoader, |
| ErrorLoader_ErrorEncrypted, |
| ErrorLoader_ErrorInvalidFormat, |
| |
| ErrorLoader_ErrorGbaTitle, |
| |
| ErrorSystemFiles, |
| ErrorSavestate, |
| ShutdownRequested, |
| ErrorUnknown |
| }; |
|
|
| explicit System(); |
| ~System(); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| [[nodiscard]] ResultStatus RunLoop(bool tight_loop = true); |
|
|
| |
| |
| |
| |
| [[nodiscard]] ResultStatus SingleStep(); |
|
|
| |
| void Shutdown(bool is_deserializing = false); |
|
|
| |
| void Reset(); |
|
|
| enum class Signal : u32 { None, Shutdown, Reset, Save, Load }; |
|
|
| bool SendSignal(Signal signal, u32 param = 0); |
|
|
| |
| void RequestReset(const std::string& chainload = "") { |
| m_chainloadpath = chainload; |
| SendSignal(Signal::Reset); |
| } |
|
|
| |
| void RequestShutdown() { |
| SendSignal(Signal::Shutdown); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| [[nodiscard]] ResultStatus Load(Frontend::EmuWindow& emu_window, const std::string& filepath, |
| Frontend::EmuWindow* secondary_window = {}); |
|
|
| |
| |
| |
| |
| |
| [[nodiscard]] bool IsPoweredOn() const { |
| return is_powered_on; |
| } |
|
|
| |
| |
| |
| |
| [[nodiscard]] Core::TelemetrySession& TelemetrySession() const { |
| return *telemetry_session; |
| } |
|
|
| |
| void PrepareReschedule(); |
|
|
| [[nodiscard]] PerfStats::Results GetAndResetPerfStats(); |
|
|
| [[nodiscard]] PerfStats::Results GetLastPerfStats(); |
|
|
| |
| |
| |
| |
|
|
| [[nodiscard]] ARM_Interface& GetRunningCore() { |
| return *running_core; |
| }; |
|
|
| |
| |
| |
| |
| |
|
|
| [[nodiscard]] ARM_Interface& GetCore(u32 core_id) { |
| return *cpu_cores[core_id]; |
| }; |
|
|
| [[nodiscard]] const ARM_Interface& GetCore(u32 core_id) const { |
| return *cpu_cores[core_id]; |
| }; |
|
|
| [[nodiscard]] u32 GetNumCores() const { |
| return static_cast<u32>(cpu_cores.size()); |
| } |
|
|
| void InvalidateCacheRange(u32 start_address, std::size_t length) { |
| for (const auto& cpu : cpu_cores) { |
| cpu->InvalidateCacheRange(start_address, length); |
| } |
| } |
|
|
| |
| |
| |
| |
| [[nodiscard]] AudioCore::DspInterface& DSP() { |
| return *dsp_core; |
| } |
|
|
| [[nodiscard]] VideoCore::GPU& GPU(); |
|
|
| |
| |
| |
| |
| [[nodiscard]] Service::SM::ServiceManager& ServiceManager(); |
|
|
| |
| |
| |
| |
| [[nodiscard]] const Service::SM::ServiceManager& ServiceManager() const; |
|
|
| |
| [[nodiscard]] Service::FS::ArchiveManager& ArchiveManager(); |
|
|
| |
| [[nodiscard]] const Service::FS::ArchiveManager& ArchiveManager() const; |
|
|
| |
| [[nodiscard]] Kernel::KernelSystem& Kernel(); |
|
|
| |
| [[nodiscard]] const Kernel::KernelSystem& Kernel() const; |
|
|
| |
| [[nodiscard]] bool KernelRunning(); |
|
|
| |
| [[nodiscard]] Timing& CoreTiming(); |
|
|
| |
| [[nodiscard]] const Timing& CoreTiming() const; |
|
|
| |
| [[nodiscard]] Memory::MemorySystem& Memory(); |
|
|
| |
| [[nodiscard]] const Memory::MemorySystem& Memory() const; |
|
|
| |
| [[nodiscard]] Cheats::CheatEngine& CheatEngine(); |
|
|
| |
| [[nodiscard]] const Cheats::CheatEngine& CheatEngine() const; |
|
|
| |
| [[nodiscard]] VideoCore::CustomTexManager& CustomTexManager(); |
|
|
| |
| [[nodiscard]] const VideoCore::CustomTexManager& CustomTexManager() const; |
|
|
| |
| [[nodiscard]] Core::Movie& Movie(); |
|
|
| |
| [[nodiscard]] const Core::Movie& Movie() const; |
|
|
| |
|
|
| void RegisterVideoDumper(std::shared_ptr<VideoDumper::Backend> video_dumper); |
|
|
| [[nodiscard]] std::shared_ptr<VideoDumper::Backend> GetVideoDumper() const { |
| return video_dumper; |
| } |
|
|
| std::unique_ptr<PerfStats> perf_stats; |
| FrameLimiter frame_limiter; |
|
|
| void SetStatus(ResultStatus new_status, const char* details = nullptr) { |
| status = new_status; |
| if (details) { |
| status_details = details; |
| } |
| } |
|
|
| [[nodiscard]] const std::string& GetStatusDetails() const { |
| return status_details; |
| } |
|
|
| [[nodiscard]] Loader::AppLoader& GetAppLoader() const { |
| return *app_loader; |
| } |
|
|
| |
|
|
| void RegisterMiiSelector(std::shared_ptr<Frontend::MiiSelector> mii_selector); |
|
|
| void RegisterSoftwareKeyboard(std::shared_ptr<Frontend::SoftwareKeyboard> swkbd); |
|
|
| [[nodiscard]] std::shared_ptr<Frontend::MiiSelector> GetMiiSelector() const { |
| return registered_mii_selector; |
| } |
|
|
| [[nodiscard]] std::shared_ptr<Frontend::SoftwareKeyboard> GetSoftwareKeyboard() const { |
| return registered_swkbd; |
| } |
|
|
| |
|
|
| void RegisterImageInterface(std::shared_ptr<Frontend::ImageInterface> image_interface); |
|
|
| [[nodiscard]] std::shared_ptr<Frontend::ImageInterface> GetImageInterface() const { |
| return registered_image_interface; |
| } |
|
|
| |
|
|
| void RegisterMicPermissionCheck(const std::function<bool()>& permission_func) { |
| mic_permission_func = permission_func; |
| } |
|
|
| [[nodiscard]] bool HasMicPermission() { |
| return !mic_permission_func || mic_permission_granted || |
| (mic_permission_granted = mic_permission_func()); |
| } |
|
|
| void SaveState(u32 slot) const; |
|
|
| void LoadState(u32 slot); |
|
|
| |
| bool SetSelfDelete(const std::string& file) { |
| if (m_filepath == file) { |
| self_delete_pending = true; |
| return true; |
| } |
| return false; |
| } |
|
|
| |
| void ApplySettings(); |
|
|
| private: |
| |
| |
| |
| |
| |
| |
| |
| [[nodiscard]] ResultStatus Init(Frontend::EmuWindow& emu_window, |
| Frontend::EmuWindow* secondary_window, |
| Kernel::MemoryMode memory_mode, |
| const Kernel::New3dsHwCapabilities& n3ds_hw_caps, |
| u32 num_cores); |
|
|
| |
| void Reschedule(); |
|
|
| |
| std::unique_ptr<Loader::AppLoader> app_loader; |
|
|
| |
| std::vector<std::shared_ptr<ARM_Interface>> cpu_cores; |
| ARM_Interface* running_core = nullptr; |
|
|
| |
| std::unique_ptr<AudioCore::DspInterface> dsp_core; |
|
|
| |
| bool reschedule_pending{}; |
|
|
| |
| std::unique_ptr<Core::TelemetrySession> telemetry_session; |
|
|
| std::unique_ptr<VideoCore::GPU> gpu; |
|
|
| |
| std::unique_ptr<Service::SM::ServiceManager> service_manager; |
|
|
| |
| std::shared_ptr<Frontend::MiiSelector> registered_mii_selector; |
| std::shared_ptr<Frontend::SoftwareKeyboard> registered_swkbd; |
|
|
| |
| Core::Movie movie; |
|
|
| |
| Cheats::CheatEngine cheat_engine; |
|
|
| |
| std::shared_ptr<VideoDumper::Backend> video_dumper; |
|
|
| |
| std::unique_ptr<VideoCore::CustomTexManager> custom_tex_manager; |
|
|
| |
| std::shared_ptr<Frontend::ImageInterface> registered_image_interface; |
|
|
| #ifdef ENABLE_SCRIPTING |
| |
| std::unique_ptr<RPC::Server> rpc_server; |
| #endif |
|
|
| std::unique_ptr<Service::FS::ArchiveManager> archive_manager; |
|
|
| std::unique_ptr<Memory::MemorySystem> memory; |
| std::unique_ptr<Kernel::KernelSystem> kernel; |
| std::unique_ptr<Timing> timing; |
|
|
| std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; |
|
|
| private: |
| static System s_instance; |
|
|
| std::atomic_bool is_powered_on{}; |
|
|
| ResultStatus status = ResultStatus::Success; |
| std::string status_details = ""; |
| |
| Frontend::EmuWindow* m_emu_window; |
| Frontend::EmuWindow* m_secondary_window; |
| std::string m_filepath; |
| std::string m_chainloadpath; |
| u64 title_id; |
| bool self_delete_pending; |
|
|
| std::mutex signal_mutex; |
| Signal current_signal; |
| u32 signal_param; |
|
|
| std::function<bool()> mic_permission_func; |
| bool mic_permission_granted = false; |
|
|
| boost::optional<Service::APT::DeliverArg> restore_deliver_arg; |
| boost::optional<Service::PLGLDR::PLG_LDR::PluginLoaderContext> restore_plugin_context; |
|
|
| friend class boost::serialization::access; |
| template <typename Archive> |
| void serialize(Archive& ar, const unsigned int file_version); |
| }; |
|
|
| [[nodiscard]] inline ARM_Interface& GetRunningCore() { |
| return System::GetInstance().GetRunningCore(); |
| } |
|
|
| [[nodiscard]] inline ARM_Interface& GetCore(u32 core_id) { |
| return System::GetInstance().GetCore(core_id); |
| } |
|
|
| [[nodiscard]] inline u32 GetNumCores() { |
| return System::GetInstance().GetNumCores(); |
| } |
|
|
| } |
|
|
| BOOST_CLASS_VERSION(Core::System, 1) |
|
|