| 
									
										
										
										
											2014-04-08 19:19:26 -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:19:26 -04:00
										 |  |  | // Refer to the license.txt file included.
 | 
					
						
							| 
									
										
										
										
											2013-09-05 18:33:46 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-29 18:03:08 -05:00
										 |  |  | #include <memory>
 | 
					
						
							| 
									
										
										
										
											2017-03-08 20:21:31 -05:00
										 |  |  | #include <utility>
 | 
					
						
							| 
									
										
										
										
											2015-05-06 04:06:12 -03:00
										 |  |  | #include "common/logging/log.h"
 | 
					
						
							| 
									
										
										
										
											2018-08-09 21:33:13 -04:00
										 |  |  | #include "common/string_util.h"
 | 
					
						
							| 
									
										
										
										
											2016-09-20 23:52:38 -07:00
										 |  |  | #include "core/core.h"
 | 
					
						
							| 
									
										
										
										
											2016-09-01 23:18:01 -04:00
										 |  |  | #include "core/core_timing.h"
 | 
					
						
							|  |  |  | #include "core/gdbstub/gdbstub.h"
 | 
					
						
							| 
									
										
										
										
											2018-04-20 19:29:04 -04:00
										 |  |  | #include "core/hle/kernel/client_port.h"
 | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  | #include "core/hle/kernel/kernel.h"
 | 
					
						
							| 
									
										
										
										
											2017-09-26 18:17:47 -05:00
										 |  |  | #include "core/hle/kernel/process.h"
 | 
					
						
							| 
									
										
										
										
											2014-05-22 22:54:07 -04:00
										 |  |  | #include "core/hle/kernel/thread.h"
 | 
					
						
							| 
									
										
										
										
											2016-12-16 00:37:38 -05:00
										 |  |  | #include "core/hle/service/service.h"
 | 
					
						
							| 
									
										
										
										
											2018-04-20 19:29:04 -04:00
										 |  |  | #include "core/hle/service/sm/controller.h"
 | 
					
						
							|  |  |  | #include "core/hle/service/sm/sm.h"
 | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  | #include "core/loader/loader.h"
 | 
					
						
							| 
									
										
										
										
											2016-09-01 23:18:01 -04:00
										 |  |  | #include "core/settings.h"
 | 
					
						
							| 
									
										
										
										
											2018-08-09 20:48:41 -04:00
										 |  |  | #include "file_sys/vfs_concat.h"
 | 
					
						
							| 
									
										
										
										
											2018-07-18 21:07:11 -04:00
										 |  |  | #include "file_sys/vfs_real.h"
 | 
					
						
							| 
									
										
										
										
											2018-08-03 12:55:58 -04:00
										 |  |  | #include "video_core/renderer_base.h"
 | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  | #include "video_core/video_core.h"
 | 
					
						
							| 
									
										
										
										
											2015-09-02 08:56:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-05 18:33:46 -04:00
										 |  |  | namespace Core { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  | /*static*/ System System::s_instance; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-18 18:15:16 -04:00
										 |  |  | System::System() = default; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-20 19:29:04 -04:00
										 |  |  | System::~System() = default; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-02 21:26:14 -04:00
										 |  |  | /// Runs a CPU core while the system is powered on
 | 
					
						
							|  |  |  | static void RunCpuCore(std::shared_ptr<Cpu> cpu_state) { | 
					
						
							| 
									
										
										
										
											2018-07-18 18:10:06 -04:00
										 |  |  |     while (Core::System::GetInstance().IsPoweredOn()) { | 
					
						
							| 
									
										
										
										
											2018-05-02 21:26:14 -04:00
										 |  |  |         cpu_state->RunLoop(true); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-07 22:57:39 -04:00
										 |  |  | Cpu& System::CurrentCpuCore() { | 
					
						
							|  |  |  |     // If multicore is enabled, use host thread to figure out the current CPU core
 | 
					
						
							|  |  |  |     if (Settings::values.use_multi_core) { | 
					
						
							|  |  |  |         const auto& search = thread_to_cpu.find(std::this_thread::get_id()); | 
					
						
							|  |  |  |         ASSERT(search != thread_to_cpu.end()); | 
					
						
							|  |  |  |         ASSERT(search->second); | 
					
						
							|  |  |  |         return *search->second; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Otherwise, use single-threaded mode active_core variable
 | 
					
						
							|  |  |  |     return *cpu_cores[active_core]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-14 18:47:48 +01:00
										 |  |  | System::ResultStatus System::RunLoop(bool tight_loop) { | 
					
						
							| 
									
										
										
										
											2017-06-02 17:03:38 -04:00
										 |  |  |     status = ResultStatus::Success; | 
					
						
							| 
									
										
										
										
											2013-09-05 18:33:46 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-03 00:16:12 -04:00
										 |  |  |     // Update thread_to_cpu in case Core 0 is run from a different host thread
 | 
					
						
							|  |  |  |     thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 16:19:30 -05:00
										 |  |  |     if (GDBStub::IsServerEnabled()) { | 
					
						
							| 
									
										
										
										
											2015-09-02 08:56:38 -04:00
										 |  |  |         GDBStub::HandlePacket(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-18 09:38:01 +09:00
										 |  |  |         // If the loop is halted and we want to step, use a tiny (1) number of instructions to
 | 
					
						
							| 
									
										
										
										
											2016-09-18 18:01:46 -07:00
										 |  |  |         // execute. Otherwise, get out of the loop function.
 | 
					
						
							| 
									
										
										
										
											2015-09-02 08:56:38 -04:00
										 |  |  |         if (GDBStub::GetCpuHaltFlag()) { | 
					
						
							|  |  |  |             if (GDBStub::GetCpuStepFlag()) { | 
					
						
							| 
									
										
										
										
											2018-02-14 18:47:48 +01:00
										 |  |  |                 tight_loop = false; | 
					
						
							| 
									
										
										
										
											2015-09-02 08:56:38 -04:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  |                 return ResultStatus::Success; | 
					
						
							| 
									
										
										
										
											2015-09-02 08:56:38 -04:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-07 22:57:39 -04:00
										 |  |  |     for (active_core = 0; active_core < NUM_CPU_CORES; ++active_core) { | 
					
						
							|  |  |  |         cpu_cores[active_core]->RunLoop(tight_loop); | 
					
						
							|  |  |  |         if (Settings::values.use_multi_core) { | 
					
						
							|  |  |  |             // Cores 1-3 are run on other threads in this mode
 | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-09-26 22:01:09 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-07 03:01:24 +01:00
										 |  |  |     if (GDBStub::IsServerEnabled()) { | 
					
						
							|  |  |  |         GDBStub::SetCpuStepFlag(false); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-02 17:03:38 -04:00
										 |  |  |     return status; | 
					
						
							| 
									
										
										
										
											2013-09-05 18:33:46 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  | System::ResultStatus System::SingleStep() { | 
					
						
							| 
									
										
										
										
											2018-02-14 18:47:48 +01:00
										 |  |  |     return RunLoop(false); | 
					
						
							| 
									
										
										
										
											2013-09-26 22:01:09 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-09 20:48:41 -04:00
										 |  |  | static FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, | 
					
						
							|  |  |  |                                                 const std::string& path) { | 
					
						
							|  |  |  |     // To account for split 00+01+etc files.
 | 
					
						
							|  |  |  |     std::string dir_name; | 
					
						
							|  |  |  |     std::string filename; | 
					
						
							|  |  |  |     Common::SplitPath(path, &dir_name, &filename, nullptr); | 
					
						
							|  |  |  |     if (filename == "00") { | 
					
						
							|  |  |  |         const auto dir = vfs->OpenDirectory(dir_name, FileSys::Mode::Read); | 
					
						
							|  |  |  |         std::vector<FileSys::VirtualFile> concat; | 
					
						
							|  |  |  |         for (u8 i = 0; i < 0x10; ++i) { | 
					
						
							|  |  |  |             auto next = dir->GetFile(fmt::format("{:02X}", i)); | 
					
						
							|  |  |  |             if (next != nullptr) | 
					
						
							|  |  |  |                 concat.push_back(std::move(next)); | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 next = dir->GetFile(fmt::format("{:02x}", i)); | 
					
						
							|  |  |  |                 if (next != nullptr) | 
					
						
							|  |  |  |                     concat.push_back(std::move(next)); | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (concat.empty()) | 
					
						
							|  |  |  |             return nullptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return FileSys::ConcatenateFiles(concat, dir->GetName()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return vfs->OpenFile(path, FileSys::Mode::Read); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-11 20:20:19 -04:00
										 |  |  | System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) { | 
					
						
							| 
									
										
										
										
											2018-08-09 20:48:41 -04:00
										 |  |  |     app_loader = Loader::GetLoader(GetGameFileFromPath(virtual_filesystem, filepath)); | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!app_loader) { | 
					
						
							| 
									
										
										
										
											2018-07-02 10:13:26 -06:00
										 |  |  |         LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  |         return ResultStatus::ErrorGetLoader; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-03-08 20:21:31 -05:00
										 |  |  |     std::pair<boost::optional<u32>, Loader::ResultStatus> system_mode = | 
					
						
							|  |  |  |         app_loader->LoadKernelSystemMode(); | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-08 20:21:31 -05:00
										 |  |  |     if (system_mode.second != Loader::ResultStatus::Success) { | 
					
						
							| 
									
										
										
										
											2018-07-02 10:13:26 -06:00
										 |  |  |         LOG_CRITICAL(Core, "Failed to determine system mode (Error {})!", | 
					
						
							| 
									
										
										
										
											2018-07-02 10:20:50 -06:00
										 |  |  |                      static_cast<int>(system_mode.second)); | 
					
						
							| 
									
										
										
										
											2017-03-08 16:28:30 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-24 02:48:28 -04:00
										 |  |  |         return ResultStatus::ErrorSystemMode; | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-02 23:37:44 -04:00
										 |  |  |     ResultStatus init_result{Init(emu_window)}; | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  |     if (init_result != ResultStatus::Success) { | 
					
						
							| 
									
										
										
										
											2018-07-02 10:13:26 -06:00
										 |  |  |         LOG_CRITICAL(Core, "Failed to initialize system (Error {})!", | 
					
						
							| 
									
										
										
										
											2018-07-02 10:20:50 -06:00
										 |  |  |                      static_cast<int>(init_result)); | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  |         System::Shutdown(); | 
					
						
							|  |  |  |         return init_result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-13 17:49:59 -04:00
										 |  |  |     const Loader::ResultStatus load_result{app_loader->Load(current_process)}; | 
					
						
							| 
									
										
										
										
											2018-08-24 02:48:28 -04:00
										 |  |  |     if (load_result != Loader::ResultStatus::Success) { | 
					
						
							| 
									
										
										
										
											2018-07-02 10:13:26 -06:00
										 |  |  |         LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast<int>(load_result)); | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  |         System::Shutdown(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-24 02:48:28 -04:00
										 |  |  |         return static_cast<ResultStatus>(static_cast<u32>(ResultStatus::ErrorLoader) + | 
					
						
							|  |  |  |                                          static_cast<u32>(load_result)); | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-03-08 16:28:30 -05:00
										 |  |  |     status = ResultStatus::Success; | 
					
						
							| 
									
										
										
										
											2017-06-02 17:03:38 -04:00
										 |  |  |     return status; | 
					
						
							| 
									
										
										
										
											2013-09-05 18:33:46 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-16 00:37:38 -05:00
										 |  |  | void System::PrepareReschedule() { | 
					
						
							| 
									
										
										
										
											2018-05-02 21:26:14 -04:00
										 |  |  |     CurrentCpuCore().PrepareReschedule(); | 
					
						
							| 
									
										
										
										
											2016-12-16 00:37:38 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 14:34:47 -08:00
										 |  |  | PerfStats::Results System::GetAndResetPerfStats() { | 
					
						
							| 
									
										
										
										
											2017-02-20 13:56:58 -08:00
										 |  |  |     return perf_stats.GetAndResetStats(CoreTiming::GetGlobalTimeUs()); | 
					
						
							| 
									
										
										
										
											2017-02-19 14:34:47 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-03 00:34:54 -04:00
										 |  |  | const std::shared_ptr<Kernel::Scheduler>& System::Scheduler(size_t core_index) { | 
					
						
							|  |  |  |     ASSERT(core_index < NUM_CPU_CORES); | 
					
						
							|  |  |  |     return cpu_cores[core_index]->Scheduler(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ARM_Interface& System::ArmInterface(size_t core_index) { | 
					
						
							|  |  |  |     ASSERT(core_index < NUM_CPU_CORES); | 
					
						
							|  |  |  |     return cpu_cores[core_index]->ArmInterface(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-05 23:54:43 -04:00
										 |  |  | Cpu& System::CpuCore(size_t core_index) { | 
					
						
							|  |  |  |     ASSERT(core_index < NUM_CPU_CORES); | 
					
						
							|  |  |  |     return *cpu_cores[core_index]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-11 20:20:19 -04:00
										 |  |  | System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) { | 
					
						
							| 
									
										
										
										
											2018-07-02 10:13:26 -06:00
										 |  |  |     LOG_DEBUG(HW_Memory, "initialized OK"); | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 16:37:48 +00:00
										 |  |  |     CoreTiming::Init(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-03 11:51:48 -04:00
										 |  |  |     // Create a default fs if one doesn't already exist.
 | 
					
						
							|  |  |  |     if (virtual_filesystem == nullptr) | 
					
						
							|  |  |  |         virtual_filesystem = std::make_shared<FileSys::RealVfsFilesystem>(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-13 17:49:59 -04:00
										 |  |  |     current_process = Kernel::Process::Create("main"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-02 21:26:14 -04:00
										 |  |  |     cpu_barrier = std::make_shared<CpuBarrier>(); | 
					
						
							| 
									
										
										
										
											2018-07-03 14:28:46 +01:00
										 |  |  |     cpu_exclusive_monitor = Cpu::MakeExclusiveMonitor(cpu_cores.size()); | 
					
						
							| 
									
										
										
										
											2018-05-02 21:26:14 -04:00
										 |  |  |     for (size_t index = 0; index < cpu_cores.size(); ++index) { | 
					
						
							| 
									
										
										
										
											2018-07-03 14:28:46 +01:00
										 |  |  |         cpu_cores[index] = std::make_shared<Cpu>(cpu_exclusive_monitor, cpu_barrier, index); | 
					
						
							| 
									
										
										
										
											2018-01-12 16:06:30 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-02 00:09:15 -04:00
										 |  |  |     telemetry_session = std::make_unique<Core::TelemetrySession>(); | 
					
						
							| 
									
										
										
										
											2018-04-20 19:29:04 -04:00
										 |  |  |     service_manager = std::make_shared<Service::SM::ServiceManager>(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-02 23:37:44 -04:00
										 |  |  |     Kernel::Init(); | 
					
						
							| 
									
										
										
										
											2018-08-03 11:51:48 -04:00
										 |  |  |     Service::Init(service_manager, virtual_filesystem); | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  |     GDBStub::Init(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-03 12:55:58 -04:00
										 |  |  |     renderer = VideoCore::CreateRenderer(emu_window); | 
					
						
							|  |  |  |     if (!renderer->Init()) { | 
					
						
							| 
									
										
										
										
											2017-03-08 20:21:31 -05:00
										 |  |  |         return ResultStatus::ErrorVideoCore; | 
					
						
							| 
									
										
										
										
											2016-09-01 23:18:01 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-10-25 12:54:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-03 13:56:33 -04:00
										 |  |  |     gpu_core = std::make_unique<Tegra::GPU>(renderer->Rasterizer()); | 
					
						
							| 
									
										
										
										
											2018-08-03 12:55:58 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-02 21:26:14 -04:00
										 |  |  |     // Create threads for CPU cores 1-3, and build thread_to_cpu map
 | 
					
						
							|  |  |  |     // CPU core 0 is run on the main thread
 | 
					
						
							|  |  |  |     thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0]; | 
					
						
							| 
									
										
										
										
											2018-05-03 00:34:54 -04:00
										 |  |  |     if (Settings::values.use_multi_core) { | 
					
						
							|  |  |  |         for (size_t index = 0; index < cpu_core_threads.size(); ++index) { | 
					
						
							|  |  |  |             cpu_core_threads[index] = | 
					
						
							|  |  |  |                 std::make_unique<std::thread>(RunCpuCore, cpu_cores[index + 1]); | 
					
						
							|  |  |  |             thread_to_cpu[cpu_core_threads[index]->get_id()] = cpu_cores[index + 1]; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-05-02 21:26:14 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-02 10:13:26 -06:00
										 |  |  |     LOG_DEBUG(Core, "Initialized OK"); | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 14:34:47 -08:00
										 |  |  |     // Reset counters and set time origin to current frame
 | 
					
						
							|  |  |  |     GetAndResetPerfStats(); | 
					
						
							| 
									
										
										
										
											2017-02-20 13:56:58 -08:00
										 |  |  |     perf_stats.BeginSystemFrame(); | 
					
						
							| 
									
										
										
										
											2017-02-19 14:34:47 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  |     return ResultStatus::Success; | 
					
						
							| 
									
										
										
										
											2014-03-31 22:26:50 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  | void System::Shutdown() { | 
					
						
							| 
									
										
										
										
											2017-07-12 22:19:34 -04:00
										 |  |  |     // Log last frame performance stats
 | 
					
						
							|  |  |  |     auto perf_results = GetAndResetPerfStats(); | 
					
						
							|  |  |  |     Telemetry().AddField(Telemetry::FieldType::Performance, "Shutdown_EmulationSpeed", | 
					
						
							|  |  |  |                          perf_results.emulation_speed * 100.0); | 
					
						
							|  |  |  |     Telemetry().AddField(Telemetry::FieldType::Performance, "Shutdown_Framerate", | 
					
						
							|  |  |  |                          perf_results.game_fps); | 
					
						
							|  |  |  |     Telemetry().AddField(Telemetry::FieldType::Performance, "Shutdown_Frametime", | 
					
						
							|  |  |  |                          perf_results.frametime * 1000.0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Shutdown emulation session
 | 
					
						
							| 
									
										
										
										
											2018-08-03 12:55:58 -04:00
										 |  |  |     renderer.reset(); | 
					
						
							| 
									
										
										
										
											2018-02-21 16:37:48 +00:00
										 |  |  |     GDBStub::Shutdown(); | 
					
						
							| 
									
										
										
										
											2016-12-16 00:37:38 -05:00
										 |  |  |     Service::Shutdown(); | 
					
						
							| 
									
										
										
										
											2016-12-15 19:01:48 -05:00
										 |  |  |     Kernel::Shutdown(); | 
					
						
							| 
									
										
										
										
											2018-04-20 19:29:04 -04:00
										 |  |  |     service_manager.reset(); | 
					
						
							|  |  |  |     telemetry_session.reset(); | 
					
						
							|  |  |  |     gpu_core.reset(); | 
					
						
							| 
									
										
										
										
											2018-05-01 22:21:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-02 21:26:14 -04:00
										 |  |  |     // Close all CPU/threading state
 | 
					
						
							| 
									
										
										
										
											2018-05-03 00:16:12 -04:00
										 |  |  |     cpu_barrier->NotifyEnd(); | 
					
						
							| 
									
										
										
										
											2018-05-03 00:34:54 -04:00
										 |  |  |     if (Settings::values.use_multi_core) { | 
					
						
							|  |  |  |         for (auto& thread : cpu_core_threads) { | 
					
						
							|  |  |  |             thread->join(); | 
					
						
							|  |  |  |             thread.reset(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-05-02 21:26:14 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-05-03 00:16:12 -04:00
										 |  |  |     thread_to_cpu.clear(); | 
					
						
							|  |  |  |     for (auto& cpu_core : cpu_cores) { | 
					
						
							|  |  |  |         cpu_core.reset(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     cpu_barrier.reset(); | 
					
						
							| 
									
										
										
										
											2018-05-01 22:21:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-03 00:16:12 -04:00
										 |  |  |     // Close core timing
 | 
					
						
							| 
									
										
										
										
											2018-02-21 16:37:48 +00:00
										 |  |  |     CoreTiming::Shutdown(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-03 00:16:12 -04:00
										 |  |  |     // Close app loader
 | 
					
						
							| 
									
										
										
										
											2018-04-20 19:29:04 -04:00
										 |  |  |     app_loader.reset(); | 
					
						
							| 
									
										
										
										
											2014-04-05 15:26:03 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-02 10:13:26 -06:00
										 |  |  |     LOG_DEBUG(Core, "Shutdown OK"); | 
					
						
							| 
									
										
										
										
											2013-09-05 18:33:46 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-20 19:29:04 -04:00
										 |  |  | Service::SM::ServiceManager& System::ServiceManager() { | 
					
						
							|  |  |  |     return *service_manager; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const Service::SM::ServiceManager& System::ServiceManager() const { | 
					
						
							|  |  |  |     return *service_manager; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-26 18:17:47 -05:00
										 |  |  | } // namespace Core
 |