core: move main applet initialization to am

This commit is contained in:
Liam 2024-02-25 21:16:47 -05:00
parent 89e00dff57
commit 23ac21dc6e
6 changed files with 48 additions and 98 deletions

View File

@ -3,7 +3,6 @@
#include <array> #include <array>
#include <atomic> #include <atomic>
#include <exception>
#include <memory> #include <memory>
#include <utility> #include <utility>
@ -20,7 +19,6 @@
#include "core/cpu_manager.h" #include "core/cpu_manager.h"
#include "core/debugger/debugger.h" #include "core/debugger/debugger.h"
#include "core/device_memory.h" #include "core/device_memory.h"
#include "core/file_sys/bis_factory.h"
#include "core/file_sys/fs_filesystem.h" #include "core/file_sys/fs_filesystem.h"
#include "core/file_sys/patch_manager.h" #include "core/file_sys/patch_manager.h"
#include "core/file_sys/registered_cache.h" #include "core/file_sys/registered_cache.h"
@ -38,6 +36,7 @@
#include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/acc/profile_manager.h"
#include "core/hle/service/am/applet_manager.h" #include "core/hle/service/am/applet_manager.h"
#include "core/hle/service/am/frontend/applets.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/apm/apm_controller.h"
#include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/glue/glue_manager.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 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
FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
const std::string& path) { const std::string& path) {
// To account for split 00+01+etc files. // To account for split 00+01+etc files.
@ -297,9 +272,6 @@ struct System::Impl {
} }
SystemResultStatus SetupForApplicationProcess(System& system, Frontend::EmuWindow& emu_window) { SystemResultStatus SetupForApplicationProcess(System& system, Frontend::EmuWindow& emu_window) {
/// Reset all glue registrations
arp_manager.ResetAll();
telemetry_session = std::make_unique<Core::TelemetrySession>(); telemetry_session = std::make_unique<Core::TelemetrySession>();
host1x_core = std::make_unique<Tegra::Host1x::Host1x>(system); host1x_core = std::make_unique<Tegra::Host1x::Host1x>(system);
@ -335,33 +307,17 @@ struct System::Impl {
SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window, SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
const std::string& filepath, const std::string& filepath,
Service::AM::FrontendAppletParameters& params) { 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); InitializeKernel(system);
// Create the application process. const auto file = GetGameFileFromPath(virtual_filesystem, filepath);
auto main_process = Kernel::KProcess::Create(system.Kernel());
Kernel::KProcess::Register(system.Kernel(), main_process); // Create the application process
kernel.AppendNewProcess(main_process); Loader::ResultStatus load_result{};
kernel.MakeApplicationProcess(main_process); std::vector<u8> control;
const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); auto process =
Service::AM::CreateApplicationProcess(control, app_loader, load_result, system, file,
params.program_id, params.program_index);
if (load_result != Loader::ResultStatus::Success) { if (load_result != Loader::ResultStatus::Success) {
LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result); LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result);
ShutdownMainProcess(); ShutdownMainProcess();
@ -370,6 +326,25 @@ struct System::Impl {
static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result)); static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(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. // Set up the rest of the system.
SystemResultStatus init_result{SetupForApplicationProcess(system, emu_window)}; SystemResultStatus init_result{SetupForApplicationProcess(system, emu_window)};
if (init_result != SystemResultStatus::Success) { if (init_result != SystemResultStatus::Success) {
@ -379,7 +354,6 @@ struct System::Impl {
return init_result; return init_result;
} }
AddGlueRegistrationForProcess(*app_loader, *main_process);
telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider); telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider);
// Initialize cheat engine // Initialize cheat engine
@ -387,14 +361,9 @@ struct System::Impl {
cheat_engine->Initialize(); cheat_engine->Initialize();
} }
// Register with applet manager. // Register with applet manager
applet_manager.CreateAndInsertByFrontendAppletParameters(main_process->GetProcessId(), // All threads are started, begin main process execution, now that we're in the clear
params); applet_manager.CreateAndInsertByFrontendAppletParameters(std::move(process), 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();
if (Settings::values.gamecard_inserted) { if (Settings::values.gamecard_inserted) {
if (Settings::values.gamecard_current_game) { if (Settings::values.gamecard_current_game) {
@ -461,7 +430,6 @@ struct System::Impl {
kernel.SuspendEmulation(true); kernel.SuspendEmulation(true);
kernel.CloseServices(); kernel.CloseServices();
kernel.ShutdownCores(); kernel.ShutdownCores();
applet_manager.Reset();
services.reset(); services.reset();
service_manager.reset(); service_manager.reset();
fs_controller.Reset(); fs_controller.Reset();
@ -484,6 +452,9 @@ struct System::Impl {
room_member->SendGameInfo(game_info); room_member->SendGameInfo(game_info);
} }
// Reset all glue registrations
arp_manager.ResetAll();
LOG_DEBUG(Core, "Shutdown OK"); LOG_DEBUG(Core, "Shutdown OK");
} }
@ -501,31 +472,6 @@ struct System::Impl {
return app_loader->ReadTitle(out); return app_loader->ReadTitle(out);
} }
void AddGlueRegistrationForProcess(Loader::AppLoader& loader, Kernel::KProcess& 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.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) { void SetStatus(SystemResultStatus new_status, const char* details = nullptr) {
status = new_status; status = new_status;
if (details) { if (details) {

View File

@ -1170,6 +1170,7 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
// Determine if we are an application. // Determine if we are an application.
if (pool == KMemoryManager::Pool::Application) { if (pool == KMemoryManager::Pool::Application) {
flag |= Svc::CreateProcessFlag::IsApplication; flag |= Svc::CreateProcessFlag::IsApplication;
m_is_application = true;
} }
// If we are 64-bit, create as such. // If we are 64-bit, create as such.

View File

@ -267,13 +267,12 @@ void AppletManager::TerminateAndRemoveApplet(u64 aruid) {
} }
void AppletManager::CreateAndInsertByFrontendAppletParameters( void AppletManager::CreateAndInsertByFrontendAppletParameters(
u64 aruid, const FrontendAppletParameters& params) { std::unique_ptr<Process> process, const FrontendAppletParameters& params) {
// TODO: this should be run inside AM so that the events will have a parent process // TODO: this should be run inside AM so that the events will have a parent process
// TODO: have am create the guest process // TODO: have am create the guest process
auto applet = std::make_shared<Applet>(m_system, std::make_unique<Process>(m_system), auto applet = std::make_shared<Applet>(m_system, std::move(process),
params.applet_id == AppletId::Application); params.applet_id == AppletId::Application);
applet->aruid.pid = aruid;
applet->program_id = params.program_id; applet->program_id = params.program_id;
applet->applet_id = params.applet_id; applet->applet_id = params.applet_id;
applet->type = params.applet_type; applet->type = params.applet_type;
@ -329,6 +328,7 @@ void AppletManager::CreateAndInsertByFrontendAppletParameters(
// Applet was started by frontend, so it is foreground. // Applet was started by frontend, so it is foreground.
applet->lifecycle_manager.SetFocusState(FocusState::InFocus); applet->lifecycle_manager.SetFocusState(FocusState::InFocus);
applet->process->Run();
this->InsertApplet(std::move(applet)); this->InsertApplet(std::move(applet));
} }

View File

@ -12,6 +12,10 @@ namespace Core {
class System; class System;
} }
namespace Service {
class Process;
}
namespace Service::AM { namespace Service::AM {
enum class LaunchType { enum class LaunchType {
@ -36,7 +40,7 @@ public:
void InsertApplet(std::shared_ptr<Applet> applet); void InsertApplet(std::shared_ptr<Applet> applet);
void TerminateAndRemoveApplet(u64 aruid); void TerminateAndRemoveApplet(u64 aruid);
void CreateAndInsertByFrontendAppletParameters(u64 aruid, void CreateAndInsertByFrontendAppletParameters(std::unique_ptr<Process> process,
const FrontendAppletParameters& params); const FrontendAppletParameters& params);
std::shared_ptr<Applet> GetByAppletResourceUserId(u64 aruid) const; std::shared_ptr<Applet> GetByAppletResourceUserId(u64 aruid) const;

View File

@ -13,21 +13,21 @@ namespace Service::AM {
HidRegistration::HidRegistration(Core::System& system, Process& process) : m_process(process) { HidRegistration::HidRegistration(Core::System& system, Process& process) : m_process(process) {
m_hid_server = system.ServiceManager().GetService<HID::IHidServer>("hid"); m_hid_server = system.ServiceManager().GetService<HID::IHidServer>("hid");
if (m_process.IsInitialized()) { if (m_hid_server && m_process.IsInitialized()) {
m_hid_server->GetResourceManager()->RegisterAppletResourceUserId(m_process.GetProcessId(), m_hid_server->GetResourceManager()->RegisterAppletResourceUserId(m_process.GetProcessId(),
true); true);
} }
} }
HidRegistration::~HidRegistration() { HidRegistration::~HidRegistration() {
if (m_process.IsInitialized()) { if (m_hid_server && m_process.IsInitialized()) {
m_hid_server->GetResourceManager()->UnregisterAppletResourceUserId( m_hid_server->GetResourceManager()->UnregisterAppletResourceUserId(
m_process.GetProcessId()); m_process.GetProcessId());
} }
} }
void HidRegistration::EnableAppletToGetInput(bool enable) { 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); m_hid_server->GetResourceManager()->EnableInput(m_process.GetProcessId(), enable);
} }
} }

View File

@ -49,8 +49,7 @@ struct Memory::Impl {
void SetCurrentPageTable(Kernel::KProcess& process) { void SetCurrentPageTable(Kernel::KProcess& process) {
current_page_table = &process.GetPageTable().GetImpl(); current_page_table = &process.GetPageTable().GetImpl();
if (std::addressof(process) == system.ApplicationProcess() && if (process.IsApplication() && Settings::IsFastmemEnabled()) {
Settings::IsFastmemEnabled()) {
current_page_table->fastmem_arena = system.DeviceMemory().buffer.VirtualBasePointer(); current_page_table->fastmem_arena = system.DeviceMemory().buffer.VirtualBasePointer();
} else { } else {
current_page_table->fastmem_arena = nullptr; current_page_table->fastmem_arena = nullptr;