diff --git a/src/core/core.cpp b/src/core/core.cpp index dc515bc824..e1c8b41ee5 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -3,7 +3,6 @@ #include #include -#include #include #include @@ -20,7 +19,6 @@ #include "core/cpu_manager.h" #include "core/debugger/debugger.h" #include "core/device_memory.h" -#include "core/file_sys/bis_factory.h" #include "core/file_sys/fs_filesystem.h" #include "core/file_sys/patch_manager.h" #include "core/file_sys/registered_cache.h" @@ -38,6 +36,7 @@ #include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/am/applet_manager.h" #include "core/hle/service/am/frontend/applets.h" +#include "core/hle/service/am/process_creation.h" #include "core/hle/service/apm/apm_controller.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/glue/glue_manager.h" @@ -72,30 +71,6 @@ MICROPROFILE_DEFINE(ARM_CPU3, "ARM", "CPU 3", MP_RGB(255, 64, 64)); namespace Core { -namespace { - -FileSys::StorageId GetStorageIdForFrontendSlot( - std::optional 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 - FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, const std::string& path) { // To account for split 00+01+etc files. @@ -297,9 +272,6 @@ struct System::Impl { } SystemResultStatus SetupForApplicationProcess(System& system, Frontend::EmuWindow& emu_window) { - /// Reset all glue registrations - arp_manager.ResetAll(); - telemetry_session = std::make_unique(); host1x_core = std::make_unique(system); @@ -335,33 +307,17 @@ struct System::Impl { SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window, const std::string& filepath, Service::AM::FrontendAppletParameters& params) { - app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath), - params.program_id, params.program_index); - - if (!app_loader) { - LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); - return SystemResultStatus::ErrorGetLoader; - } - - if (app_loader->ReadProgramId(params.program_id) != Loader::ResultStatus::Success) { - LOG_ERROR(Core, "Failed to find title id for ROM!"); - } - - std::string name = "Unknown program"; - if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) { - LOG_ERROR(Core, "Failed to read title for ROM!"); - } - - LOG_INFO(Core, "Loading {} ({})", name, params.program_id); - InitializeKernel(system); - // Create the application process. - auto main_process = Kernel::KProcess::Create(system.Kernel()); - Kernel::KProcess::Register(system.Kernel(), main_process); - kernel.AppendNewProcess(main_process); - kernel.MakeApplicationProcess(main_process); - const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); + const auto file = GetGameFileFromPath(virtual_filesystem, filepath); + + // Create the application process + Loader::ResultStatus load_result{}; + std::vector control; + auto process = + Service::AM::CreateApplicationProcess(control, app_loader, load_result, system, file, + params.program_id, params.program_index); + if (load_result != Loader::ResultStatus::Success) { LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result); ShutdownMainProcess(); @@ -370,6 +326,25 @@ struct System::Impl { static_cast(SystemResultStatus::ErrorLoader) + static_cast(load_result)); } + if (!app_loader) { + LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); + return SystemResultStatus::ErrorGetLoader; + } + + if (app_loader->ReadProgramId(params.program_id) != Loader::ResultStatus::Success) { + LOG_ERROR(Core, "Failed to find program id for ROM!"); + } + + std::string name = "Unknown program"; + if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) { + LOG_ERROR(Core, "Failed to read title for ROM!"); + } + + LOG_INFO(Core, "Loading {} ({:016X}) ...", name, params.program_id); + + // Make the process created be the application + kernel.MakeApplicationProcess(process->GetHandle()); + // Set up the rest of the system. SystemResultStatus init_result{SetupForApplicationProcess(system, emu_window)}; if (init_result != SystemResultStatus::Success) { @@ -379,7 +354,6 @@ struct System::Impl { return init_result; } - AddGlueRegistrationForProcess(*app_loader, *main_process); telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider); // Initialize cheat engine @@ -387,14 +361,9 @@ struct System::Impl { cheat_engine->Initialize(); } - // Register with applet manager. - applet_manager.CreateAndInsertByFrontendAppletParameters(main_process->GetProcessId(), - params); - - // 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); - main_process->Close(); + // Register with applet manager + // All threads are started, begin main process execution, now that we're in the clear + applet_manager.CreateAndInsertByFrontendAppletParameters(std::move(process), params); if (Settings::values.gamecard_inserted) { if (Settings::values.gamecard_current_game) { @@ -461,7 +430,6 @@ struct System::Impl { kernel.SuspendEmulation(true); kernel.CloseServices(); kernel.ShutdownCores(); - applet_manager.Reset(); services.reset(); service_manager.reset(); fs_controller.Reset(); @@ -484,6 +452,9 @@ struct System::Impl { room_member->SendGameInfo(game_info); } + // Reset all glue registrations + arp_manager.ResetAll(); + LOG_DEBUG(Core, "Shutdown OK"); } @@ -501,31 +472,6 @@ struct System::Impl { return app_loader->ReadTitle(out); } - void AddGlueRegistrationForProcess(Loader::AppLoader& loader, Kernel::KProcess& process) { - std::vector 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.GetProgramId(); - - 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 - // 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(SystemResultStatus new_status, const char* details = nullptr) { status = new_status; if (details) { diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index cb9a11a631..80566b7e77 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -1170,6 +1170,7 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: // Determine if we are an application. if (pool == KMemoryManager::Pool::Application) { flag |= Svc::CreateProcessFlag::IsApplication; + m_is_application = true; } // If we are 64-bit, create as such. diff --git a/src/core/hle/service/am/applet_manager.cpp b/src/core/hle/service/am/applet_manager.cpp index f0b2d28b8e..923b973f72 100644 --- a/src/core/hle/service/am/applet_manager.cpp +++ b/src/core/hle/service/am/applet_manager.cpp @@ -267,13 +267,12 @@ void AppletManager::TerminateAndRemoveApplet(u64 aruid) { } void AppletManager::CreateAndInsertByFrontendAppletParameters( - u64 aruid, const FrontendAppletParameters& params) { + std::unique_ptr process, const FrontendAppletParameters& params) { // TODO: this should be run inside AM so that the events will have a parent process // TODO: have am create the guest process - auto applet = std::make_shared(m_system, std::make_unique(m_system), + auto applet = std::make_shared(m_system, std::move(process), params.applet_id == AppletId::Application); - applet->aruid.pid = aruid; applet->program_id = params.program_id; applet->applet_id = params.applet_id; applet->type = params.applet_type; @@ -329,6 +328,7 @@ void AppletManager::CreateAndInsertByFrontendAppletParameters( // Applet was started by frontend, so it is foreground. applet->lifecycle_manager.SetFocusState(FocusState::InFocus); + applet->process->Run(); this->InsertApplet(std::move(applet)); } diff --git a/src/core/hle/service/am/applet_manager.h b/src/core/hle/service/am/applet_manager.h index 44143e26a8..39a967c694 100644 --- a/src/core/hle/service/am/applet_manager.h +++ b/src/core/hle/service/am/applet_manager.h @@ -12,6 +12,10 @@ namespace Core { class System; } +namespace Service { +class Process; +} + namespace Service::AM { enum class LaunchType { @@ -36,7 +40,7 @@ public: void InsertApplet(std::shared_ptr applet); void TerminateAndRemoveApplet(u64 aruid); - void CreateAndInsertByFrontendAppletParameters(u64 aruid, + void CreateAndInsertByFrontendAppletParameters(std::unique_ptr process, const FrontendAppletParameters& params); std::shared_ptr GetByAppletResourceUserId(u64 aruid) const; diff --git a/src/core/hle/service/am/hid_registration.cpp b/src/core/hle/service/am/hid_registration.cpp index 793ba2e14f..baa2a18fd1 100644 --- a/src/core/hle/service/am/hid_registration.cpp +++ b/src/core/hle/service/am/hid_registration.cpp @@ -13,21 +13,21 @@ namespace Service::AM { HidRegistration::HidRegistration(Core::System& system, Process& process) : m_process(process) { m_hid_server = system.ServiceManager().GetService("hid"); - if (m_process.IsInitialized()) { + if (m_hid_server && m_process.IsInitialized()) { m_hid_server->GetResourceManager()->RegisterAppletResourceUserId(m_process.GetProcessId(), true); } } HidRegistration::~HidRegistration() { - if (m_process.IsInitialized()) { + if (m_hid_server && m_process.IsInitialized()) { m_hid_server->GetResourceManager()->UnregisterAppletResourceUserId( m_process.GetProcessId()); } } void HidRegistration::EnableAppletToGetInput(bool enable) { - if (m_process.IsInitialized()) { + if (m_hid_server && m_process.IsInitialized()) { m_hid_server->GetResourceManager()->EnableInput(m_process.GetProcessId(), enable); } } diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 8775369a41..6f7703fced 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -49,8 +49,7 @@ struct Memory::Impl { void SetCurrentPageTable(Kernel::KProcess& process) { current_page_table = &process.GetPageTable().GetImpl(); - if (std::addressof(process) == system.ApplicationProcess() && - Settings::IsFastmemEnabled()) { + if (process.IsApplication() && Settings::IsFastmemEnabled()) { current_page_table->fastmem_arena = system.DeviceMemory().buffer.VirtualBasePointer(); } else { current_page_table->fastmem_arena = nullptr;