summaryrefslogtreecommitdiff
path: root/src/core/core.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/core.cpp')
-rw-r--r--src/core/core.cpp169
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
121struct System::Impl { 131struct 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
440System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) { 458void System::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) {
441 return impl->Load(*this, emu_window, filepath); 459 impl->kernel.InvalidateCpuInstructionCacheRange(addr, size);
460}
461
462void System::Shutdown() {
463 impl->Shutdown();
464}
465
466System::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
444bool System::IsPoweredOn() const { 471bool System::IsPoweredOn() const {
@@ -466,11 +493,11 @@ const TelemetrySession& System::TelemetrySession() const {
466} 493}
467 494
468ARM_Interface& System::CurrentArmInterface() { 495ARM_Interface& System::CurrentArmInterface() {
469 return impl->kernel.CurrentScheduler().GetCurrentThread()->ArmInterface(); 496 return impl->kernel.CurrentPhysicalCore().ArmInterface();
470} 497}
471 498
472const ARM_Interface& System::CurrentArmInterface() const { 499const ARM_Interface& System::CurrentArmInterface() const {
473 return impl->kernel.CurrentScheduler().GetCurrentThread()->ArmInterface(); 500 return impl->kernel.CurrentPhysicalCore().ArmInterface();
474} 501}
475 502
476std::size_t System::CurrentCoreIndex() const { 503std::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
482Kernel::Scheduler& System::CurrentScheduler() {
483 return impl->kernel.CurrentScheduler();
484}
485
486const Kernel::Scheduler& System::CurrentScheduler() const {
487 return impl->kernel.CurrentScheduler();
488}
489
490Kernel::PhysicalCore& System::CurrentPhysicalCore() { 509Kernel::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
498Kernel::Scheduler& System::Scheduler(std::size_t core_index) {
499 return impl->kernel.Scheduler(core_index);
500}
501
502const 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
507Kernel::GlobalScheduler& System::GlobalScheduler() { 518Kernel::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
512const Kernel::GlobalScheduler& System::GlobalScheduler() const { 523const Kernel::GlobalSchedulerContext& System::GlobalSchedulerContext() const {
513 return impl->kernel.GlobalScheduler(); 524 return impl->kernel.GlobalSchedulerContext();
514} 525}
515 526
516Kernel::Process* System::CurrentProcess() { 527Kernel::Process* System::CurrentProcess() {
@@ -530,15 +541,11 @@ const Kernel::Process* System::CurrentProcess() const {
530} 541}
531 542
532ARM_Interface& System::ArmInterface(std::size_t core_index) { 543ARM_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
538const ARM_Interface& System::ArmInterface(std::size_t core_index) const { 547const 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
544ExclusiveMonitor& System::Monitor() { 551ExclusiveMonitor& 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
628Loader::AppLoader& System::GetAppLoader() const { 635Loader::AppLoader& System::GetAppLoader() {
636 return *impl->app_loader;
637}
638
639const 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
731Service::Time::TimeManager& System::GetTimeManager() {
732 return impl->time_manager;
733}
734
735const Service::Time::TimeManager& System::GetTimeManager() const {
736 return impl->time_manager;
737}
738
720void System::SetExitLock(bool locked) { 739void 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
736System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) {
737 return impl->Init(*this, emu_window);
738}
739
740void System::Shutdown() {
741 impl->Shutdown();
742}
743
744Service::SM::ServiceManager& System::ServiceManager() { 755Service::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
785void System::RegisterExecuteProgramCallback(ExecuteProgramCallback&& callback) {
786 impl->execute_program_callback = std::move(callback);
787}
788
789void 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