| 
									
										
										
										
											2014-04-08 19:15:46 -04:00
										 |  |  | // Copyright 2014 Citra Emulator Project
 | 
					
						
							| 
									
										
										
										
											2014-12-16 21:38:14 -08:00
										 |  |  | // Licensed under GPLv2 or any later version
 | 
					
						
							| 
									
										
										
										
											2014-04-08 19:15:46 -04:00
										 |  |  | // Refer to the license.txt file included.
 | 
					
						
							| 
									
										
										
										
											2013-09-05 18:33:46 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-08 19:15:46 -04:00
										 |  |  | #pragma once
 | 
					
						
							| 
									
										
										
										
											2013-09-05 18:33:46 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-01 22:21:38 -04:00
										 |  |  | #include <array>
 | 
					
						
							| 
									
										
										
										
											2015-12-29 18:03:08 -05:00
										 |  |  | #include <memory>
 | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  | #include <string>
 | 
					
						
							| 
									
										
										
										
											2018-05-02 21:26:14 -04:00
										 |  |  | #include <thread>
 | 
					
						
							| 
									
										
										
										
											2018-07-26 22:03:33 -04:00
										 |  |  | #include "audio_core/audio_out.h"
 | 
					
						
							| 
									
										
										
										
											2014-12-22 04:30:09 -02:00
										 |  |  | #include "common/common_types.h"
 | 
					
						
							| 
									
										
										
										
											2018-07-03 14:28:46 +01:00
										 |  |  | #include "core/arm/exclusive_monitor.h"
 | 
					
						
							| 
									
										
										
										
											2018-05-01 22:21:38 -04:00
										 |  |  | #include "core/core_cpu.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-13 17:49:59 -04:00
										 |  |  | #include "core/hle/kernel/kernel.h"
 | 
					
						
							| 
									
										
										
										
											2018-02-18 15:17:16 -05:00
										 |  |  | #include "core/hle/kernel/scheduler.h"
 | 
					
						
							| 
									
										
										
										
											2017-08-01 19:53:35 -04:00
										 |  |  | #include "core/loader/loader.h"
 | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  | #include "core/memory.h"
 | 
					
						
							| 
									
										
										
										
											2017-02-19 14:34:47 -08:00
										 |  |  | #include "core/perf_stats.h"
 | 
					
						
							| 
									
										
										
										
											2017-05-02 00:09:15 -04:00
										 |  |  | #include "core/telemetry_session.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-24 23:35:06 -05:00
										 |  |  | #include "video_core/debug_utils/debug_utils.h"
 | 
					
						
							| 
									
										
										
										
											2018-02-11 23:44:12 -05:00
										 |  |  | #include "video_core/gpu.h"
 | 
					
						
							| 
									
										
										
										
											2014-12-22 04:30:09 -02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  | class EmuWindow; | 
					
						
							| 
									
										
										
										
											2014-12-22 04:30:09 -02:00
										 |  |  | class ARM_Interface; | 
					
						
							| 
									
										
										
										
											2014-04-03 21:22:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-20 19:29:04 -04:00
										 |  |  | namespace Service::SM { | 
					
						
							|  |  |  | class ServiceManager; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-05 18:33:46 -04:00
										 |  |  | namespace Core { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  | class System { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2018-04-20 19:29:04 -04:00
										 |  |  |     ~System(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  |     /**
 | 
					
						
							|  |  |  |      * 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 { | 
					
						
							| 
									
										
										
										
											2016-12-17 01:20:47 -05:00
										 |  |  |         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
 | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  |         ErrorLoader_ErrorEncrypted, ///< Error loading the specified application due to encryption
 | 
					
						
							| 
									
										
										
										
											2016-12-17 01:20:47 -05:00
										 |  |  |         ErrorLoader_ErrorInvalidFormat, ///< Error loading the specified application due to an
 | 
					
						
							|  |  |  |                                         /// invalid format
 | 
					
						
							| 
									
										
										
										
											2017-03-08 16:28:30 -05:00
										 |  |  |         ErrorSystemFiles,               ///< Error in finding system files
 | 
					
						
							|  |  |  |         ErrorSharedFont,                ///< Error in finding shared font
 | 
					
						
							| 
									
										
										
										
											2016-12-17 01:20:47 -05:00
										 |  |  |         ErrorVideoCore,                 ///< Error in the video core
 | 
					
						
							| 
									
										
										
										
											2018-04-06 17:06:32 +02:00
										 |  |  |         ErrorUnsupportedArch,           ///< Unsupported Architecture (32-Bit ROMs)
 | 
					
						
							| 
									
										
										
										
											2017-03-08 16:28:30 -05:00
										 |  |  |         ErrorUnknown                    ///< Any other error
 | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * Run the core CPU loop | 
					
						
							| 
									
										
										
										
											2016-12-17 01:20:47 -05:00
										 |  |  |      * 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). | 
					
						
							| 
									
										
										
										
											2018-02-14 18:47:48 +01:00
										 |  |  |      * @param tight_loop If false, the CPU single-steps. | 
					
						
							| 
									
										
										
										
											2018-01-23 14:20:18 +01:00
										 |  |  |      * @return Result status, indicating whether or not the operation succeeded. | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2018-02-14 18:47:48 +01:00
										 |  |  |     ResultStatus RunLoop(bool tight_loop = true); | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * Step the CPU one instruction | 
					
						
							| 
									
										
										
										
											2018-01-23 14:20:18 +01:00
										 |  |  |      * @return Result status, indicating whether or not the operation succeeded. | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  |      */ | 
					
						
							|  |  |  |     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 { | 
					
						
							| 
									
										
										
										
											2018-05-03 00:16:12 -04:00
										 |  |  |         return cpu_barrier && cpu_barrier->IsAlive(); | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-02 00:09:15 -04:00
										 |  |  |     /**
 | 
					
						
							|  |  |  |      * Returns a reference to the telemetry session for this emulation session. | 
					
						
							|  |  |  |      * @returns Reference to the telemetry session. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     Core::TelemetrySession& TelemetrySession() const { | 
					
						
							|  |  |  |         return *telemetry_session; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-16 00:37:38 -05:00
										 |  |  |     /// Prepare the core emulation for a reschedule
 | 
					
						
							|  |  |  |     void PrepareReschedule(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 19:34:21 -04:00
										 |  |  |     /// Gets and resets core performance statistics
 | 
					
						
							| 
									
										
										
										
											2017-02-19 14:34:47 -08:00
										 |  |  |     PerfStats::Results GetAndResetPerfStats(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 19:34:21 -04:00
										 |  |  |     /// Gets an ARM interface to the CPU core that is currently running
 | 
					
						
							| 
									
										
										
										
											2018-05-02 22:36:51 -04:00
										 |  |  |     ARM_Interface& CurrentArmInterface() { | 
					
						
							|  |  |  |         return CurrentCpuCore().ArmInterface(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-03 14:28:46 +01:00
										 |  |  |     /// Gets the index of the currently running CPU core
 | 
					
						
							|  |  |  |     size_t CurrentCoreIndex() { | 
					
						
							|  |  |  |         return CurrentCpuCore().CoreIndex(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 19:34:21 -04:00
										 |  |  |     /// Gets an ARM interface to the CPU core with the specified index
 | 
					
						
							| 
									
										
										
										
											2018-05-03 00:34:54 -04:00
										 |  |  |     ARM_Interface& ArmInterface(size_t core_index); | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 19:34:21 -04:00
										 |  |  |     /// Gets a CPU interface to the CPU core with the specified index
 | 
					
						
							| 
									
										
										
										
											2018-05-05 23:54:43 -04:00
										 |  |  |     Cpu& CpuCore(size_t core_index); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 19:34:21 -04:00
										 |  |  |     /// Gets the GPU interface
 | 
					
						
							| 
									
										
										
										
											2018-02-11 23:44:12 -05:00
										 |  |  |     Tegra::GPU& GPU() { | 
					
						
							|  |  |  |         return *gpu_core; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-26 22:03:33 -04:00
										 |  |  |     /// Gets the AudioCore interface
 | 
					
						
							|  |  |  |     AudioCore::AudioOut& AudioCore() { | 
					
						
							|  |  |  |         return *audio_core; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 19:34:21 -04:00
										 |  |  |     /// Gets the scheduler for the CPU core that is currently running
 | 
					
						
							| 
									
										
										
										
											2018-05-02 22:36:51 -04:00
										 |  |  |     Kernel::Scheduler& CurrentScheduler() { | 
					
						
							|  |  |  |         return *CurrentCpuCore().Scheduler(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-03 14:28:46 +01:00
										 |  |  |     /// Gets the exclusive monitor
 | 
					
						
							|  |  |  |     ExclusiveMonitor& Monitor() { | 
					
						
							|  |  |  |         return *cpu_exclusive_monitor; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 19:34:21 -04:00
										 |  |  |     /// Gets the scheduler for the CPU core with the specified index
 | 
					
						
							| 
									
										
										
										
											2018-05-03 00:34:54 -04:00
										 |  |  |     const std::shared_ptr<Kernel::Scheduler>& Scheduler(size_t core_index); | 
					
						
							| 
									
										
										
										
											2018-02-18 15:17:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 19:34:21 -04:00
										 |  |  |     /// Gets the current process
 | 
					
						
							| 
									
										
										
										
											2018-03-13 17:49:59 -04:00
										 |  |  |     Kernel::SharedPtr<Kernel::Process>& CurrentProcess() { | 
					
						
							|  |  |  |         return current_process; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-20 13:56:58 -08:00
										 |  |  |     PerfStats perf_stats; | 
					
						
							| 
									
										
										
										
											2017-02-20 16:31:59 -08:00
										 |  |  |     FrameLimiter frame_limiter; | 
					
						
							| 
									
										
										
										
											2017-02-19 14:34:47 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-02 17:03:38 -04:00
										 |  |  |     void SetStatus(ResultStatus new_status, const char* details = nullptr) { | 
					
						
							| 
									
										
										
										
											2017-04-13 01:15:23 -04:00
										 |  |  |         status = new_status; | 
					
						
							| 
									
										
										
										
											2017-06-02 17:03:38 -04:00
										 |  |  |         if (details) { | 
					
						
							|  |  |  |             status_details = details; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-04-13 01:15:23 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-02 17:03:38 -04:00
										 |  |  |     const std::string& GetStatusDetails() const { | 
					
						
							| 
									
										
										
										
											2017-04-13 01:15:23 -04:00
										 |  |  |         return status_details; | 
					
						
							| 
									
										
										
										
											2017-03-08 16:28:30 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-01 19:53:35 -04:00
										 |  |  |     Loader::AppLoader& GetAppLoader() const { | 
					
						
							|  |  |  |         return *app_loader; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-20 19:29:04 -04:00
										 |  |  |     Service::SM::ServiceManager& ServiceManager(); | 
					
						
							|  |  |  |     const Service::SM::ServiceManager& ServiceManager() const; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-24 23:35:06 -05:00
										 |  |  |     void SetGPUDebugContext(std::shared_ptr<Tegra::DebugContext> context) { | 
					
						
							|  |  |  |         debug_context = std::move(context); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     std::shared_ptr<Tegra::DebugContext> GetGPUDebugContext() const { | 
					
						
							|  |  |  |         return debug_context; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  | private: | 
					
						
							| 
									
										
										
										
											2018-07-18 18:15:16 -04:00
										 |  |  |     System(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-07 22:57:39 -04:00
										 |  |  |     /// Returns the currently running CPU core
 | 
					
						
							|  |  |  |     Cpu& CurrentCpuCore(); | 
					
						
							| 
									
										
										
										
											2018-05-02 21:26:14 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-16 00:37:38 -05:00
										 |  |  |     /**
 | 
					
						
							|  |  |  |      * 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); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  |     /// AppLoader used to load the current executing application
 | 
					
						
							|  |  |  |     std::unique_ptr<Loader::AppLoader> app_loader; | 
					
						
							| 
									
										
										
										
											2018-02-11 23:44:12 -05:00
										 |  |  |     std::unique_ptr<Tegra::GPU> gpu_core; | 
					
						
							| 
									
										
										
										
											2018-07-26 22:03:33 -04:00
										 |  |  |     std::unique_ptr<AudioCore::AudioOut> audio_core; | 
					
						
							| 
									
										
										
										
											2018-03-24 23:35:06 -05:00
										 |  |  |     std::shared_ptr<Tegra::DebugContext> debug_context; | 
					
						
							| 
									
										
										
										
											2018-03-13 17:49:59 -04:00
										 |  |  |     Kernel::SharedPtr<Kernel::Process> current_process; | 
					
						
							| 
									
										
										
										
											2018-07-03 14:28:46 +01:00
										 |  |  |     std::shared_ptr<ExclusiveMonitor> cpu_exclusive_monitor; | 
					
						
							| 
									
										
										
										
											2018-05-02 21:26:14 -04:00
										 |  |  |     std::shared_ptr<CpuBarrier> cpu_barrier; | 
					
						
							|  |  |  |     std::array<std::shared_ptr<Cpu>, NUM_CPU_CORES> cpu_cores; | 
					
						
							|  |  |  |     std::array<std::unique_ptr<std::thread>, NUM_CPU_CORES - 1> cpu_core_threads; | 
					
						
							| 
									
										
										
										
											2018-05-07 22:57:39 -04:00
										 |  |  |     size_t active_core{}; ///< Active core, only used in single thread mode
 | 
					
						
							| 
									
										
										
										
											2016-12-16 00:37:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-20 19:29:04 -04:00
										 |  |  |     /// Service manager
 | 
					
						
							|  |  |  |     std::shared_ptr<Service::SM::ServiceManager> service_manager; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-02 00:09:15 -04:00
										 |  |  |     /// Telemetry session for this emulation session
 | 
					
						
							|  |  |  |     std::unique_ptr<Core::TelemetrySession> telemetry_session; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  |     static System s_instance; | 
					
						
							| 
									
										
										
										
											2017-04-13 01:15:23 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-02 17:03:38 -04:00
										 |  |  |     ResultStatus status = ResultStatus::Success; | 
					
						
							|  |  |  |     std::string status_details = ""; | 
					
						
							| 
									
										
										
										
											2018-05-02 21:26:14 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /// Map of guest threads to CPU cores
 | 
					
						
							|  |  |  |     std::map<std::thread::id, std::shared_ptr<Cpu>> thread_to_cpu; | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2013-09-05 18:33:46 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-02 22:36:51 -04:00
										 |  |  | inline ARM_Interface& CurrentArmInterface() { | 
					
						
							|  |  |  |     return System::GetInstance().CurrentArmInterface(); | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-04-05 00:01:07 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-02 00:09:15 -04:00
										 |  |  | inline TelemetrySession& Telemetry() { | 
					
						
							|  |  |  |     return System::GetInstance().TelemetrySession(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-13 17:49:59 -04:00
										 |  |  | inline Kernel::SharedPtr<Kernel::Process>& CurrentProcess() { | 
					
						
							|  |  |  |     return System::GetInstance().CurrentProcess(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  | } // namespace Core
 |