From 619fbcaeaca377af1436ed0fad8a6370e8244a3c Mon Sep 17 00:00:00 2001 From: Malachi Date: Mon, 15 Sep 2025 12:33:26 -0400 Subject: [PATCH] Add a check for O3DS extended-memory ROMs in applet_manager.cpp to ensure reboot if necessary. --- src/core/hle/service/apt/applet_manager.cpp | 13 +++++++++++++ src/core/hle/service/apt/ns.cpp | 15 ++++++++++++++- src/core/hle/service/apt/ns.h | 6 +++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/apt/applet_manager.cpp b/src/core/hle/service/apt/applet_manager.cpp index 2d21f9ae8..7bad19d16 100644 --- a/src/core/hle/service/apt/applet_manager.cpp +++ b/src/core/hle/service/apt/applet_manager.cpp @@ -1349,6 +1349,19 @@ Result AppletManager::StartApplication(const std::vector& parameter, // PM::LaunchTitle. We should research more about that. ASSERT_MSG(app_start_parameters, "Trying to start an application without preparing it first."); + // Determine if the target title is an O3DS extended-memory title. + bool needs_extended_memory_reboot = NS::RequiresExtendedMemoryOld3DS( + app_start_parameters->next_media_type, app_start_parameters->next_title_id); + + if (needs_extended_memory_reboot) { + // For O3DS extended-memory titles, reboot to ensure a clean low-memory state to prevent + // hang/crash. + NS::RebootToTitle(system, app_start_parameters->next_media_type, + app_start_parameters->next_title_id); + app_start_parameters.reset(); + return ResultSuccess; + } + active_slot = AppletSlot::Application; // Launch the title directly. diff --git a/src/core/hle/service/apt/ns.cpp b/src/core/hle/service/apt/ns.cpp index c71c23419..8be5d9732 100644 --- a/src/core/hle/service/apt/ns.cpp +++ b/src/core/hle/service/apt/ns.cpp @@ -1,4 +1,4 @@ -// Copyright 2017 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -54,4 +54,17 @@ void RebootToTitle(Core::System& system, FS::MediaType media_type, u64 title_id) system.RequestReset(new_path); } +bool RequiresExtendedMemoryOld3DS(FS::MediaType media_type, u64 title_id) { + const std::string path = AM::GetTitleContentPath(media_type, title_id); + auto loader = Loader::GetLoader(path); + if (!loader) + return false; + + auto [mem_mode_opt, status] = loader->LoadKernelMemoryMode(); + if (status != Loader::ResultStatus::Success || !mem_mode_opt.has_value()) + return false; + + return (*mem_mode_opt != Kernel::MemoryMode::Prod); +} + } // namespace Service::NS diff --git a/src/core/hle/service/apt/ns.h b/src/core/hle/service/apt/ns.h index 8fa80e11b..feaad27c6 100644 --- a/src/core/hle/service/apt/ns.h +++ b/src/core/hle/service/apt/ns.h @@ -1,4 +1,4 @@ -// Copyright 2017 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -22,4 +22,8 @@ std::shared_ptr LaunchTitle(Core::System& system, FS::MediaType /// Reboots the system to the specified title. void RebootToTitle(Core::System& system, FS::MediaType media_type, u64 title_id); +/// Returns true if the specified title requires extended memory on Old 3DS +/// (i.e., its ExHeader system mode is not Prod/64MB). +bool RequiresExtendedMemoryOld3DS(FS::MediaType media_type, u64 title_id); + } // namespace Service::NS