summaryrefslogtreecommitdiffstats
path: root/src/core/core.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/core.cpp190
1 files changed, 169 insertions, 21 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index ff0721079..92ba42fb9 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -14,30 +14,66 @@
#include "core/core_cpu.h"
#include "core/core_timing.h"
#include "core/cpu_core_manager.h"
+#include "core/file_sys/bis_factory.h"
+#include "core/file_sys/card_image.h"
#include "core/file_sys/mode.h"
+#include "core/file_sys/patch_manager.h"
#include "core/file_sys/registered_cache.h"
+#include "core/file_sys/romfs_factory.h"
+#include "core/file_sys/savedata_factory.h"
+#include "core/file_sys/sdmc_factory.h"
#include "core/file_sys/vfs_concat.h"
#include "core/file_sys/vfs_real.h"
#include "core/gdbstub/gdbstub.h"
+#include "core/hardware_interrupt_manager.h"
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/scheduler.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/service/am/applets/applets.h"
+#include "core/hle/service/apm/controller.h"
+#include "core/hle/service/filesystem/filesystem.h"
+#include "core/hle/service/glue/manager.h"
#include "core/hle/service/service.h"
#include "core/hle/service/sm/sm.h"
#include "core/loader/loader.h"
+#include "core/memory/cheat_engine.h"
#include "core/perf_stats.h"
+#include "core/reporter.h"
#include "core/settings.h"
#include "core/telemetry_session.h"
-#include "file_sys/cheat_engine.h"
+#include "core/tools/freezer.h"
#include "video_core/debug_utils/debug_utils.h"
#include "video_core/renderer_base.h"
#include "video_core/video_core.h"
namespace Core {
+namespace {
+
+FileSys::StorageId GetStorageIdForFrontendSlot(
+ std::optional<FileSys::ContentProviderUnionSlot> slot) {
+ if (!slot.has_value()) {
+ return FileSys::StorageId::None;
+ }
+
+ switch (*slot) {
+ case FileSys::ContentProviderUnionSlot::UserNAND:
+ return FileSys::StorageId::NandUser;
+ case FileSys::ContentProviderUnionSlot::SysNAND:
+ return FileSys::StorageId::NandSystem;
+ case FileSys::ContentProviderUnionSlot::SDMC:
+ return FileSys::StorageId::SdCard;
+ case FileSys::ContentProviderUnionSlot::FrontendManual:
+ return FileSys::StorageId::Host;
+ default:
+ return FileSys::StorageId::None;
+ }
+}
+
+} // Anonymous namespace
+
/*static*/ System System::s_instance;
FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
@@ -74,7 +110,8 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
return vfs->OpenFile(path, FileSys::Mode::Read);
}
struct System::Impl {
- explicit Impl(System& system) : kernel{system}, cpu_core_manager{system} {}
+ explicit Impl(System& system)
+ : kernel{system}, cpu_core_manager{system}, applet_manager{system}, reporter{system} {}
Cpu& CurrentCpuCore() {
return cpu_core_manager.GetCurrentCore();
@@ -109,27 +146,27 @@ struct System::Impl {
/// Create default implementations of applets if one is not provided.
applet_manager.SetDefaultAppletsIfMissing();
+ /// Reset all glue registrations
+ arp_manager.ResetAll();
+
telemetry_session = std::make_unique<Core::TelemetrySession>();
service_manager = std::make_shared<Service::SM::ServiceManager>();
- Service::Init(service_manager, system, *virtual_filesystem);
+ Service::Init(service_manager, system);
GDBStub::Init();
renderer = VideoCore::CreateRenderer(emu_window, system);
if (!renderer->Init()) {
return ResultStatus::ErrorVideoCore;
}
-
+ interrupt_manager = std::make_unique<Core::Hardware::InterruptManager>(system);
gpu_core = VideoCore::CreateGPU(system);
is_powered_on = true;
+ exit_lock = false;
LOG_DEBUG(Core, "Initialized OK");
- // Reset counters and set time origin to current frame
- GetAndResetPerfStats();
- perf_stats.BeginSystemFrame();
-
return ResultStatus::Success;
}
@@ -150,7 +187,8 @@ struct System::Impl {
}
telemetry_session->AddInitialInfo(*app_loader);
- auto main_process = Kernel::Process::Create(system, "main");
+ auto main_process =
+ Kernel::Process::Create(system, "main", Kernel::Process::ProcessType::Userland);
const auto [load_result, load_parameters] = app_loader->Load(*main_process);
if (load_result != Loader::ResultStatus::Success) {
LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast<int>(load_result));
@@ -159,6 +197,7 @@ struct System::Impl {
return static_cast<ResultStatus>(static_cast<u32>(ResultStatus::ErrorLoader) +
static_cast<u32>(load_result));
}
+ AddGlueRegistrationForProcess(*app_loader, *main_process);
kernel.MakeCurrentProcess(main_process.get());
// Main process has been loaded and been made current.
@@ -166,10 +205,34 @@ struct System::Impl {
gpu_core->Start();
cpu_core_manager.StartThreads();
+ // Initialize cheat engine
+ if (cheat_engine) {
+ cheat_engine->Initialize();
+ }
+
// All threads are started, begin main process execution, now that we're in the clear.
main_process->Run(load_parameters->main_thread_priority,
load_parameters->main_thread_stack_size);
+ if (Settings::values.gamecard_inserted) {
+ if (Settings::values.gamecard_current_game) {
+ fs_controller.SetGameCard(GetGameFileFromPath(virtual_filesystem, filepath));
+ } else if (!Settings::values.gamecard_path.empty()) {
+ fs_controller.SetGameCard(
+ GetGameFileFromPath(virtual_filesystem, Settings::values.gamecard_path));
+ }
+ }
+
+ u64 title_id{0};
+ if (app_loader->ReadProgramId(title_id) != Loader::ResultStatus::Success) {
+ LOG_ERROR(Core, "Failed to find title id for ROM (Error {})",
+ static_cast<u32>(load_result));
+ }
+ perf_stats = std::make_unique<PerfStats>(title_id);
+ // Reset counters and set time origin to current frame
+ GetAndResetPerfStats();
+ perf_stats->BeginSystemFrame();
+
status = ResultStatus::Success;
return status;
}
@@ -183,8 +246,11 @@ struct System::Impl {
perf_results.game_fps);
telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_Frametime",
perf_results.frametime * 1000.0);
+ telemetry_session->AddField(Telemetry::FieldType::Performance, "Mean_Frametime_MS",
+ perf_stats->GetMeanFrametime());
is_powered_on = false;
+ exit_lock = false;
// Shutdown emulation session
renderer.reset();
@@ -193,6 +259,7 @@ struct System::Impl {
service_manager.reset();
cheat_engine.reset();
telemetry_session.reset();
+ perf_stats.reset();
gpu_core.reset();
// Close all CPU/threading state
@@ -217,6 +284,31 @@ struct System::Impl {
return app_loader->ReadTitle(out);
}
+ void AddGlueRegistrationForProcess(Loader::AppLoader& loader, Kernel::Process& process) {
+ std::vector<u8> nacp_data;
+ FileSys::NACP nacp;
+ if (loader.ReadControlData(nacp) == Loader::ResultStatus::Success) {
+ nacp_data = nacp.GetRawBytes();
+ } else {
+ nacp_data.resize(sizeof(FileSys::RawNACP));
+ }
+
+ Service::Glue::ApplicationLaunchProperty launch{};
+ launch.title_id = process.GetTitleID();
+
+ FileSys::PatchManager pm{launch.title_id};
+ launch.version = pm.GetGameVersion().value_or(0);
+
+ // TODO(DarkLordZach): When FSController/Game Card Support is added, if
+ // current_process_game_card use correct StorageId
+ launch.base_game_storage_id = GetStorageIdForFrontendSlot(content_provider->GetSlotForEntry(
+ launch.title_id, FileSys::ContentRecordType::Program));
+ launch.update_storage_id = GetStorageIdForFrontendSlot(content_provider->GetSlotForEntry(
+ FileSys::GetUpdateTitleID(launch.title_id), FileSys::ContentRecordType::Program));
+
+ arp_manager.Register(launch.title_id, launch, std::move(nacp_data));
+ }
+
void SetStatus(ResultStatus new_status, const char* details = nullptr) {
status = new_status;
if (details) {
@@ -225,7 +317,7 @@ struct System::Impl {
}
PerfStatsResults GetAndResetPerfStats() {
- return perf_stats.GetAndResetStats(core_timing.GetGlobalTimeUs());
+ return perf_stats->GetAndResetStats(core_timing.GetGlobalTimeUs());
}
Timing::CoreTiming core_timing;
@@ -234,29 +326,41 @@ struct System::Impl {
FileSys::VirtualFilesystem virtual_filesystem;
/// ContentProviderUnion instance
std::unique_ptr<FileSys::ContentProviderUnion> content_provider;
+ Service::FileSystem::FileSystemController fs_controller;
/// AppLoader used to load the current executing application
std::unique_ptr<Loader::AppLoader> app_loader;
std::unique_ptr<VideoCore::RendererBase> renderer;
std::unique_ptr<Tegra::GPU> gpu_core;
std::shared_ptr<Tegra::DebugContext> debug_context;
+ std::unique_ptr<Core::Hardware::InterruptManager> interrupt_manager;
CpuCoreManager cpu_core_manager;
bool is_powered_on = false;
+ bool exit_lock = false;
- std::unique_ptr<FileSys::CheatEngine> cheat_engine;
+ std::unique_ptr<Memory::CheatEngine> cheat_engine;
+ std::unique_ptr<Tools::Freezer> memory_freezer;
/// Frontend applets
Service::AM::Applets::AppletManager applet_manager;
+ /// APM (Performance) services
+ Service::APM::Controller apm_controller{core_timing};
+
+ /// Glue services
+ Service::Glue::ARPManager arp_manager;
+
/// Service manager
std::shared_ptr<Service::SM::ServiceManager> service_manager;
/// Telemetry session for this emulation session
std::unique_ptr<Core::TelemetrySession> telemetry_session;
+ Reporter reporter;
+
ResultStatus status = ResultStatus::Success;
std::string status_details = "";
- Core::PerfStats perf_stats;
+ std::unique_ptr<Core::PerfStats> perf_stats;
Core::FrameLimiter frame_limiter;
};
@@ -376,6 +480,14 @@ const Tegra::GPU& System::GPU() const {
return *impl->gpu_core;
}
+Core::Hardware::InterruptManager& System::InterruptManager() {
+ return *impl->interrupt_manager;
+}
+
+const Core::Hardware::InterruptManager& System::InterruptManager() const {
+ return *impl->interrupt_manager;
+}
+
VideoCore::RendererBase& System::Renderer() {
return *impl->renderer;
}
@@ -401,11 +513,11 @@ const Timing::CoreTiming& System::CoreTiming() const {
}
Core::PerfStats& System::GetPerfStats() {
- return impl->perf_stats;
+ return *impl->perf_stats;
}
const Core::PerfStats& System::GetPerfStats() const {
- return impl->perf_stats;
+ return *impl->perf_stats;
}
Core::FrameLimiter& System::FrameLimiter() {
@@ -440,13 +552,6 @@ Tegra::DebugContext* System::GetGPUDebugContext() const {
return impl->debug_context.get();
}
-void System::RegisterCheatList(const std::vector<FileSys::CheatList>& list,
- const std::string& build_id, VAddr code_region_start,
- VAddr code_region_end) {
- impl->cheat_engine = std::make_unique<FileSys::CheatEngine>(*this, list, build_id,
- code_region_start, code_region_end);
-}
-
void System::SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs) {
impl->virtual_filesystem = std::move(vfs);
}
@@ -455,6 +560,13 @@ std::shared_ptr<FileSys::VfsFilesystem> System::GetFilesystem() const {
return impl->virtual_filesystem;
}
+void System::RegisterCheatList(const std::vector<Memory::CheatEntry>& list,
+ const std::array<u8, 32>& build_id, VAddr main_region_begin,
+ u64 main_region_size) {
+ impl->cheat_engine = std::make_unique<Memory::CheatEngine>(*this, list, build_id);
+ impl->cheat_engine->SetMainMemoryParameters(main_region_begin, main_region_size);
+}
+
void System::SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set) {
impl->applet_manager.SetAppletFrontendSet(std::move(set));
}
@@ -483,6 +595,14 @@ const FileSys::ContentProvider& System::GetContentProvider() const {
return *impl->content_provider;
}
+Service::FileSystem::FileSystemController& System::GetFileSystemController() {
+ return impl->fs_controller;
+}
+
+const Service::FileSystem::FileSystemController& System::GetFileSystemController() const {
+ return impl->fs_controller;
+}
+
void System::RegisterContentProvider(FileSys::ContentProviderUnionSlot slot,
FileSys::ContentProvider* provider) {
impl->content_provider->SetSlot(slot, provider);
@@ -492,6 +612,34 @@ void System::ClearContentProvider(FileSys::ContentProviderUnionSlot slot) {
impl->content_provider->ClearSlot(slot);
}
+const Reporter& System::GetReporter() const {
+ return impl->reporter;
+}
+
+Service::Glue::ARPManager& System::GetARPManager() {
+ return impl->arp_manager;
+}
+
+const Service::Glue::ARPManager& System::GetARPManager() const {
+ return impl->arp_manager;
+}
+
+Service::APM::Controller& System::GetAPMController() {
+ return impl->apm_controller;
+}
+
+const Service::APM::Controller& System::GetAPMController() const {
+ return impl->apm_controller;
+}
+
+void System::SetExitLock(bool locked) {
+ impl->exit_lock = locked;
+}
+
+bool System::GetExitLock() const {
+ return impl->exit_lock;
+}
+
System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) {
return impl->Init(*this, emu_window);
}