diff options
Diffstat (limited to 'src/core/core.cpp')
| -rw-r--r-- | src/core/core.cpp | 169 |
1 files changed, 96 insertions, 73 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp index 81e8cc338..1a2002dec 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -25,13 +25,12 @@ | |||
| 25 | #include "core/file_sys/sdmc_factory.h" | 25 | #include "core/file_sys/sdmc_factory.h" |
| 26 | #include "core/file_sys/vfs_concat.h" | 26 | #include "core/file_sys/vfs_concat.h" |
| 27 | #include "core/file_sys/vfs_real.h" | 27 | #include "core/file_sys/vfs_real.h" |
| 28 | #include "core/gdbstub/gdbstub.h" | ||
| 29 | #include "core/hardware_interrupt_manager.h" | 28 | #include "core/hardware_interrupt_manager.h" |
| 30 | #include "core/hle/kernel/client_port.h" | 29 | #include "core/hle/kernel/client_port.h" |
| 30 | #include "core/hle/kernel/k_scheduler.h" | ||
| 31 | #include "core/hle/kernel/kernel.h" | 31 | #include "core/hle/kernel/kernel.h" |
| 32 | #include "core/hle/kernel/physical_core.h" | 32 | #include "core/hle/kernel/physical_core.h" |
| 33 | #include "core/hle/kernel/process.h" | 33 | #include "core/hle/kernel/process.h" |
| 34 | #include "core/hle/kernel/scheduler.h" | ||
| 35 | #include "core/hle/kernel/thread.h" | 34 | #include "core/hle/kernel/thread.h" |
| 36 | #include "core/hle/service/am/applets/applets.h" | 35 | #include "core/hle/service/am/applets/applets.h" |
| 37 | #include "core/hle/service/apm/controller.h" | 36 | #include "core/hle/service/apm/controller.h" |
| @@ -40,6 +39,7 @@ | |||
| 40 | #include "core/hle/service/lm/manager.h" | 39 | #include "core/hle/service/lm/manager.h" |
| 41 | #include "core/hle/service/service.h" | 40 | #include "core/hle/service/service.h" |
| 42 | #include "core/hle/service/sm/sm.h" | 41 | #include "core/hle/service/sm/sm.h" |
| 42 | #include "core/hle/service/time/time_manager.h" | ||
| 43 | #include "core/loader/loader.h" | 43 | #include "core/loader/loader.h" |
| 44 | #include "core/memory.h" | 44 | #include "core/memory.h" |
| 45 | #include "core/memory/cheat_engine.h" | 45 | #include "core/memory/cheat_engine.h" |
| @@ -91,37 +91,47 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, | |||
| 91 | std::string dir_name; | 91 | std::string dir_name; |
| 92 | std::string filename; | 92 | std::string filename; |
| 93 | Common::SplitPath(path, &dir_name, &filename, nullptr); | 93 | Common::SplitPath(path, &dir_name, &filename, nullptr); |
| 94 | |||
| 94 | if (filename == "00") { | 95 | if (filename == "00") { |
| 95 | const auto dir = vfs->OpenDirectory(dir_name, FileSys::Mode::Read); | 96 | const auto dir = vfs->OpenDirectory(dir_name, FileSys::Mode::Read); |
| 96 | std::vector<FileSys::VirtualFile> concat; | 97 | std::vector<FileSys::VirtualFile> concat; |
| 97 | for (u8 i = 0; i < 0x10; ++i) { | 98 | |
| 98 | auto next = dir->GetFile(fmt::format("{:02X}", i)); | 99 | for (u32 i = 0; i < 0x10; ++i) { |
| 99 | if (next != nullptr) | 100 | const auto file_name = fmt::format("{:02X}", i); |
| 101 | auto next = dir->GetFile(file_name); | ||
| 102 | |||
| 103 | if (next != nullptr) { | ||
| 100 | concat.push_back(std::move(next)); | 104 | concat.push_back(std::move(next)); |
| 101 | else { | 105 | } else { |
| 102 | next = dir->GetFile(fmt::format("{:02x}", i)); | 106 | next = dir->GetFile(file_name); |
| 103 | if (next != nullptr) | 107 | |
| 104 | concat.push_back(std::move(next)); | 108 | if (next == nullptr) { |
| 105 | else | ||
| 106 | break; | 109 | break; |
| 110 | } | ||
| 111 | |||
| 112 | concat.push_back(std::move(next)); | ||
| 107 | } | 113 | } |
| 108 | } | 114 | } |
| 109 | 115 | ||
| 110 | if (concat.empty()) | 116 | if (concat.empty()) { |
| 111 | return nullptr; | 117 | return nullptr; |
| 118 | } | ||
| 112 | 119 | ||
| 113 | return FileSys::ConcatenatedVfsFile::MakeConcatenatedFile(concat, dir->GetName()); | 120 | return FileSys::ConcatenatedVfsFile::MakeConcatenatedFile(std::move(concat), |
| 121 | dir->GetName()); | ||
| 114 | } | 122 | } |
| 115 | 123 | ||
| 116 | if (Common::FS::IsDirectory(path)) | 124 | if (Common::FS::IsDirectory(path)) { |
| 117 | return vfs->OpenFile(path + "/" + "main", FileSys::Mode::Read); | 125 | return vfs->OpenFile(path + "/main", FileSys::Mode::Read); |
| 126 | } | ||
| 118 | 127 | ||
| 119 | return vfs->OpenFile(path, FileSys::Mode::Read); | 128 | return vfs->OpenFile(path, FileSys::Mode::Read); |
| 120 | } | 129 | } |
| 130 | |||
| 121 | struct System::Impl { | 131 | struct System::Impl { |
| 122 | explicit Impl(System& system) | 132 | explicit Impl(System& system) |
| 123 | : kernel{system}, fs_controller{system}, memory{system}, | 133 | : kernel{system}, fs_controller{system}, memory{system}, |
| 124 | cpu_manager{system}, reporter{system}, applet_manager{system} {} | 134 | cpu_manager{system}, reporter{system}, applet_manager{system}, time_manager{system} {} |
| 125 | 135 | ||
| 126 | ResultStatus Run() { | 136 | ResultStatus Run() { |
| 127 | status = ResultStatus::Success; | 137 | status = ResultStatus::Success; |
| @@ -144,12 +154,12 @@ struct System::Impl { | |||
| 144 | } | 154 | } |
| 145 | 155 | ||
| 146 | ResultStatus Init(System& system, Frontend::EmuWindow& emu_window) { | 156 | ResultStatus Init(System& system, Frontend::EmuWindow& emu_window) { |
| 147 | LOG_DEBUG(HW_Memory, "initialized OK"); | 157 | LOG_DEBUG(Core, "initialized OK"); |
| 148 | 158 | ||
| 149 | device_memory = std::make_unique<Core::DeviceMemory>(); | 159 | device_memory = std::make_unique<Core::DeviceMemory>(); |
| 150 | 160 | ||
| 151 | is_multicore = Settings::values.use_multi_core.GetValue(); | 161 | is_multicore = Settings::values.use_multi_core.GetValue(); |
| 152 | is_async_gpu = is_multicore || Settings::values.use_asynchronous_gpu_emulation.GetValue(); | 162 | is_async_gpu = Settings::values.use_asynchronous_gpu_emulation.GetValue(); |
| 153 | 163 | ||
| 154 | kernel.SetMulticore(is_multicore); | 164 | kernel.SetMulticore(is_multicore); |
| 155 | cpu_manager.SetMulticore(is_multicore); | 165 | cpu_manager.SetMulticore(is_multicore); |
| @@ -178,17 +188,19 @@ struct System::Impl { | |||
| 178 | arp_manager.ResetAll(); | 188 | arp_manager.ResetAll(); |
| 179 | 189 | ||
| 180 | telemetry_session = std::make_unique<Core::TelemetrySession>(); | 190 | telemetry_session = std::make_unique<Core::TelemetrySession>(); |
| 181 | service_manager = std::make_shared<Service::SM::ServiceManager>(kernel); | ||
| 182 | 191 | ||
| 183 | Service::Init(service_manager, system); | ||
| 184 | GDBStub::DeferStart(); | ||
| 185 | |||
| 186 | interrupt_manager = std::make_unique<Core::Hardware::InterruptManager>(system); | ||
| 187 | gpu_core = VideoCore::CreateGPU(emu_window, system); | 192 | gpu_core = VideoCore::CreateGPU(emu_window, system); |
| 188 | if (!gpu_core) { | 193 | if (!gpu_core) { |
| 189 | return ResultStatus::ErrorVideoCore; | 194 | return ResultStatus::ErrorVideoCore; |
| 190 | } | 195 | } |
| 191 | 196 | ||
| 197 | service_manager = std::make_shared<Service::SM::ServiceManager>(kernel); | ||
| 198 | services = std::make_unique<Service::Services>(service_manager, system); | ||
| 199 | interrupt_manager = std::make_unique<Hardware::InterruptManager>(system); | ||
| 200 | |||
| 201 | // Initialize time manager, which must happen after kernel is created | ||
| 202 | time_manager.Initialize(); | ||
| 203 | |||
| 192 | is_powered_on = true; | 204 | is_powered_on = true; |
| 193 | exit_lock = false; | 205 | exit_lock = false; |
| 194 | 206 | ||
| @@ -202,9 +214,11 @@ struct System::Impl { | |||
| 202 | return ResultStatus::Success; | 214 | return ResultStatus::Success; |
| 203 | } | 215 | } |
| 204 | 216 | ||
| 205 | ResultStatus Load(System& system, Frontend::EmuWindow& emu_window, | 217 | ResultStatus Load(System& system, Frontend::EmuWindow& emu_window, const std::string& filepath, |
| 206 | const std::string& filepath) { | 218 | std::size_t program_index) { |
| 207 | app_loader = Loader::GetLoader(GetGameFileFromPath(virtual_filesystem, filepath)); | 219 | app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath), |
| 220 | program_index); | ||
| 221 | |||
| 208 | if (!app_loader) { | 222 | if (!app_loader) { |
| 209 | LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); | 223 | LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); |
| 210 | return ResultStatus::ErrorGetLoader; | 224 | return ResultStatus::ErrorGetLoader; |
| @@ -218,12 +232,12 @@ struct System::Impl { | |||
| 218 | return init_result; | 232 | return init_result; |
| 219 | } | 233 | } |
| 220 | 234 | ||
| 221 | telemetry_session->AddInitialInfo(*app_loader); | 235 | telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider); |
| 222 | auto main_process = | 236 | auto main_process = |
| 223 | Kernel::Process::Create(system, "main", Kernel::Process::ProcessType::Userland); | 237 | Kernel::Process::Create(system, "main", Kernel::Process::ProcessType::Userland); |
| 224 | const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); | 238 | const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); |
| 225 | if (load_result != Loader::ResultStatus::Success) { | 239 | if (load_result != Loader::ResultStatus::Success) { |
| 226 | LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast<int>(load_result)); | 240 | LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result); |
| 227 | Shutdown(); | 241 | Shutdown(); |
| 228 | 242 | ||
| 229 | return static_cast<ResultStatus>(static_cast<u32>(ResultStatus::ErrorLoader) + | 243 | return static_cast<ResultStatus>(static_cast<u32>(ResultStatus::ErrorLoader) + |
| @@ -231,6 +245,7 @@ struct System::Impl { | |||
| 231 | } | 245 | } |
| 232 | AddGlueRegistrationForProcess(*app_loader, *main_process); | 246 | AddGlueRegistrationForProcess(*app_loader, *main_process); |
| 233 | kernel.MakeCurrentProcess(main_process.get()); | 247 | kernel.MakeCurrentProcess(main_process.get()); |
| 248 | kernel.InitializeCores(); | ||
| 234 | 249 | ||
| 235 | // Initialize cheat engine | 250 | // Initialize cheat engine |
| 236 | if (cheat_engine) { | 251 | if (cheat_engine) { |
| @@ -252,8 +267,7 @@ struct System::Impl { | |||
| 252 | 267 | ||
| 253 | u64 title_id{0}; | 268 | u64 title_id{0}; |
| 254 | if (app_loader->ReadProgramId(title_id) != Loader::ResultStatus::Success) { | 269 | if (app_loader->ReadProgramId(title_id) != Loader::ResultStatus::Success) { |
| 255 | LOG_ERROR(Core, "Failed to find title id for ROM (Error {})", | 270 | LOG_ERROR(Core, "Failed to find title id for ROM (Error {})", load_result); |
| 256 | static_cast<u32>(load_result)); | ||
| 257 | } | 271 | } |
| 258 | perf_stats = std::make_unique<PerfStats>(title_id); | 272 | perf_stats = std::make_unique<PerfStats>(title_id); |
| 259 | // Reset counters and set time origin to current frame | 273 | // Reset counters and set time origin to current frame |
| @@ -289,19 +303,17 @@ struct System::Impl { | |||
| 289 | } | 303 | } |
| 290 | 304 | ||
| 291 | // Shutdown emulation session | 305 | // Shutdown emulation session |
| 292 | GDBStub::Shutdown(); | 306 | services.reset(); |
| 293 | Service::Shutdown(); | ||
| 294 | service_manager.reset(); | 307 | service_manager.reset(); |
| 295 | cheat_engine.reset(); | 308 | cheat_engine.reset(); |
| 296 | telemetry_session.reset(); | 309 | telemetry_session.reset(); |
| 297 | device_memory.reset(); | ||
| 298 | 310 | ||
| 299 | // Close all CPU/threading state | 311 | // Close all CPU/threading state |
| 300 | cpu_manager.Shutdown(); | 312 | cpu_manager.Shutdown(); |
| 301 | 313 | ||
| 302 | // Shutdown kernel and core timing | 314 | // Shutdown kernel and core timing |
| 303 | kernel.Shutdown(); | ||
| 304 | core_timing.Shutdown(); | 315 | core_timing.Shutdown(); |
| 316 | kernel.Shutdown(); | ||
| 305 | 317 | ||
| 306 | // Close app loader | 318 | // Close app loader |
| 307 | app_loader.reset(); | 319 | app_loader.reset(); |
| @@ -332,7 +344,7 @@ struct System::Impl { | |||
| 332 | Service::Glue::ApplicationLaunchProperty launch{}; | 344 | Service::Glue::ApplicationLaunchProperty launch{}; |
| 333 | launch.title_id = process.GetTitleID(); | 345 | launch.title_id = process.GetTitleID(); |
| 334 | 346 | ||
| 335 | FileSys::PatchManager pm{launch.title_id}; | 347 | FileSys::PatchManager pm{launch.title_id, fs_controller, *content_provider}; |
| 336 | launch.version = pm.GetGameVersion().value_or(0); | 348 | launch.version = pm.GetGameVersion().value_or(0); |
| 337 | 349 | ||
| 338 | // TODO(DarkLordZach): When FSController/Game Card Support is added, if | 350 | // TODO(DarkLordZach): When FSController/Game Card Support is added, if |
| @@ -387,10 +399,14 @@ struct System::Impl { | |||
| 387 | /// Service State | 399 | /// Service State |
| 388 | Service::Glue::ARPManager arp_manager; | 400 | Service::Glue::ARPManager arp_manager; |
| 389 | Service::LM::Manager lm_manager{reporter}; | 401 | Service::LM::Manager lm_manager{reporter}; |
| 402 | Service::Time::TimeManager time_manager; | ||
| 390 | 403 | ||
| 391 | /// Service manager | 404 | /// Service manager |
| 392 | std::shared_ptr<Service::SM::ServiceManager> service_manager; | 405 | std::shared_ptr<Service::SM::ServiceManager> service_manager; |
| 393 | 406 | ||
| 407 | /// Services | ||
| 408 | std::unique_ptr<Service::Services> services; | ||
| 409 | |||
| 394 | /// Telemetry session for this emulation session | 410 | /// Telemetry session for this emulation session |
| 395 | std::unique_ptr<Core::TelemetrySession> telemetry_session; | 411 | std::unique_ptr<Core::TelemetrySession> telemetry_session; |
| 396 | 412 | ||
| @@ -406,6 +422,8 @@ struct System::Impl { | |||
| 406 | bool is_multicore{}; | 422 | bool is_multicore{}; |
| 407 | bool is_async_gpu{}; | 423 | bool is_async_gpu{}; |
| 408 | 424 | ||
| 425 | ExecuteProgramCallback execute_program_callback; | ||
| 426 | |||
| 409 | std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{}; | 427 | std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{}; |
| 410 | std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_dynarmic{}; | 428 | std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_dynarmic{}; |
| 411 | }; | 429 | }; |
| @@ -437,8 +455,17 @@ void System::InvalidateCpuInstructionCaches() { | |||
| 437 | impl->kernel.InvalidateAllInstructionCaches(); | 455 | impl->kernel.InvalidateAllInstructionCaches(); |
| 438 | } | 456 | } |
| 439 | 457 | ||
| 440 | System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) { | 458 | void System::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) { |
| 441 | return impl->Load(*this, emu_window, filepath); | 459 | impl->kernel.InvalidateCpuInstructionCacheRange(addr, size); |
| 460 | } | ||
| 461 | |||
| 462 | void System::Shutdown() { | ||
| 463 | impl->Shutdown(); | ||
| 464 | } | ||
| 465 | |||
| 466 | System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath, | ||
| 467 | std::size_t program_index) { | ||
| 468 | return impl->Load(*this, emu_window, filepath, program_index); | ||
| 442 | } | 469 | } |
| 443 | 470 | ||
| 444 | bool System::IsPoweredOn() const { | 471 | bool System::IsPoweredOn() const { |
| @@ -466,11 +493,11 @@ const TelemetrySession& System::TelemetrySession() const { | |||
| 466 | } | 493 | } |
| 467 | 494 | ||
| 468 | ARM_Interface& System::CurrentArmInterface() { | 495 | ARM_Interface& System::CurrentArmInterface() { |
| 469 | return impl->kernel.CurrentScheduler().GetCurrentThread()->ArmInterface(); | 496 | return impl->kernel.CurrentPhysicalCore().ArmInterface(); |
| 470 | } | 497 | } |
| 471 | 498 | ||
| 472 | const ARM_Interface& System::CurrentArmInterface() const { | 499 | const ARM_Interface& System::CurrentArmInterface() const { |
| 473 | return impl->kernel.CurrentScheduler().GetCurrentThread()->ArmInterface(); | 500 | return impl->kernel.CurrentPhysicalCore().ArmInterface(); |
| 474 | } | 501 | } |
| 475 | 502 | ||
| 476 | std::size_t System::CurrentCoreIndex() const { | 503 | std::size_t System::CurrentCoreIndex() const { |
| @@ -479,14 +506,6 @@ std::size_t System::CurrentCoreIndex() const { | |||
| 479 | return core; | 506 | return core; |
| 480 | } | 507 | } |
| 481 | 508 | ||
| 482 | Kernel::Scheduler& System::CurrentScheduler() { | ||
| 483 | return impl->kernel.CurrentScheduler(); | ||
| 484 | } | ||
| 485 | |||
| 486 | const Kernel::Scheduler& System::CurrentScheduler() const { | ||
| 487 | return impl->kernel.CurrentScheduler(); | ||
| 488 | } | ||
| 489 | |||
| 490 | Kernel::PhysicalCore& System::CurrentPhysicalCore() { | 509 | Kernel::PhysicalCore& System::CurrentPhysicalCore() { |
| 491 | return impl->kernel.CurrentPhysicalCore(); | 510 | return impl->kernel.CurrentPhysicalCore(); |
| 492 | } | 511 | } |
| @@ -495,22 +514,14 @@ const Kernel::PhysicalCore& System::CurrentPhysicalCore() const { | |||
| 495 | return impl->kernel.CurrentPhysicalCore(); | 514 | return impl->kernel.CurrentPhysicalCore(); |
| 496 | } | 515 | } |
| 497 | 516 | ||
| 498 | Kernel::Scheduler& System::Scheduler(std::size_t core_index) { | ||
| 499 | return impl->kernel.Scheduler(core_index); | ||
| 500 | } | ||
| 501 | |||
| 502 | const Kernel::Scheduler& System::Scheduler(std::size_t core_index) const { | ||
| 503 | return impl->kernel.Scheduler(core_index); | ||
| 504 | } | ||
| 505 | |||
| 506 | /// Gets the global scheduler | 517 | /// Gets the global scheduler |
| 507 | Kernel::GlobalScheduler& System::GlobalScheduler() { | 518 | Kernel::GlobalSchedulerContext& System::GlobalSchedulerContext() { |
| 508 | return impl->kernel.GlobalScheduler(); | 519 | return impl->kernel.GlobalSchedulerContext(); |
| 509 | } | 520 | } |
| 510 | 521 | ||
| 511 | /// Gets the global scheduler | 522 | /// Gets the global scheduler |
| 512 | const Kernel::GlobalScheduler& System::GlobalScheduler() const { | 523 | const Kernel::GlobalSchedulerContext& System::GlobalSchedulerContext() const { |
| 513 | return impl->kernel.GlobalScheduler(); | 524 | return impl->kernel.GlobalSchedulerContext(); |
| 514 | } | 525 | } |
| 515 | 526 | ||
| 516 | Kernel::Process* System::CurrentProcess() { | 527 | Kernel::Process* System::CurrentProcess() { |
| @@ -530,15 +541,11 @@ const Kernel::Process* System::CurrentProcess() const { | |||
| 530 | } | 541 | } |
| 531 | 542 | ||
| 532 | ARM_Interface& System::ArmInterface(std::size_t core_index) { | 543 | ARM_Interface& System::ArmInterface(std::size_t core_index) { |
| 533 | auto* thread = impl->kernel.Scheduler(core_index).GetCurrentThread(); | 544 | return impl->kernel.PhysicalCore(core_index).ArmInterface(); |
| 534 | ASSERT(thread && !thread->IsHLEThread()); | ||
| 535 | return thread->ArmInterface(); | ||
| 536 | } | 545 | } |
| 537 | 546 | ||
| 538 | const ARM_Interface& System::ArmInterface(std::size_t core_index) const { | 547 | const ARM_Interface& System::ArmInterface(std::size_t core_index) const { |
| 539 | auto* thread = impl->kernel.Scheduler(core_index).GetCurrentThread(); | 548 | return impl->kernel.PhysicalCore(core_index).ArmInterface(); |
| 540 | ASSERT(thread && !thread->IsHLEThread()); | ||
| 541 | return thread->ArmInterface(); | ||
| 542 | } | 549 | } |
| 543 | 550 | ||
| 544 | ExclusiveMonitor& System::Monitor() { | 551 | ExclusiveMonitor& System::Monitor() { |
| @@ -625,7 +632,11 @@ const std::string& System::GetStatusDetails() const { | |||
| 625 | return impl->status_details; | 632 | return impl->status_details; |
| 626 | } | 633 | } |
| 627 | 634 | ||
| 628 | Loader::AppLoader& System::GetAppLoader() const { | 635 | Loader::AppLoader& System::GetAppLoader() { |
| 636 | return *impl->app_loader; | ||
| 637 | } | ||
| 638 | |||
| 639 | const Loader::AppLoader& System::GetAppLoader() const { | ||
| 629 | return *impl->app_loader; | 640 | return *impl->app_loader; |
| 630 | } | 641 | } |
| 631 | 642 | ||
| @@ -717,6 +728,14 @@ const Service::LM::Manager& System::GetLogManager() const { | |||
| 717 | return impl->lm_manager; | 728 | return impl->lm_manager; |
| 718 | } | 729 | } |
| 719 | 730 | ||
| 731 | Service::Time::TimeManager& System::GetTimeManager() { | ||
| 732 | return impl->time_manager; | ||
| 733 | } | ||
| 734 | |||
| 735 | const Service::Time::TimeManager& System::GetTimeManager() const { | ||
| 736 | return impl->time_manager; | ||
| 737 | } | ||
| 738 | |||
| 720 | void System::SetExitLock(bool locked) { | 739 | void System::SetExitLock(bool locked) { |
| 721 | impl->exit_lock = locked; | 740 | impl->exit_lock = locked; |
| 722 | } | 741 | } |
| @@ -733,14 +752,6 @@ const System::CurrentBuildProcessID& System::GetCurrentProcessBuildID() const { | |||
| 733 | return impl->build_id; | 752 | return impl->build_id; |
| 734 | } | 753 | } |
| 735 | 754 | ||
| 736 | System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) { | ||
| 737 | return impl->Init(*this, emu_window); | ||
| 738 | } | ||
| 739 | |||
| 740 | void System::Shutdown() { | ||
| 741 | impl->Shutdown(); | ||
| 742 | } | ||
| 743 | |||
| 744 | Service::SM::ServiceManager& System::ServiceManager() { | 755 | Service::SM::ServiceManager& System::ServiceManager() { |
| 745 | return *impl->service_manager; | 756 | return *impl->service_manager; |
| 746 | } | 757 | } |
| @@ -771,4 +782,16 @@ bool System::IsMulticore() const { | |||
| 771 | return impl->is_multicore; | 782 | return impl->is_multicore; |
| 772 | } | 783 | } |
| 773 | 784 | ||
| 785 | void System::RegisterExecuteProgramCallback(ExecuteProgramCallback&& callback) { | ||
| 786 | impl->execute_program_callback = std::move(callback); | ||
| 787 | } | ||
| 788 | |||
| 789 | void System::ExecuteProgram(std::size_t program_index) { | ||
| 790 | if (impl->execute_program_callback) { | ||
| 791 | impl->execute_program_callback(program_index); | ||
| 792 | } else { | ||
| 793 | LOG_CRITICAL(Core, "execute_program_callback must be initialized by the frontend"); | ||
| 794 | } | ||
| 795 | } | ||
| 796 | |||
| 774 | } // namespace Core | 797 | } // namespace Core |