Skip to content
This repository has been archived by the owner on Oct 29, 2024. It is now read-only.

Implement plugin loader Mode3 mem strategy #7

Merged
merged 1 commit into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/core/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,18 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st
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();
if (memory_mode.second != Loader::ResultStatus::Success) {
LOG_CRITICAL(Core, "Failed to determine system mode (Error {})!",
Expand Down
12 changes: 6 additions & 6 deletions src/core/hle/service/apt/applet_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ Result AppletManager::PrepareToStartLibraryApplet(AppletId applet_id) {

if (Settings::values.lle_applets) {
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()));
if (process) {
return ResultSuccess;
Expand Down Expand Up @@ -603,7 +603,7 @@ Result AppletManager::PreloadLibraryApplet(AppletId applet_id) {

if (Settings::values.lle_applets) {
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()));
if (process) {
return ResultSuccess;
Expand Down Expand Up @@ -815,7 +815,7 @@ Result AppletManager::StartSystemApplet(AppletId applet_id, std::shared_ptr<Kern
applet_id == AppletId::HomeMenu ? AppletSlot::HomeMenu : AppletSlot::SystemApplet;
if (!GetAppletSlot(slot_id)->registered) {
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()));
if (!process) {
// TODO: Find the right error code.
Expand Down Expand Up @@ -1346,8 +1346,8 @@ Result AppletManager::StartApplication(const std::vector<u8>& parameter,
active_slot = AppletSlot::Application;

// Launch the title directly.
auto process =
NS::LaunchTitle(app_start_parameters->next_media_type, app_start_parameters->next_title_id);
auto process = NS::LaunchTitle(system, app_start_parameters->next_media_type,
app_start_parameters->next_title_id);
if (!process) {
LOG_CRITICAL(Service_APT, "Failed to launch title during application start, exiting.");
system.RequestShutdown();
Expand Down Expand Up @@ -1423,7 +1423,7 @@ void AppletManager::EnsureHomeMenuLoaded() {

auto cfg = Service::CFG::GetModule(system);
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) {
LOG_WARNING(Service_APT,
"The Home Menu failed to launch, application jumping will not work.");
Expand Down
14 changes: 13 additions & 1 deletion src/core/hle/service/apt/ns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

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);
auto loader = Loader::GetLoader(path);

Expand All @@ -18,6 +19,17 @@ std::shared_ptr<Kernel::Process> LaunchTitle(FS::MediaType media_type, u64 title
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;
Loader::ResultStatus result = loader->Load(process);

Expand Down
3 changes: 2 additions & 1 deletion src/core/hle/service/apt/ns.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ class System;
namespace Service::NS {

/// 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.
void RebootToTitle(Core::System& system, FS::MediaType media_type, u64 title_id);
Expand Down
5 changes: 4 additions & 1 deletion src/core/hle/service/plgldr/plgldr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,10 @@ void PLG_LDR::SetLoadSettings(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);

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>();

auto path = rp.PopMappedBuffer();
Expand Down
10 changes: 8 additions & 2 deletions src/core/hle/service/plgldr/plgldr.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,24 @@ namespace Service::PLGLDR {

class PLG_LDR final : public ServiceFramework<PLG_LDR> {
public:
enum class PluginMemoryStrategy : u8 {
PLG_STRATEGY_NONE = 2,
PLG_STRATEGY_SWAP = 0,
PLG_STRATEGY_MODE3 = 1,
};

struct PluginLoaderContext {
struct PluginLoadParameters {
u8 no_flash = 0;
u8 no_IR_Patch = 0;
PluginMemoryStrategy plugin_memory_strategy = PluginMemoryStrategy::PLG_STRATEGY_SWAP;
u32_le low_title_Id = 0;
char path[256] = {0};
u32_le config[32] = {0};

template <class Archive>
void serialize(Archive& ar, const unsigned int) {
ar& no_flash;
ar& no_IR_Patch;
ar& plugin_memory_strategy;
ar& low_title_Id;
ar& path;
ar& config;
Expand Down
12 changes: 12 additions & 0 deletions src/core/loader/loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,24 @@ class AppLoader : NonCopyable {
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.
* This function defaults to Dev1 (96MB allocated to the application) if it can't read the
* information.
* @returns A pair with the optional memory mode, and the status.
*/
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.
return std::make_pair(Kernel::MemoryMode::Dev1, ResultStatus::Success);
}
Expand Down Expand Up @@ -257,6 +268,7 @@ class AppLoader : NonCopyable {
Core::System& system;
FileUtil::IOFile file;
bool is_loaded = false;
std::optional<Kernel::MemoryMode> memory_mode_override = std::nullopt;
};

/**
Expand Down
5 changes: 4 additions & 1 deletion src/core/loader/ncch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ std::pair<std::optional<Kernel::MemoryMode>, ResultStatus> AppLoader_NCCH::LoadK
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.
auto& ncch_caps = overlay_ncch->exheader_header.arm11_system_local_caps;
Expand Down Expand Up @@ -159,7 +162,7 @@ ResultStatus AppLoader_NCCH::LoadExec(std::shared_ptr<Kernel::Process>& process)
// APPLICATION. See:
// https://github.com/LumaTeam/Luma3DS/blob/e2778a45/sysmodules/pm/source/launch.c#L237
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 bool is_new_3ds = Settings::values.is_new_3ds.GetValue();
if (is_new_3ds && n3ds_mode == Kernel::New3dsMemoryMode::Legacy &&
Expand Down