aboutsummaryrefslogtreecommitdiff
path: root/src/core/core.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/core.cpp')
-rw-r--r--src/core/core.cpp223
1 files changed, 150 insertions, 73 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 3bd90d79f..5accdc783 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -8,12 +8,13 @@
#include "common/file_util.h"
#include "common/logging/log.h"
+#include "common/microprofile.h"
#include "common/string_util.h"
#include "core/arm/exclusive_monitor.h"
#include "core/core.h"
-#include "core/core_manager.h"
#include "core/core_timing.h"
#include "core/cpu_manager.h"
+#include "core/device_memory.h"
#include "core/file_sys/bis_factory.h"
#include "core/file_sys/card_image.h"
#include "core/file_sys/mode.h"
@@ -39,9 +40,11 @@
#include "core/hle/service/lm/manager.h"
#include "core/hle/service/service.h"
#include "core/hle/service/sm/sm.h"
+#include "core/hle/service/time/time_manager.h"
#include "core/loader/loader.h"
#include "core/memory.h"
#include "core/memory/cheat_engine.h"
+#include "core/network/network.h"
#include "core/perf_stats.h"
#include "core/reporter.h"
#include "core/settings.h"
@@ -50,6 +53,11 @@
#include "video_core/renderer_base.h"
#include "video_core/video_core.h"
+MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_CPU0, "ARM JIT", "Dynarmic CPU 0", MP_RGB(255, 64, 64));
+MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_CPU1, "ARM JIT", "Dynarmic CPU 1", MP_RGB(255, 64, 64));
+MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_CPU2, "ARM JIT", "Dynarmic CPU 2", MP_RGB(255, 64, 64));
+MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_CPU3, "ARM JIT", "Dynarmic CPU 3", MP_RGB(255, 64, 64));
+
namespace Core {
namespace {
@@ -106,7 +114,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
return FileSys::ConcatenatedVfsFile::MakeConcatenatedFile(concat, dir->GetName());
}
- if (FileUtil::IsDirectory(path))
+ if (Common::FS::IsDirectory(path))
return vfs->OpenFile(path + "/" + "main", FileSys::Mode::Read);
return vfs->OpenFile(path, FileSys::Mode::Read);
@@ -114,25 +122,24 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
struct System::Impl {
explicit Impl(System& system)
: kernel{system}, fs_controller{system}, memory{system},
- cpu_manager{system}, reporter{system}, applet_manager{system} {}
+ cpu_manager{system}, reporter{system}, applet_manager{system}, time_manager{system} {}
- CoreManager& CurrentCoreManager() {
- return cpu_manager.GetCurrentCoreManager();
- }
+ ResultStatus Run() {
+ status = ResultStatus::Success;
- Kernel::PhysicalCore& CurrentPhysicalCore() {
- const auto index = cpu_manager.GetActiveCoreIndex();
- return kernel.PhysicalCore(index);
- }
+ kernel.Suspend(false);
+ core_timing.SyncPause(false);
+ cpu_manager.Pause(false);
- Kernel::PhysicalCore& GetPhysicalCore(std::size_t index) {
- return kernel.PhysicalCore(index);
+ return status;
}
- ResultStatus RunLoop(bool tight_loop) {
+ ResultStatus Pause() {
status = ResultStatus::Success;
- cpu_manager.RunLoop(tight_loop);
+ core_timing.SyncPause(true);
+ kernel.Suspend(true);
+ cpu_manager.Pause(true);
return status;
}
@@ -140,14 +147,24 @@ struct System::Impl {
ResultStatus Init(System& system, Frontend::EmuWindow& emu_window) {
LOG_DEBUG(HW_Memory, "initialized OK");
- core_timing.Initialize();
+ device_memory = std::make_unique<Core::DeviceMemory>();
+
+ is_multicore = Settings::values.use_multi_core.GetValue();
+ is_async_gpu = is_multicore || Settings::values.use_asynchronous_gpu_emulation.GetValue();
+
+ kernel.SetMulticore(is_multicore);
+ cpu_manager.SetMulticore(is_multicore);
+ cpu_manager.SetAsyncGpu(is_async_gpu);
+ core_timing.SetMulticore(is_multicore);
+
+ core_timing.Initialize([&system]() { system.RegisterHostThread(); });
kernel.Initialize();
cpu_manager.Initialize();
const auto current_time = std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch());
Settings::values.custom_rtc_differential =
- Settings::values.custom_rtc.value_or(current_time) - current_time;
+ Settings::values.custom_rtc.GetValue().value_or(current_time) - current_time;
// Create a default fs if one doesn't already exist.
if (virtual_filesystem == nullptr)
@@ -162,21 +179,30 @@ struct System::Impl {
arp_manager.ResetAll();
telemetry_session = std::make_unique<Core::TelemetrySession>();
- service_manager = std::make_shared<Service::SM::ServiceManager>();
- Service::Init(service_manager, system);
- GDBStub::DeferStart();
-
- interrupt_manager = std::make_unique<Core::Hardware::InterruptManager>(system);
gpu_core = VideoCore::CreateGPU(emu_window, system);
if (!gpu_core) {
return ResultStatus::ErrorVideoCore;
}
- gpu_core->Renderer().Rasterizer().SetupDirtyFlags();
+
+ service_manager = std::make_shared<Service::SM::ServiceManager>(kernel);
+
+ Service::Init(service_manager, system);
+ GDBStub::DeferStart();
+
+ interrupt_manager = std::make_unique<Core::Hardware::InterruptManager>(system);
+
+ // Initialize time manager, which must happen after kernel is created
+ time_manager.Initialize();
is_powered_on = true;
exit_lock = false;
+ microprofile_dynarmic[0] = MICROPROFILE_TOKEN(ARM_Jit_Dynarmic_CPU0);
+ microprofile_dynarmic[1] = MICROPROFILE_TOKEN(ARM_Jit_Dynarmic_CPU1);
+ microprofile_dynarmic[2] = MICROPROFILE_TOKEN(ARM_Jit_Dynarmic_CPU2);
+ microprofile_dynarmic[3] = MICROPROFILE_TOKEN(ARM_Jit_Dynarmic_CPU3);
+
LOG_DEBUG(Core, "Initialized OK");
return ResultStatus::Success;
@@ -184,7 +210,7 @@ struct System::Impl {
ResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
const std::string& filepath) {
- app_loader = Loader::GetLoader(GetGameFileFromPath(virtual_filesystem, filepath));
+ app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath));
if (!app_loader) {
LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
return ResultStatus::ErrorGetLoader;
@@ -198,10 +224,10 @@ struct System::Impl {
return init_result;
}
- telemetry_session->AddInitialInfo(*app_loader);
+ telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider);
auto main_process =
Kernel::Process::Create(system, "main", Kernel::Process::ProcessType::Userland);
- const auto [load_result, load_parameters] = app_loader->Load(*main_process);
+ const auto [load_result, load_parameters] = app_loader->Load(*main_process, system);
if (load_result != Loader::ResultStatus::Success) {
LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast<int>(load_result));
Shutdown();
@@ -248,14 +274,14 @@ struct System::Impl {
// Log last frame performance stats if game was loded
if (perf_stats) {
const auto perf_results = GetAndResetPerfStats();
- telemetry_session->AddField(Telemetry::FieldType::Performance,
- "Shutdown_EmulationSpeed",
+ constexpr auto performance = Common::Telemetry::FieldType::Performance;
+
+ telemetry_session->AddField(performance, "Shutdown_EmulationSpeed",
perf_results.emulation_speed * 100.0);
- telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_Framerate",
- perf_results.game_fps);
- telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_Frametime",
+ telemetry_session->AddField(performance, "Shutdown_Framerate", perf_results.game_fps);
+ telemetry_session->AddField(performance, "Shutdown_Frametime",
perf_results.frametime * 1000.0);
- telemetry_session->AddField(Telemetry::FieldType::Performance, "Mean_Frametime_MS",
+ telemetry_session->AddField(performance, "Mean_Frametime_MS",
perf_stats->GetMeanFrametime());
}
@@ -274,8 +300,7 @@ struct System::Impl {
service_manager.reset();
cheat_engine.reset();
telemetry_session.reset();
- perf_stats.reset();
- gpu_core.reset();
+ device_memory.reset();
// Close all CPU/threading state
cpu_manager.Shutdown();
@@ -286,6 +311,8 @@ struct System::Impl {
// Close app loader
app_loader.reset();
+ gpu_core.reset();
+ perf_stats.reset();
// Clear all applets
applet_manager.ClearAll();
@@ -311,7 +338,7 @@ struct System::Impl {
Service::Glue::ApplicationLaunchProperty launch{};
launch.title_id = process.GetTitleID();
- FileSys::PatchManager pm{launch.title_id};
+ FileSys::PatchManager pm{launch.title_id, fs_controller, *content_provider};
launch.version = pm.GetGameVersion().value_or(0);
// TODO(DarkLordZach): When FSController/Game Card Support is added, if
@@ -346,7 +373,8 @@ struct System::Impl {
std::unique_ptr<Loader::AppLoader> app_loader;
std::unique_ptr<Tegra::GPU> gpu_core;
std::unique_ptr<Hardware::InterruptManager> interrupt_manager;
- Memory::Memory memory;
+ std::unique_ptr<Core::DeviceMemory> device_memory;
+ Core::Memory::Memory memory;
CpuManager cpu_manager;
bool is_powered_on = false;
bool exit_lock = false;
@@ -365,6 +393,7 @@ struct System::Impl {
/// Service State
Service::Glue::ARPManager arp_manager;
Service::LM::Manager lm_manager{reporter};
+ Service::Time::TimeManager time_manager;
/// Service manager
std::shared_ptr<Service::SM::ServiceManager> service_manager;
@@ -372,36 +401,53 @@ struct System::Impl {
/// Telemetry session for this emulation session
std::unique_ptr<Core::TelemetrySession> telemetry_session;
+ /// Network instance
+ Network::NetworkInstance network_instance;
+
ResultStatus status = ResultStatus::Success;
std::string status_details = "";
std::unique_ptr<Core::PerfStats> perf_stats;
Core::FrameLimiter frame_limiter;
+
+ bool is_multicore{};
+ bool is_async_gpu{};
+
+ std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
+ std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_dynarmic{};
};
System::System() : impl{std::make_unique<Impl>(*this)} {}
System::~System() = default;
-CoreManager& System::CurrentCoreManager() {
- return impl->CurrentCoreManager();
+CpuManager& System::GetCpuManager() {
+ return impl->cpu_manager;
+}
+
+const CpuManager& System::GetCpuManager() const {
+ return impl->cpu_manager;
}
-const CoreManager& System::CurrentCoreManager() const {
- return impl->CurrentCoreManager();
+System::ResultStatus System::Run() {
+ return impl->Run();
}
-System::ResultStatus System::RunLoop(bool tight_loop) {
- return impl->RunLoop(tight_loop);
+System::ResultStatus System::Pause() {
+ return impl->Pause();
}
System::ResultStatus System::SingleStep() {
- return RunLoop(false);
+ return ResultStatus::Success;
}
void System::InvalidateCpuInstructionCaches() {
impl->kernel.InvalidateAllInstructionCaches();
}
+void System::Shutdown() {
+ impl->Shutdown();
+}
+
System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) {
return impl->Load(*this, emu_window, filepath);
}
@@ -411,7 +457,7 @@ bool System::IsPoweredOn() const {
}
void System::PrepareReschedule() {
- impl->CurrentPhysicalCore().Stop();
+ // Deprecated, does nothing, kept for backward compatibility.
}
void System::PrepareReschedule(const u32 core_index) {
@@ -431,31 +477,41 @@ const TelemetrySession& System::TelemetrySession() const {
}
ARM_Interface& System::CurrentArmInterface() {
- return impl->CurrentPhysicalCore().ArmInterface();
+ return impl->kernel.CurrentScheduler().GetCurrentThread()->ArmInterface();
}
const ARM_Interface& System::CurrentArmInterface() const {
- return impl->CurrentPhysicalCore().ArmInterface();
+ return impl->kernel.CurrentScheduler().GetCurrentThread()->ArmInterface();
}
std::size_t System::CurrentCoreIndex() const {
- return impl->cpu_manager.GetActiveCoreIndex();
+ std::size_t core = impl->kernel.GetCurrentHostThreadID();
+ ASSERT(core < Core::Hardware::NUM_CPU_CORES);
+ return core;
}
Kernel::Scheduler& System::CurrentScheduler() {
- return impl->CurrentPhysicalCore().Scheduler();
+ return impl->kernel.CurrentScheduler();
}
const Kernel::Scheduler& System::CurrentScheduler() const {
- return impl->CurrentPhysicalCore().Scheduler();
+ return impl->kernel.CurrentScheduler();
+}
+
+Kernel::PhysicalCore& System::CurrentPhysicalCore() {
+ return impl->kernel.CurrentPhysicalCore();
+}
+
+const Kernel::PhysicalCore& System::CurrentPhysicalCore() const {
+ return impl->kernel.CurrentPhysicalCore();
}
Kernel::Scheduler& System::Scheduler(std::size_t core_index) {
- return impl->GetPhysicalCore(core_index).Scheduler();
+ return impl->kernel.Scheduler(core_index);
}
const Kernel::Scheduler& System::Scheduler(std::size_t core_index) const {
- return impl->GetPhysicalCore(core_index).Scheduler();
+ return impl->kernel.Scheduler(core_index);
}
/// Gets the global scheduler
@@ -472,25 +528,28 @@ Kernel::Process* System::CurrentProcess() {
return impl->kernel.CurrentProcess();
}
-const Kernel::Process* System::CurrentProcess() const {
- return impl->kernel.CurrentProcess();
+Core::DeviceMemory& System::DeviceMemory() {
+ return *impl->device_memory;
}
-ARM_Interface& System::ArmInterface(std::size_t core_index) {
- return impl->GetPhysicalCore(core_index).ArmInterface();
+const Core::DeviceMemory& System::DeviceMemory() const {
+ return *impl->device_memory;
}
-const ARM_Interface& System::ArmInterface(std::size_t core_index) const {
- return impl->GetPhysicalCore(core_index).ArmInterface();
+const Kernel::Process* System::CurrentProcess() const {
+ return impl->kernel.CurrentProcess();
}
-CoreManager& System::GetCoreManager(std::size_t core_index) {
- return impl->cpu_manager.GetCoreManager(core_index);
+ARM_Interface& System::ArmInterface(std::size_t core_index) {
+ auto* thread = impl->kernel.Scheduler(core_index).GetCurrentThread();
+ ASSERT(thread && !thread->IsHLEThread());
+ return thread->ArmInterface();
}
-const CoreManager& System::GetCoreManager(std::size_t core_index) const {
- ASSERT(core_index < NUM_CPU_CORES);
- return impl->cpu_manager.GetCoreManager(core_index);
+const ARM_Interface& System::ArmInterface(std::size_t core_index) const {
+ auto* thread = impl->kernel.Scheduler(core_index).GetCurrentThread();
+ ASSERT(thread && !thread->IsHLEThread());
+ return thread->ArmInterface();
}
ExclusiveMonitor& System::Monitor() {
@@ -505,7 +564,7 @@ Memory::Memory& System::Memory() {
return impl->memory;
}
-const Memory::Memory& System::Memory() const {
+const Core::Memory::Memory& System::Memory() const {
return impl->memory;
}
@@ -577,15 +636,19 @@ const std::string& System::GetStatusDetails() const {
return impl->status_details;
}
-Loader::AppLoader& System::GetAppLoader() const {
+Loader::AppLoader& System::GetAppLoader() {
+ return *impl->app_loader;
+}
+
+const Loader::AppLoader& System::GetAppLoader() const {
return *impl->app_loader;
}
-void System::SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs) {
+void System::SetFilesystem(FileSys::VirtualFilesystem vfs) {
impl->virtual_filesystem = std::move(vfs);
}
-std::shared_ptr<FileSys::VfsFilesystem> System::GetFilesystem() const {
+FileSys::VirtualFilesystem System::GetFilesystem() const {
return impl->virtual_filesystem;
}
@@ -669,6 +732,14 @@ const Service::LM::Manager& System::GetLogManager() const {
return impl->lm_manager;
}
+Service::Time::TimeManager& System::GetTimeManager() {
+ return impl->time_manager;
+}
+
+const Service::Time::TimeManager& System::GetTimeManager() const {
+ return impl->time_manager;
+}
+
void System::SetExitLock(bool locked) {
impl->exit_lock = locked;
}
@@ -685,14 +756,6 @@ const System::CurrentBuildProcessID& System::GetCurrentProcessBuildID() const {
return impl->build_id;
}
-System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) {
- return impl->Init(*this, emu_window);
-}
-
-void System::Shutdown() {
- impl->Shutdown();
-}
-
Service::SM::ServiceManager& System::ServiceManager() {
return *impl->service_manager;
}
@@ -709,4 +772,18 @@ void System::RegisterHostThread() {
impl->kernel.RegisterHostThread();
}
+void System::EnterDynarmicProfile() {
+ std::size_t core = impl->kernel.GetCurrentHostThreadID();
+ impl->dynarmic_ticks[core] = MicroProfileEnter(impl->microprofile_dynarmic[core]);
+}
+
+void System::ExitDynarmicProfile() {
+ std::size_t core = impl->kernel.GetCurrentHostThreadID();
+ MicroProfileLeave(impl->microprofile_dynarmic[core], impl->dynarmic_ticks[core]);
+}
+
+bool System::IsMulticore() const {
+ return impl->is_multicore;
+}
+
} // namespace Core