mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-14 17:30:05 +00:00
Implement plugin loader Mode3 mem strategy
This commit is contained in:
parent
f4768cd26c
commit
10f82aaa6e
@ -263,6 +263,18 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st
|
|||||||
return ResultStatus::ErrorGetLoader;
|
return ResultStatus::ErrorGetLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (restore_plugin_context.has_value() && restore_plugin_context->is_enabled &&
|
||||||
|
restore_plugin_context->use_user_load_parameters) {
|
||||||
|
u64_le program_id = 0;
|
||||||
|
app_loader->ReadProgramId(program_id);
|
||||||
|
if (restore_plugin_context->user_load_parameters.low_title_Id ==
|
||||||
|
static_cast<u32_le>(program_id) &&
|
||||||
|
restore_plugin_context->user_load_parameters.plugin_memory_strategy ==
|
||||||
|
Service::PLGLDR::PLG_LDR::PluginMemoryStrategy::PLG_STRATEGY_MODE3) {
|
||||||
|
app_loader->SetKernelMemoryModeOverride(Kernel::MemoryMode::Dev2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto memory_mode = app_loader->LoadKernelMemoryMode();
|
auto memory_mode = app_loader->LoadKernelMemoryMode();
|
||||||
if (memory_mode.second != Loader::ResultStatus::Success) {
|
if (memory_mode.second != Loader::ResultStatus::Success) {
|
||||||
LOG_CRITICAL(Core, "Failed to determine system mode (Error {})!",
|
LOG_CRITICAL(Core, "Failed to determine system mode (Error {})!",
|
||||||
|
@ -574,7 +574,7 @@ Result AppletManager::PrepareToStartLibraryApplet(AppletId applet_id) {
|
|||||||
|
|
||||||
if (Settings::values.lle_applets) {
|
if (Settings::values.lle_applets) {
|
||||||
auto cfg = Service::CFG::GetModule(system);
|
auto cfg = Service::CFG::GetModule(system);
|
||||||
auto process = NS::LaunchTitle(FS::MediaType::NAND,
|
auto process = NS::LaunchTitle(system, FS::MediaType::NAND,
|
||||||
GetTitleIdForApplet(applet_id, cfg->GetRegionValue()));
|
GetTitleIdForApplet(applet_id, cfg->GetRegionValue()));
|
||||||
if (process) {
|
if (process) {
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
@ -603,7 +603,7 @@ Result AppletManager::PreloadLibraryApplet(AppletId applet_id) {
|
|||||||
|
|
||||||
if (Settings::values.lle_applets) {
|
if (Settings::values.lle_applets) {
|
||||||
auto cfg = Service::CFG::GetModule(system);
|
auto cfg = Service::CFG::GetModule(system);
|
||||||
auto process = NS::LaunchTitle(FS::MediaType::NAND,
|
auto process = NS::LaunchTitle(system, FS::MediaType::NAND,
|
||||||
GetTitleIdForApplet(applet_id, cfg->GetRegionValue()));
|
GetTitleIdForApplet(applet_id, cfg->GetRegionValue()));
|
||||||
if (process) {
|
if (process) {
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
@ -815,7 +815,7 @@ Result AppletManager::StartSystemApplet(AppletId applet_id, std::shared_ptr<Kern
|
|||||||
applet_id == AppletId::HomeMenu ? AppletSlot::HomeMenu : AppletSlot::SystemApplet;
|
applet_id == AppletId::HomeMenu ? AppletSlot::HomeMenu : AppletSlot::SystemApplet;
|
||||||
if (!GetAppletSlot(slot_id)->registered) {
|
if (!GetAppletSlot(slot_id)->registered) {
|
||||||
auto cfg = Service::CFG::GetModule(system);
|
auto cfg = Service::CFG::GetModule(system);
|
||||||
auto process = NS::LaunchTitle(FS::MediaType::NAND,
|
auto process = NS::LaunchTitle(system, FS::MediaType::NAND,
|
||||||
GetTitleIdForApplet(applet_id, cfg->GetRegionValue()));
|
GetTitleIdForApplet(applet_id, cfg->GetRegionValue()));
|
||||||
if (!process) {
|
if (!process) {
|
||||||
// TODO: Find the right error code.
|
// TODO: Find the right error code.
|
||||||
@ -1346,8 +1346,8 @@ Result AppletManager::StartApplication(const std::vector<u8>& parameter,
|
|||||||
active_slot = AppletSlot::Application;
|
active_slot = AppletSlot::Application;
|
||||||
|
|
||||||
// Launch the title directly.
|
// Launch the title directly.
|
||||||
auto process =
|
auto process = NS::LaunchTitle(system, app_start_parameters->next_media_type,
|
||||||
NS::LaunchTitle(app_start_parameters->next_media_type, app_start_parameters->next_title_id);
|
app_start_parameters->next_title_id);
|
||||||
if (!process) {
|
if (!process) {
|
||||||
LOG_CRITICAL(Service_APT, "Failed to launch title during application start, exiting.");
|
LOG_CRITICAL(Service_APT, "Failed to launch title during application start, exiting.");
|
||||||
system.RequestShutdown();
|
system.RequestShutdown();
|
||||||
@ -1423,7 +1423,7 @@ void AppletManager::EnsureHomeMenuLoaded() {
|
|||||||
|
|
||||||
auto cfg = Service::CFG::GetModule(system);
|
auto cfg = Service::CFG::GetModule(system);
|
||||||
auto menu_title_id = GetTitleIdForApplet(AppletId::HomeMenu, cfg->GetRegionValue());
|
auto menu_title_id = GetTitleIdForApplet(AppletId::HomeMenu, cfg->GetRegionValue());
|
||||||
auto process = NS::LaunchTitle(FS::MediaType::NAND, menu_title_id);
|
auto process = NS::LaunchTitle(system, FS::MediaType::NAND, menu_title_id);
|
||||||
if (!process) {
|
if (!process) {
|
||||||
LOG_WARNING(Service_APT,
|
LOG_WARNING(Service_APT,
|
||||||
"The Home Menu failed to launch, application jumping will not work.");
|
"The Home Menu failed to launch, application jumping will not work.");
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
|
|
||||||
namespace Service::NS {
|
namespace Service::NS {
|
||||||
|
|
||||||
std::shared_ptr<Kernel::Process> LaunchTitle(FS::MediaType media_type, u64 title_id) {
|
std::shared_ptr<Kernel::Process> LaunchTitle(Core::System& system, FS::MediaType media_type,
|
||||||
|
u64 title_id) {
|
||||||
std::string path = AM::GetTitleContentPath(media_type, title_id);
|
std::string path = AM::GetTitleContentPath(media_type, title_id);
|
||||||
auto loader = Loader::GetLoader(path);
|
auto loader = Loader::GetLoader(path);
|
||||||
|
|
||||||
@ -18,6 +19,17 @@ std::shared_ptr<Kernel::Process> LaunchTitle(FS::MediaType media_type, u64 title
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto plg_ldr = Service::PLGLDR::GetService(system);
|
||||||
|
if (plg_ldr) {
|
||||||
|
const auto& plg_context = plg_ldr->GetPluginLoaderContext();
|
||||||
|
if (plg_context.is_enabled && plg_context.use_user_load_parameters &&
|
||||||
|
plg_context.user_load_parameters.low_title_Id == static_cast<u32>(title_id) &&
|
||||||
|
plg_context.user_load_parameters.plugin_memory_strategy ==
|
||||||
|
PLGLDR::PLG_LDR::PluginMemoryStrategy::PLG_STRATEGY_MODE3) {
|
||||||
|
loader->SetKernelMemoryModeOverride(Kernel::MemoryMode::Dev2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<Kernel::Process> process;
|
std::shared_ptr<Kernel::Process> process;
|
||||||
Loader::ResultStatus result = loader->Load(process);
|
Loader::ResultStatus result = loader->Load(process);
|
||||||
|
|
||||||
|
@ -16,7 +16,8 @@ class System;
|
|||||||
namespace Service::NS {
|
namespace Service::NS {
|
||||||
|
|
||||||
/// Loads and launches the title identified by title_id in the specified media type.
|
/// Loads and launches the title identified by title_id in the specified media type.
|
||||||
std::shared_ptr<Kernel::Process> LaunchTitle(FS::MediaType media_type, u64 title_id);
|
std::shared_ptr<Kernel::Process> LaunchTitle(Core::System& system, FS::MediaType media_type,
|
||||||
|
u64 title_id);
|
||||||
|
|
||||||
/// Reboots the system to the specified title.
|
/// Reboots the system to the specified title.
|
||||||
void RebootToTitle(Core::System& system, FS::MediaType media_type, u64 title_id);
|
void RebootToTitle(Core::System& system, FS::MediaType media_type, u64 title_id);
|
||||||
|
@ -204,7 +204,10 @@ void PLG_LDR::SetLoadSettings(Kernel::HLERequestContext& ctx) {
|
|||||||
IPC::RequestParser rp(ctx);
|
IPC::RequestParser rp(ctx);
|
||||||
|
|
||||||
plgldr_context.use_user_load_parameters = true;
|
plgldr_context.use_user_load_parameters = true;
|
||||||
plgldr_context.user_load_parameters.no_flash = rp.Pop<u32>() == 1;
|
u32_le flags = rp.Pop<u32>();
|
||||||
|
plgldr_context.user_load_parameters.no_flash = (flags & 1) == 1;
|
||||||
|
plgldr_context.user_load_parameters.plugin_memory_strategy =
|
||||||
|
static_cast<PluginMemoryStrategy>((flags >> 8) & 0xF);
|
||||||
plgldr_context.user_load_parameters.low_title_Id = rp.Pop<u32>();
|
plgldr_context.user_load_parameters.low_title_Id = rp.Pop<u32>();
|
||||||
|
|
||||||
auto path = rp.PopMappedBuffer();
|
auto path = rp.PopMappedBuffer();
|
||||||
|
@ -33,10 +33,16 @@ namespace Service::PLGLDR {
|
|||||||
|
|
||||||
class PLG_LDR final : public ServiceFramework<PLG_LDR> {
|
class PLG_LDR final : public ServiceFramework<PLG_LDR> {
|
||||||
public:
|
public:
|
||||||
|
enum class PluginMemoryStrategy : u8 {
|
||||||
|
PLG_STRATEGY_NONE = 2,
|
||||||
|
PLG_STRATEGY_SWAP = 0,
|
||||||
|
PLG_STRATEGY_MODE3 = 1,
|
||||||
|
};
|
||||||
|
|
||||||
struct PluginLoaderContext {
|
struct PluginLoaderContext {
|
||||||
struct PluginLoadParameters {
|
struct PluginLoadParameters {
|
||||||
u8 no_flash = 0;
|
u8 no_flash = 0;
|
||||||
u8 no_IR_Patch = 0;
|
PluginMemoryStrategy plugin_memory_strategy = PluginMemoryStrategy::PLG_STRATEGY_SWAP;
|
||||||
u32_le low_title_Id = 0;
|
u32_le low_title_Id = 0;
|
||||||
char path[256] = {0};
|
char path[256] = {0};
|
||||||
u32_le config[32] = {0};
|
u32_le config[32] = {0};
|
||||||
@ -44,7 +50,7 @@ public:
|
|||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive& ar, const unsigned int) {
|
void serialize(Archive& ar, const unsigned int) {
|
||||||
ar& no_flash;
|
ar& no_flash;
|
||||||
ar& no_IR_Patch;
|
ar& plugin_memory_strategy;
|
||||||
ar& low_title_Id;
|
ar& low_title_Id;
|
||||||
ar& path;
|
ar& path;
|
||||||
ar& config;
|
ar& config;
|
||||||
|
@ -117,6 +117,14 @@ public:
|
|||||||
return std::make_pair(0x2, ResultStatus::Success);
|
return std::make_pair(0x2, ResultStatus::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forces the application memory mode to the specified value,
|
||||||
|
* overriding the memory mode specified in the metadata.
|
||||||
|
*/
|
||||||
|
void SetKernelMemoryModeOverride(Kernel::MemoryMode mem_override) {
|
||||||
|
memory_mode_override = mem_override;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the memory mode that this application needs.
|
* Loads the memory mode that this application needs.
|
||||||
* This function defaults to Dev1 (96MB allocated to the application) if it can't read the
|
* This function defaults to Dev1 (96MB allocated to the application) if it can't read the
|
||||||
@ -124,6 +132,9 @@ public:
|
|||||||
* @returns A pair with the optional memory mode, and the status.
|
* @returns A pair with the optional memory mode, and the status.
|
||||||
*/
|
*/
|
||||||
virtual std::pair<std::optional<Kernel::MemoryMode>, ResultStatus> LoadKernelMemoryMode() {
|
virtual std::pair<std::optional<Kernel::MemoryMode>, ResultStatus> LoadKernelMemoryMode() {
|
||||||
|
if (memory_mode_override.has_value()) {
|
||||||
|
return std::make_pair(*memory_mode_override, ResultStatus::Success);
|
||||||
|
}
|
||||||
// 96MB allocated to the application.
|
// 96MB allocated to the application.
|
||||||
return std::make_pair(Kernel::MemoryMode::Dev1, ResultStatus::Success);
|
return std::make_pair(Kernel::MemoryMode::Dev1, ResultStatus::Success);
|
||||||
}
|
}
|
||||||
@ -257,6 +268,7 @@ protected:
|
|||||||
Core::System& system;
|
Core::System& system;
|
||||||
FileUtil::IOFile file;
|
FileUtil::IOFile file;
|
||||||
bool is_loaded = false;
|
bool is_loaded = false;
|
||||||
|
std::optional<Kernel::MemoryMode> memory_mode_override = std::nullopt;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,6 +69,9 @@ std::pair<std::optional<Kernel::MemoryMode>, ResultStatus> AppLoader_NCCH::LoadK
|
|||||||
return std::make_pair(std::nullopt, res);
|
return std::make_pair(std::nullopt, res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (memory_mode_override.has_value()) {
|
||||||
|
return std::make_pair(memory_mode_override, ResultStatus::Success);
|
||||||
|
}
|
||||||
|
|
||||||
// Provide the memory mode from the exheader.
|
// Provide the memory mode from the exheader.
|
||||||
auto& ncch_caps = overlay_ncch->exheader_header.arm11_system_local_caps;
|
auto& ncch_caps = overlay_ncch->exheader_header.arm11_system_local_caps;
|
||||||
@ -159,7 +162,7 @@ ResultStatus AppLoader_NCCH::LoadExec(std::shared_ptr<Kernel::Process>& process)
|
|||||||
// APPLICATION. See:
|
// APPLICATION. See:
|
||||||
// https://github.com/LumaTeam/Luma3DS/blob/e2778a45/sysmodules/pm/source/launch.c#L237
|
// https://github.com/LumaTeam/Luma3DS/blob/e2778a45/sysmodules/pm/source/launch.c#L237
|
||||||
auto& ncch_caps = overlay_ncch->exheader_header.arm11_system_local_caps;
|
auto& ncch_caps = overlay_ncch->exheader_header.arm11_system_local_caps;
|
||||||
const auto o3ds_mode = static_cast<Kernel::MemoryMode>(ncch_caps.system_mode.Value());
|
const auto o3ds_mode = *LoadKernelMemoryMode().first;
|
||||||
const auto n3ds_mode = static_cast<Kernel::New3dsMemoryMode>(ncch_caps.n3ds_mode);
|
const auto n3ds_mode = static_cast<Kernel::New3dsMemoryMode>(ncch_caps.n3ds_mode);
|
||||||
const bool is_new_3ds = Settings::values.is_new_3ds.GetValue();
|
const bool is_new_3ds = Settings::values.is_new_3ds.GetValue();
|
||||||
if (is_new_3ds && n3ds_mode == Kernel::New3dsMemoryMode::Legacy &&
|
if (is_new_3ds && n3ds_mode == Kernel::New3dsMemoryMode::Legacy &&
|
||||||
|
Loading…
Reference in New Issue
Block a user