diff --git a/src/android/app/src/main/java/org/citra/citra_emu/NativeLibrary.kt b/src/android/app/src/main/java/org/citra/citra_emu/NativeLibrary.kt index c6c97e762..75c97b101 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/NativeLibrary.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/NativeLibrary.kt @@ -272,6 +272,12 @@ object NativeLibrary { canContinue = false } + CoreError.ErrorN3DSApplication -> { + title = emulationActivity.getString(R.string.invalid_system_mode) + message = emulationActivity.getString(R.string.invalid_system_mode_message) + canContinue = false + } + CoreError.ErrorUnknown -> { title = emulationActivity.getString(R.string.fatal_error) message = emulationActivity.getString(R.string.fatal_error_message) @@ -729,6 +735,7 @@ object NativeLibrary { ErrorSystemFiles, ErrorSavestate, ErrorArticDisconnected, + ErrorN3DSApplication, ErrorUnknown } diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index a2880d6dc..e52c09a65 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -95,6 +95,7 @@ static jobject ToJavaCoreError(Core::System::ResultStatus result) { {Core::System::ResultStatus::ErrorSystemFiles, "ErrorSystemFiles"}, {Core::System::ResultStatus::ErrorSavestate, "ErrorSavestate"}, {Core::System::ResultStatus::ErrorArticDisconnected, "ErrorArticDisconnected"}, + {Core::System::ResultStatus::ErrorN3DSApplication, "ErrorN3DSApplication"}, {Core::System::ResultStatus::ErrorUnknown, "ErrorUnknown"}, }; diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 8d40452ee..d3e5d958d 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -559,6 +559,8 @@ Fatal Error A fatal error occurred. Check the log for details.\nContinuing emulation may result in crashes and bugs. Unsupported encrypted application + Invalid system mode + New 3DS exclusive applications cannot be loaded without enabling the New 3DS mode. Preparing Shaders diff --git a/src/citra_qt/citra_qt.cpp b/src/citra_qt/citra_qt.cpp index c15811f99..6398d1f22 100644 --- a/src/citra_qt/citra_qt.cpp +++ b/src/citra_qt/citra_qt.cpp @@ -1313,6 +1313,11 @@ bool GMainWindow::LoadROM(const QString& filename) { system.GetStatusDetails()) .c_str())); break; + case Core::System::ResultStatus::ErrorN3DSApplication: + QMessageBox::critical(this, tr("Invalid system mode"), + tr("New 3DS exclusive applications cannot be loaded without " + "enabling the New 3DS mode.")); + break; default: QMessageBox::critical( this, tr("Error while loading App!"), diff --git a/src/core/core.cpp b/src/core/core.cpp index ee338232d..e960571a7 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -27,6 +27,7 @@ #include "core/frontend/image_interface.h" #include "core/gdbstub/gdbstub.h" #include "core/global.h" +#include "core/hle/kernel/ipc_debugger/recorder.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/thread.h" @@ -317,49 +318,110 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st } } - auto memory_mode = app_loader->LoadKernelMemoryMode(); - if (memory_mode.second != Loader::ResultStatus::Success) { - LOG_CRITICAL(Core, "Failed to determine system mode (Error {})!", - static_cast(memory_mode.second)); + Kernel::MemoryMode app_mem_mode; + Kernel::MemoryMode system_mem_mode; + bool used_default_mem_mode = false; + Kernel::New3dsHwCapabilities app_n3ds_hw_capabilities; - switch (memory_mode.second) { - case Loader::ResultStatus::ErrorEncrypted: - return ResultStatus::ErrorLoader_ErrorEncrypted; - case Loader::ResultStatus::ErrorInvalidFormat: - return ResultStatus::ErrorLoader_ErrorInvalidFormat; - case Loader::ResultStatus::ErrorGbaTitle: - return ResultStatus::ErrorLoader_ErrorGbaTitle; - case Loader::ResultStatus::ErrorArtic: - return ResultStatus::ErrorArticDisconnected; - default: - return ResultStatus::ErrorSystemMode; + if (m_mem_mode) { + // Use memory mode set by the FIRM launch parameters + system_mem_mode = static_cast(m_mem_mode.value()); + m_mem_mode = {}; + } else { + // Use default memory mode based on the n3ds setting + system_mem_mode = Settings::values.is_new_3ds.GetValue() ? Kernel::MemoryMode::NewProd + : Kernel::MemoryMode::Prod; + used_default_mem_mode = true; + } + + { + auto memory_mode = app_loader->LoadKernelMemoryMode(); + if (memory_mode.second != Loader::ResultStatus::Success) { + LOG_CRITICAL(Core, "Failed to determine system mode (Error {})!", + static_cast(memory_mode.second)); + + switch (memory_mode.second) { + case Loader::ResultStatus::ErrorEncrypted: + return ResultStatus::ErrorLoader_ErrorEncrypted; + case Loader::ResultStatus::ErrorInvalidFormat: + return ResultStatus::ErrorLoader_ErrorInvalidFormat; + case Loader::ResultStatus::ErrorGbaTitle: + return ResultStatus::ErrorLoader_ErrorGbaTitle; + case Loader::ResultStatus::ErrorArtic: + return ResultStatus::ErrorArticDisconnected; + default: + return ResultStatus::ErrorSystemMode; + } + } + + ASSERT(memory_mode.first); + app_mem_mode = memory_mode.first.value(); + } + + auto n3ds_hw_caps = app_loader->LoadNew3dsHwCapabilities(); + ASSERT(n3ds_hw_caps.first); + app_n3ds_hw_capabilities = n3ds_hw_caps.first.value(); + + if (!Settings::values.is_new_3ds.GetValue() && + app_n3ds_hw_capabilities.memory_mode != Kernel::New3dsMemoryMode::Legacy) { + return ResultStatus::ErrorN3DSApplication; + } + + // If the default mem mode has been used, we do not come from a FIRM launch. On real HW + // however, the home menu is in charge or setting the proper memory mode when launching + // applications by doing a FIRM launch. Since we launch the application without going + // through the home menu, we need to emulate the FIRM launch having happened and set the + // proper memory mode. + if (used_default_mem_mode) { + + // If we are on the Old 3DS prod mode, the application is not a New 3DS application and + // the application memory mode does not match, we need to adjust it. We do not need + // adjustment if we are on the New 3DS prod mode, as that one overrides all the Old 3DS + // memory modes. + if (system_mem_mode == Kernel::MemoryMode::Prod && + app_n3ds_hw_capabilities.memory_mode == Kernel::New3dsMemoryMode::Legacy && + app_mem_mode != system_mem_mode) { + + system_mem_mode = app_mem_mode; + } + + // If we are on the New 3DS prod mode, and the application needs the New 3DS extended + // memory mode (only CTRAging is known to do this), adjust the memory mode. + else if (system_mem_mode == Kernel::MemoryMode::NewProd && + app_n3ds_hw_capabilities.memory_mode == Kernel::New3dsMemoryMode::NewDev1) { + + system_mem_mode = Kernel::MemoryMode::NewDev1; } } - ASSERT(memory_mode.first); - auto n3ds_hw_caps = app_loader->LoadNew3dsHwCapabilities(); - ASSERT(n3ds_hw_caps.first); u32 num_cores = 2; if (Settings::values.is_new_3ds) { num_cores = 4; } - ResultStatus init_result{ - Init(emu_window, secondary_window, *memory_mode.first, *n3ds_hw_caps.first, num_cores)}; + ResultStatus init_result{Init(emu_window, secondary_window, system_mem_mode, num_cores)}; if (init_result != ResultStatus::Success) { LOG_CRITICAL(Core, "Failed to initialize system (Error {})!", static_cast(init_result)); System::Shutdown(); return init_result; } + + kernel->UpdateCPUAndMemoryState(program_id, app_mem_mode, app_n3ds_hw_capabilities); + gpu->ReportLoadingProgramID(program_id); // Restore any parameters that should be carried through a reset. - if (restore_deliver_arg.has_value()) { - if (auto apt = Service::APT::GetModule(*this)) { + if (auto apt = Service::APT::GetModule(*this)) { + if (restore_deliver_arg.has_value()) { apt->GetAppletManager()->SetDeliverArg(restore_deliver_arg); + restore_deliver_arg.reset(); + } + if (restore_sys_menu_arg.has_value()) { + apt->GetAppletManager()->SetSysMenuArg(restore_sys_menu_arg.value()); + restore_sys_menu_arg.reset(); } - restore_deliver_arg.reset(); } + if (restore_plugin_context.has_value()) { if (auto plg_ldr = Service::PLGLDR::GetService(*this)) { plg_ldr->SetPluginLoaderContext(restore_plugin_context.value()); @@ -367,6 +429,10 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st restore_plugin_context.reset(); } + if (restore_ipc_recorder) { + kernel->RestoreIPCRecorder(std::move(restore_ipc_recorder)); + } + std::shared_ptr process; const Loader::ResultStatus load_result{app_loader->Load(process)}; if (Loader::ResultStatus::Success != load_result) { @@ -449,8 +515,7 @@ void System::Reschedule() { System::ResultStatus System::Init(Frontend::EmuWindow& emu_window, Frontend::EmuWindow* secondary_window, - Kernel::MemoryMode memory_mode, - const Kernel::New3dsHwCapabilities& n3ds_hw_caps, u32 num_cores) { + Kernel::MemoryMode memory_mode, u32 num_cores) { LOG_DEBUG(HW_Memory, "initialized OK"); memory = std::make_unique(*this); @@ -459,7 +524,7 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window, movie.GetOverrideBaseTicks()); kernel = std::make_unique( - *memory, *timing, [this] { PrepareReschedule(); }, memory_mode, num_cores, n3ds_hw_caps, + *memory, *timing, [this] { PrepareReschedule(); }, memory_mode, num_cores, movie.GetOverrideInitTime()); exclusive_monitor = MakeExclusiveMonitor(*memory, num_cores); @@ -678,11 +743,14 @@ void System::Reset() { // This is needed as we don't currently support proper app jumping. if (auto apt = Service::APT::GetModule(*this)) { restore_deliver_arg = apt->GetAppletManager()->ReceiveDeliverArg(); + restore_sys_menu_arg = apt->GetAppletManager()->GetSysMenuArg(); } if (auto plg_ldr = Service::PLGLDR::GetService(*this)) { restore_plugin_context = plg_ldr->GetPluginLoaderContext(); } + restore_ipc_recorder = std::move(kernel->BackupIPCRecorder()); + Shutdown(); if (!m_chainloadpath.empty()) { @@ -775,17 +843,19 @@ void System::serialize(Archive& ar, const unsigned int file_version) { } ar & lle_modules; + Kernel::MemoryMode mem_mode{}; + if (!Archive::is_loading::value) { + mem_mode = kernel->GetMemoryMode(); + } + ar & mem_mode; if (Archive::is_loading::value) { // When loading, we want to make sure any lingering state gets cleared out before we begin. // Shutdown, but persist a few things between loads... Shutdown(true); - // Re-initialize everything like it was before - auto memory_mode = this->app_loader->LoadKernelMemoryMode(); - auto n3ds_hw_caps = this->app_loader->LoadNew3dsHwCapabilities(); - [[maybe_unused]] const System::ResultStatus result = Init( - *m_emu_window, m_secondary_window, *memory_mode.first, *n3ds_hw_caps.first, num_cores); + [[maybe_unused]] const System::ResultStatus result = + Init(*m_emu_window, m_secondary_window, mem_mode, num_cores); } // Flush on save, don't flush on load diff --git a/src/core/core.h b/src/core/core.h index 4ed8ff326..122401eed 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -101,6 +101,7 @@ public: ErrorSystemFiles, ///< Error in finding system files ErrorSavestate, ///< Error saving or loading ErrorArticDisconnected, ///< Error when artic base disconnects + ErrorN3DSApplication, ///< Error launching New 3DS application in Old 3DS mode ShutdownRequested, ///< Emulated program requested a system shutdown ErrorUnknown ///< Any other error }; @@ -137,8 +138,9 @@ public: bool SendSignal(Signal signal, u32 param = 0); /// Request reset of the system - void RequestReset(const std::string& chainload = "") { + void RequestReset(const std::string& chainload = "", std::optional mem_mode = {}) { m_chainloadpath = chainload; + m_mem_mode = mem_mode; SendSignal(Signal::Reset); } @@ -386,9 +388,7 @@ private: */ [[nodiscard]] ResultStatus Init(Frontend::EmuWindow& emu_window, Frontend::EmuWindow* secondary_window, - Kernel::MemoryMode memory_mode, - const Kernel::New3dsHwCapabilities& n3ds_hw_caps, - u32 num_cores); + Kernel::MemoryMode memory_mode, u32 num_cores); /// Reschedule the core emulation void Reschedule(); @@ -463,6 +463,7 @@ private: Frontend::EmuWindow* m_secondary_window; std::string m_filepath; std::string m_chainloadpath; + std::optional m_mem_mode; u64 title_id; bool self_delete_pending; @@ -474,7 +475,9 @@ private: bool mic_permission_granted = false; boost::optional restore_deliver_arg; + boost::optional restore_sys_menu_arg; boost::optional restore_plugin_context; + std::unique_ptr restore_ipc_recorder; std::vector lle_modules; diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index c722b8e30..d49bcb2d1 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -26,14 +26,13 @@ namespace Kernel { /// Initialize the kernel KernelSystem::KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing, std::function prepare_reschedule_callback, - MemoryMode memory_mode, u32 num_cores, - const New3dsHwCapabilities& n3ds_hw_caps, u64 override_init_time) + MemoryMode memory_mode, u32 num_cores, u64 override_init_time) : memory(memory), timing(timing), - prepare_reschedule_callback(std::move(prepare_reschedule_callback)), memory_mode(memory_mode), - n3ds_hw_caps(n3ds_hw_caps) { + prepare_reschedule_callback(std::move(prepare_reschedule_callback)), + memory_mode(memory_mode) { std::generate(memory_regions.begin(), memory_regions.end(), [] { return std::make_shared(); }); - MemoryInit(memory_mode, n3ds_hw_caps.memory_mode, override_init_time); + MemoryInit(memory_mode, override_init_time); resource_limits = std::make_unique(*this); for (u32 core_id = 0; core_id < num_cores; ++core_id) { @@ -151,6 +150,14 @@ const IPCDebugger::Recorder& KernelSystem::GetIPCRecorder() const { return *ipc_recorder; } +std::unique_ptr KernelSystem::BackupIPCRecorder() { + return std::move(ipc_recorder); +} + +void KernelSystem::RestoreIPCRecorder(std::unique_ptr recorder) { + ipc_recorder = std::move(recorder); +} + void KernelSystem::AddNamedPort(std::string name, std::shared_ptr port) { named_ports.emplace(std::move(name), std::move(port)); } @@ -163,6 +170,35 @@ void KernelSystem::ResetThreadIDs() { next_thread_id = 0; } +void KernelSystem::UpdateCPUAndMemoryState(u64 title_id, MemoryMode memory_mode, + New3dsHwCapabilities n3ds_hw_cap) { + SetRunning804MHz(n3ds_hw_cap.enable_804MHz_cpu); + + u32 tid_high = static_cast(title_id >> 32); + + constexpr u32 TID_HIGH_APPLET = 0x00040030; + constexpr u32 TID_HIGH_SYSMODULE = 0x00040130; + + // PM only updates the reported memory for normal applications. + // TODO(PabloMK7): Using the title ID is not correct, but close enough. + if (tid_high != TID_HIGH_APPLET && tid_high != TID_HIGH_SYSMODULE) { + UpdateReportedMemory(memory_mode, n3ds_hw_cap.memory_mode); + } +} + +void KernelSystem::RestoreMemoryState(u64 title_id) { + u32 tid_high = static_cast(title_id >> 32); + + constexpr u32 TID_HIGH_APPLET = 0x00040030; + constexpr u32 TID_HIGH_SYSMODULE = 0x00040130; + + // PM only updates the reported memory for normal applications. + // TODO(PabloMK7): Using the title ID is not correct, but close enough. + if (tid_high != TID_HIGH_APPLET && tid_high != TID_HIGH_SYSMODULE) { + RestoreReportedMemory(); + } +} + template void KernelSystem::serialize(Archive& ar, const unsigned int) { ar & memory_regions; @@ -184,7 +220,7 @@ void KernelSystem::serialize(Archive& ar, const unsigned int) { ar & stored_processes; ar & next_thread_id; ar & memory_mode; - ar & n3ds_hw_caps; + ar & running_804MHz; ar & main_thread_extended_sleep; // Deliberately don't include debugger info to allow debugging through loads diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index d3b0bc53e..53d88cddf 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -111,6 +111,9 @@ enum class MemoryMode : u8 { Dev2 = 3, ///< 80MB app memory Dev3 = 4, ///< 72MB app memory Dev4 = 5, ///< 32MB app memory + + NewProd = 6, ///< 124MB app memory + NewDev1 = 7, ///< 178MB app memory }; /// New 3DS memory modes. @@ -137,8 +140,7 @@ class KernelSystem { public: explicit KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing, std::function prepare_reschedule_callback, MemoryMode memory_mode, - u32 num_cores, const New3dsHwCapabilities& n3ds_hw_caps, - u64 override_init_time = 0); + u32 num_cores, u64 override_init_time = 0); ~KernelSystem(); using PortPair = std::pair, std::shared_ptr>; @@ -305,6 +307,8 @@ public: IPCDebugger::Recorder& GetIPCRecorder(); const IPCDebugger::Recorder& GetIPCRecorder() const; + std::unique_ptr BackupIPCRecorder(); + void RestoreIPCRecorder(std::unique_ptr recorder); std::shared_ptr GetMemoryRegion(MemoryRegion region); @@ -327,8 +331,12 @@ public: return memory_mode; } - const New3dsHwCapabilities& GetNew3dsHwCapabilities() const { - return n3ds_hw_caps; + void SetRunning804MHz(bool enable) { + running_804MHz = enable; + } + + bool GetRunning804MHz() const { + return running_804MHz; } std::recursive_mutex& GetHLELock() { @@ -365,8 +373,16 @@ public: return pending_async_operations != 0; } + void UpdateCPUAndMemoryState(u64 title_id, MemoryMode memory_mode, + New3dsHwCapabilities n3ds_hw_cap); + + void RestoreMemoryState(u64 title_id); + private: - void MemoryInit(MemoryMode memory_mode, New3dsMemoryMode n3ds_mode, u64 override_init_time); + void MemoryInit(MemoryMode memory_mode, u64 override_init_time); + + void UpdateReportedMemory(MemoryMode memory_mode, New3dsMemoryMode n3ds_mode); + void RestoreReportedMemory(); std::function prepare_reschedule_callback; @@ -404,7 +420,7 @@ private: u32 next_thread_id; MemoryMode memory_mode; - New3dsHwCapabilities n3ds_hw_caps; + bool running_804MHz = false; /* * Synchronizes access to the internal HLE kernel structures, it is acquired when a guest diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp index fffa8dd6f..362e88ac5 100644 --- a/src/core/hle/kernel/memory.cpp +++ b/src/core/hle/kernel/memory.cpp @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -41,23 +41,9 @@ static const u32 memory_region_sizes[8][3] = { {0x0B200000, 0x02E00000, 0x02000000}, // 7 }; -void KernelSystem::MemoryInit(MemoryMode memory_mode, New3dsMemoryMode n3ds_mode, - u64 override_init_time) { +void KernelSystem::MemoryInit(MemoryMode memory_mode, u64 override_init_time) { const bool is_new_3ds = Settings::values.is_new_3ds.GetValue(); - u32 mem_type_index = static_cast(memory_mode); - u32 reported_mem_type = static_cast(memory_mode); - if (is_new_3ds) { - if (n3ds_mode == New3dsMemoryMode::NewProd || n3ds_mode == New3dsMemoryMode::NewDev2) { - mem_type_index = 6; - reported_mem_type = 6; - } else if (n3ds_mode == New3dsMemoryMode::NewDev1) { - mem_type_index = 7; - reported_mem_type = 7; - } else { - // On the N3ds, all O3ds configurations (<=5) are forced to 6 instead. - mem_type_index = 6; - } - } + const u32 mem_type_index = static_cast(memory_mode); // The kernel allocation regions (APPLICATION, SYSTEM and BASE) are laid out in sequence, with // the sizes specified in the memory_region_sizes table. @@ -73,14 +59,41 @@ void KernelSystem::MemoryInit(MemoryMode memory_mode, New3dsMemoryMode n3ds_mode config_mem_handler = std::make_shared(); auto& config_mem = config_mem_handler->GetConfigMem(); - config_mem.app_mem_type = reported_mem_type; - config_mem.app_mem_alloc = memory_region_sizes[reported_mem_type][0]; + config_mem.app_mem_type = static_cast(memory_mode); + config_mem.app_mem_alloc = memory_regions[0]->size; config_mem.sys_mem_alloc = memory_regions[1]->size; config_mem.base_mem_alloc = memory_regions[2]->size; shared_page_handler = std::make_shared(timing, override_init_time); } +void KernelSystem::UpdateReportedMemory(MemoryMode memory_mode, New3dsMemoryMode n3ds_mode) { + // If we are in New 3DS prod memory mode, and the application n3ds memory mode is set to legacy + // (all Old 3DS applications), then update reported available memory to the proper one according + // to the memory mode. + // This is normally done by PM when launching applications using svcSetResourceLimitLimitValues, + // but we do not implement that. + if (GetMemoryMode() == Kernel::MemoryMode::NewProd && + n3ds_mode == Kernel::New3dsMemoryMode::Legacy) { + const u32 mem_type_index = static_cast(memory_mode); + auto& config_mem = config_mem_handler->GetConfigMem(); + config_mem.app_mem_alloc = memory_region_sizes[mem_type_index][0]; + } +} + +void KernelSystem::RestoreReportedMemory() { + // If we are on New 3DS prod memory mode and we have terminated a process, restore the available + // memory to the proper size. + // This is normally done by PM when the application ends using svcSetResourceLimitLimitValues, + // but we do not implement that. + auto mem_mode = GetMemoryMode(); + if (mem_mode == Kernel::MemoryMode::NewProd) { + const u32 mem_type_index = static_cast(mem_mode); + auto& config_mem = config_mem_handler->GetConfigMem(); + config_mem.app_mem_alloc = memory_region_sizes[mem_type_index][0]; + } +} + std::shared_ptr KernelSystem::GetMemoryRegion(MemoryRegion region) { switch (region) { case MemoryRegion::APPLICATION: diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index e4200e5df..5e0d3810f 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -1,4 +1,4 @@ -// Copyright 2015 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -124,6 +124,8 @@ void KernelSystem::TerminateProcess(std::shared_ptr process) { GetThreadManager(core).TerminateProcessThreads(process); } + RestoreMemoryState(process->codeset->program_id); + process->Exit(); std::erase(process_list, process); } diff --git a/src/core/hle/service/apt/applet_manager.cpp b/src/core/hle/service/apt/applet_manager.cpp index 2d21f9ae8..47c0792c6 100644 --- a/src/core/hle/service/apt/applet_manager.cpp +++ b/src/core/hle/service/apt/applet_manager.cpp @@ -122,6 +122,37 @@ static u64 GetTitleIdForApplet(AppletId id, u32 region_value) { return itr->title_ids[region_value]; } +static constexpr std::size_t NumTitleIDConverts = 3; +static constexpr std::array, NumTitleIDConverts> TitleIDConvertTable = {{ + // MSET + {{0x0004001000020000, 0x0004001000021000, 0x0004001000022000, 0x0004001000020000, + 0x0004001000026000, 0x0004001000027000, 0x0004001000028000}}, + // eShop + {{0x0004001000020900, 0x0004001000021900, 0x0004001000022900, 0x0004001000020900, + 0x0004001000020900, 0x0004001000027900, 0x0004001000028900}}, + // NNID Settings + {{0x000400100002BF00, 0x000400100002C000, 0x000400100002C100, 0x000400100002BF00, + 0x000400100002BF00, 0x000400100002BF00, 0x000400100002BF00}}, +}}; + +static u64 ConvertTitleID(Core::System& system, u64 base_title_id) { + + auto cfg = Service::CFG::GetModule(system); + if (!cfg) { + return base_title_id; + } + + u32 region_value = cfg->GetRegionValue(false); + + for (auto& entry : TitleIDConvertTable) { + if (base_title_id == entry[0]) { + return entry[region_value]; + } + } + + return base_title_id; +} + static bool IsSystemAppletId(AppletId applet_id) { return (static_cast(applet_id) & static_cast(AppletId::AnySystemApplet)) != 0; } @@ -1013,6 +1044,22 @@ Result AppletManager::LeaveHomeMenu(std::shared_ptr object, return ResultSuccess; } +Result AppletManager::LoadSysMenuArg(std::vector& buffer) { + if (sys_menu_arg.has_value()) { + std::memcpy(buffer.data(), sys_menu_arg.value().data(), + std::min(buffer.size(), sys_menu_arg.value().size())); + } + // Always succeed, even if there is no data to copy. + return ResultSuccess; +} + +Result AppletManager::StoreSysMenuArg(const std::vector& buffer) { + sys_menu_arg = std::array(); + std::memcpy(sys_menu_arg.value().data(), buffer.data(), + std::min(buffer.size(), sys_menu_arg.value().size())); + return ResultSuccess; +} + Result AppletManager::OrderToCloseApplication() { if (active_slot == AppletSlot::Error) { return {ErrCodes::InvalidAppletSlot, ErrorModule::Applet, ErrorSummary::InvalidState, @@ -1213,8 +1260,8 @@ ApplicationRunningMode AppletManager::GetApplicationRunningMode() { // APT checks whether the system is a New 3DS and the 804MHz CPU speed is enabled to determine // the result. - auto new_3ds_mode = GetTargetPlatform() == TargetPlatform::New3ds && - system.Kernel().GetNew3dsHwCapabilities().enable_804MHz_cpu; + auto new_3ds_mode = + GetTargetPlatform() == TargetPlatform::New3ds && system.Kernel().GetRunning804MHz(); if (slot_data->registered) { return new_3ds_mode ? ApplicationRunningMode::New3dsRegistered : ApplicationRunningMode::Old3dsRegistered; @@ -1242,7 +1289,7 @@ Result AppletManager::PrepareToDoApplicationJump(u64 title_id, FS::MediaType med app_jump_parameters.next_title_id = app_jump_parameters.current_title_id; app_jump_parameters.next_media_type = app_jump_parameters.current_media_type; } else { - app_jump_parameters.next_title_id = title_id; + app_jump_parameters.next_title_id = ConvertTitleID(system, title_id); app_jump_parameters.next_media_type = media_type; } app_jump_parameters.flags = flags; @@ -1301,7 +1348,7 @@ Result AppletManager::DoApplicationJump(const DeliverArg& arg) { */ NS::RebootToTitle(system, app_jump_parameters.next_media_type, - app_jump_parameters.next_title_id); + app_jump_parameters.next_title_id, std::nullopt); return ResultSuccess; } } @@ -1320,6 +1367,53 @@ Result AppletManager::PrepareToStartApplication(u64 title_id, FS::MediaType medi ErrorLevel::Status}; } + title_id = ConvertTitleID(system, title_id); + + std::string path = AM::GetTitleContentPath(media_type, title_id); + auto loader = Loader::GetLoader(path); + + if (!loader) { + LOG_ERROR(Service_APT, "Could not find .app for title 0x{:016x}", title_id); + // TODO: Find proper error code + return ResultUnknown; + } + + 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(title_id) && + plg_context.user_load_parameters.plugin_memory_strategy == + PLGLDR::PLG_LDR::PluginMemoryStrategy::PLG_STRATEGY_MODE3) { + loader->SetKernelMemoryModeOverride(Kernel::MemoryMode::Dev2); + } + } + + auto mem_mode = loader->LoadKernelMemoryMode(); + if (mem_mode.second != Loader::ResultStatus::Success || !mem_mode.first.has_value()) { + // This cannot happen on real HW at this point of execution + LOG_ERROR(Service_APT, "Could not determine memory mode"); + return ResultUnknown; + } + + auto curr_mem_mode = system.Kernel().GetMemoryMode(); + + if (mem_mode.first.value() != curr_mem_mode) { + if (system.Kernel().GetMemoryMode() == Kernel::MemoryMode::NewProd) { + // On New 3DS prod memory mode, only incorrect state is if the app + // reports having the "unused" memory mode 1. TODO: Figure out + // how this works and if it is even used. + if (mem_mode.first.value() == static_cast(1)) { + return {ErrCodes::IncorrectMemoryMode, ErrorModule::Applet, + ErrorSummary::InvalidState, ErrorLevel::Status}; + } + } else { + // On other memory modes, the state is incorrect. + return {ErrCodes::IncorrectMemoryMode, ErrorModule::Applet, ErrorSummary::InvalidState, + ErrorLevel::Status}; + } + } + ASSERT_MSG(!app_start_parameters, "Trying to prepare an application when another is already prepared"); @@ -1403,6 +1497,44 @@ Result AppletManager::CancelApplication() { return ResultSuccess; } +Result AppletManager::PrepareToStartNewestHomeMenu() { + if (active_slot == AppletSlot::Error || + GetAppletSlot(active_slot)->attributes.applet_pos != AppletPos::System) { + return {ErrCodes::InvalidAppletSlot, ErrorModule::Applet, ErrorSummary::InvalidState, + ErrorLevel::Status}; + } + + bool is_standard; + if (Settings::values.is_new_3ds) { + // Memory layout is standard if it is not NewDev1 (178MB) + is_standard = system.Kernel().GetMemoryMode() != Kernel::MemoryMode::NewDev1; + } else { + // Memory layout is standard if it is Prod (64MB) + is_standard = system.Kernel().GetMemoryMode() == Kernel::MemoryMode::Prod; + } + + if (is_standard) { + return Result{ErrorDescription::AlreadyExists, ErrorModule::Applet, + ErrorSummary::InvalidState, ErrorLevel::Status}; + } + + home_menu_tid_to_start = GetAppletSlot(active_slot)->title_id; + return ResultSuccess; +} + +Result AppletManager::StartNewestHomeMenu() { + if (!home_menu_tid_to_start) { + return Result{ErrorDescription::AlreadyExists, ErrorModule::Applet, + ErrorSummary::InvalidState, ErrorLevel::Status}; + } + + u64 titleID = home_menu_tid_to_start; + home_menu_tid_to_start = 0; + + NS::RebootToTitle(system, Service::FS::MediaType::NAND, titleID, std::nullopt); + return ResultSuccess; +} + void AppletManager::SendApplicationParameterAfterRegistration(const MessageParameter& parameter) { auto slot = GetAppletSlotFromId(parameter.destination_id); diff --git a/src/core/hle/service/apt/applet_manager.h b/src/core/hle/service/apt/applet_manager.h index 5aaf7fdac..d4d99895b 100644 --- a/src/core/hle/service/apt/applet_manager.h +++ b/src/core/hle/service/apt/applet_manager.h @@ -1,4 +1,4 @@ -// Copyright 2018 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -118,6 +118,8 @@ enum class ApplicationRunningMode : u8 { New3dsUnregistered = 4, }; +constexpr std::size_t SysMenuArgSize = 0x40; + /// Holds information about the parameters used in Send/Glance/ReceiveParameter struct MessageParameter { AppletId sender_id = AppletId::None; @@ -180,6 +182,8 @@ private: friend class boost::serialization::access; }; +using SysMenuArg = std::array; + struct ApplicationJumpParameters { u64 next_title_id; FS::MediaType next_media_type; @@ -322,6 +326,16 @@ public: Result PrepareToLeaveHomeMenu(); Result LeaveHomeMenu(std::shared_ptr object, const std::vector& buffer); + Result LoadSysMenuArg(std::vector& buffer); + Result StoreSysMenuArg(const std::vector& buffer); + + boost::optional GetSysMenuArg() { + return sys_menu_arg; + } + void SetSysMenuArg(const SysMenuArg& arg) { + sys_menu_arg = arg; + } + Result OrderToCloseApplication(); Result PrepareToCloseApplication(bool return_to_sys); Result CloseApplication(std::shared_ptr object, const std::vector& buffer); @@ -376,6 +390,9 @@ public: Result WakeupApplication(std::shared_ptr object, const std::vector& buffer); Result CancelApplication(); + Result PrepareToStartNewestHomeMenu(); + Result StartNewestHomeMenu(); + struct AppletManInfo { AppletPos active_applet_pos; AppletId requested_applet_id; @@ -417,6 +434,8 @@ private: ApplicationJumpParameters app_jump_parameters{}; boost::optional app_start_parameters{}; boost::optional deliver_arg{}; + boost::optional sys_menu_arg{}; + u64 home_menu_tid_to_start{}; boost::optional capture_info; boost::optional capture_buffer_info; @@ -532,6 +551,8 @@ private: ar & delayed_parameter; ar & app_start_parameters; ar & deliver_arg; + ar & sys_menu_arg; + ar & home_menu_tid_to_start; ar & capture_info; ar & capture_buffer_info; ar & active_slot; diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 002bd3728..8e34bb0b7 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -92,16 +92,15 @@ void Module::NSInterface::RebootSystem(Kernel::HLERequestContext& ctx) { const auto title_id = rp.Pop(); const auto media_type = static_cast(rp.Pop()); rp.Skip(1, false); // Skip padding - // TODO: Utilize requested memory type. const auto mem_type = rp.Pop(); LOG_WARNING(Service_APT, "called launch_title={}, title_id={:016X}, media_type={:02X}, mem_type={:02X}", launch_title, title_id, media_type, mem_type); - // TODO: Handle mem type. if (launch_title) { - NS::RebootToTitle(apt->system, media_type, title_id); + NS::RebootToTitle(apt->system, media_type, title_id, + static_cast(mem_type)); } else { apt->system.RequestReset(); } @@ -763,16 +762,12 @@ void Module::APTInterface::PrepareToStartSystemApplet(Kernel::HLERequestContext& void Module::APTInterface::PrepareToStartNewestHomeMenu(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx); + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); LOG_DEBUG(Service_APT, "called"); - // TODO(Subv): This command can only be called by a System Applet (return 0xC8A0CC04 otherwise). - - // This command must return an error when called, otherwise the Home Menu will try to reboot the - // system. - rb.Push(Result(ErrorDescription::AlreadyExists, ErrorModule::Applet, ErrorSummary::InvalidState, - ErrorLevel::Status)); + rb.Push(apt->applet_manager->PrepareToStartNewestHomeMenu()); } void Module::APTInterface::PreloadLibraryApplet(Kernel::HLERequestContext& ctx) { @@ -821,6 +816,19 @@ void Module::APTInterface::StartSystemApplet(Kernel::HLERequestContext& ctx) { rb.Push(apt->applet_manager->StartSystemApplet(applet_id, object, buffer)); } +void Module::APTInterface::StartNewestHomeMenu(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx); + + const auto buffer_size = rp.Pop(); + [[maybe_unused]] const auto object = rp.PopGenericObject(); + [[maybe_unused]] const auto buffer = rp.PopStaticBuffer(); + + LOG_DEBUG(Service_APT, "called, size={:08X}", buffer_size); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(apt->applet_manager->StartNewestHomeMenu()); +} + void Module::APTInterface::OrderToCloseApplication(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx); @@ -1011,10 +1019,10 @@ void Module::APTInterface::LoadSysMenuArg(Kernel::HLERequestContext& ctx) { // This service function does not clear the buffer. std::vector buffer(size); - std::copy_n(apt->sys_menu_arg_buffer.cbegin(), size, buffer.begin()); + Result res = apt->applet_manager->LoadSysMenuArg(buffer); IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); - rb.Push(ResultSuccess); + rb.Push(res); rb.PushStaticBuffer(std::move(buffer), 0); } @@ -1026,10 +1034,10 @@ void Module::APTInterface::StoreSysMenuArg(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_APT, "called"); ASSERT_MSG(buffer.size() >= size, "Buffer too small to hold requested data"); - std::copy_n(buffer.cbegin(), size, apt->sys_menu_arg_buffer.begin()); + Result res = apt->applet_manager->StoreSysMenuArg(buffer); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(ResultSuccess); + rb.Push(res); } void Module::APTInterface::SendCaptureBufferInfo(Kernel::HLERequestContext& ctx) { @@ -1365,8 +1373,8 @@ void Module::APTInterface::Reboot(Kernel::HLERequestContext& ctx) { "called title_id={:016X}, media_type={:02X}, mem_type={:02X}, firm_tid_low={:08X}", title_id, media_type, mem_type, firm_tid_low); - // TODO: Handle mem type and FIRM TID low. - NS::RebootToTitle(apt->system, media_type, title_id); + // TODO: Handle FIRM TID low. + NS::RebootToTitle(apt->system, media_type, title_id, static_cast(mem_type)); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); rb.Push(ResultSuccess); @@ -1420,8 +1428,7 @@ void Module::APTInterface::IsStandardMemoryLayout(Kernel::HLERequestContext& ctx bool is_standard; if (Settings::values.is_new_3ds) { // Memory layout is standard if it is not NewDev1 (178MB) - is_standard = apt->system.Kernel().GetNew3dsHwCapabilities().memory_mode != - Kernel::New3dsMemoryMode::NewDev1; + is_standard = apt->system.Kernel().GetMemoryMode() != Kernel::MemoryMode::NewDev1; } else { // Memory layout is standard if it is Prod (64MB) is_standard = apt->system.Kernel().GetMemoryMode() == Kernel::MemoryMode::Prod; diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index 8e20a788b..9676a94f0 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h @@ -1,4 +1,4 @@ -// Copyright 2015 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -31,8 +31,6 @@ class AppletManager; /// Each APT service can only have up to 2 sessions connected at the same time. static const u32 MaxAPTSessions = 2; -constexpr std::size_t SysMenuArgSize = 0x40; - enum class StartupArgumentType : u32 { OtherApp = 0, Restart = 1, @@ -547,6 +545,21 @@ public: */ void StartSystemApplet(Kernel::HLERequestContext& ctx); + /** + * APT::StartNewestHomeMenu service function + * Inputs: + * 0 : Command header [0x00200044] + * 1 : Partameters size + * 2 : 0x0 + * 3 : Handle parameter + * 4 : (Parameters Size << 14) | 2 + * 5 : void*, Parameters + * Outputs: + * 0 : Return header + * 1 : Result of function, 0 on success, otherwise error code + */ + void StartNewestHomeMenu(Kernel::HLERequestContext& ctx); + /** * APT::OrderToCloseApplication service function * Inputs: @@ -1073,8 +1086,6 @@ private: u32 cpu_percent = 0; ///< CPU time available to the running application - std::array sys_menu_arg_buffer; - ScreencapPostPermission screen_capture_post_permission = ScreencapPostPermission::CleanThePermission; // TODO(JamePeng): verify the initial value diff --git a/src/core/hle/service/apt/apt_a.cpp b/src/core/hle/service/apt/apt_a.cpp index dc4c72c90..9de07a57d 100644 --- a/src/core/hle/service/apt/apt_a.cpp +++ b/src/core/hle/service/apt/apt_a.cpp @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -42,7 +42,7 @@ APT_A::APT_A(std::shared_ptr apt) {0x001D, &APT_A::CancelApplication, "CancelApplication"}, {0x001E, &APT_A::StartLibraryApplet, "StartLibraryApplet"}, {0x001F, &APT_A::StartSystemApplet, "StartSystemApplet"}, - {0x0020, nullptr, "StartNewestHomeMenu"}, + {0x0020, &APT_A::StartNewestHomeMenu, "StartNewestHomeMenu"}, {0x0021, &APT_A::OrderToCloseApplication, "OrderToCloseApplication"}, {0x0022, &APT_A::PrepareToCloseApplication, "PrepareToCloseApplication"}, {0x0023, nullptr, "PrepareToJumpToApplication"}, diff --git a/src/core/hle/service/apt/apt_s.cpp b/src/core/hle/service/apt/apt_s.cpp index 9bd6d81ed..a332cebf6 100644 --- a/src/core/hle/service/apt/apt_s.cpp +++ b/src/core/hle/service/apt/apt_s.cpp @@ -1,4 +1,4 @@ -// Copyright 2015 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -42,7 +42,7 @@ APT_S::APT_S(std::shared_ptr apt) {0x001D, &APT_S::CancelApplication, "CancelApplication"}, {0x001E, &APT_S::StartLibraryApplet, "StartLibraryApplet"}, {0x001F, &APT_S::StartSystemApplet, "StartSystemApplet"}, - {0x0020, nullptr, "StartNewestHomeMenu"}, + {0x0020, &APT_S::StartNewestHomeMenu, "StartNewestHomeMenu"}, {0x0021, &APT_S::OrderToCloseApplication, "OrderToCloseApplication"}, {0x0022, &APT_S::PrepareToCloseApplication, "PrepareToCloseApplication"}, {0x0023, nullptr, "PrepareToJumpToApplication"}, diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp index fd302ab4e..8e1fd18c6 100644 --- a/src/core/hle/service/apt/apt_u.cpp +++ b/src/core/hle/service/apt/apt_u.cpp @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -42,7 +42,7 @@ APT_U::APT_U(std::shared_ptr apt) {0x001D, &APT_U::CancelApplication, "CancelApplication"}, {0x001E, &APT_U::StartLibraryApplet, "StartLibraryApplet"}, {0x001F, &APT_U::StartSystemApplet, "StartSystemApplet"}, - {0x0020, nullptr, "StartNewestHomeMenu"}, + {0x0020, &APT_U::StartNewestHomeMenu, "StartNewestHomeMenu"}, {0x0021, &APT_U::OrderToCloseApplication, "OrderToCloseApplication"}, {0x0022, &APT_U::PrepareToCloseApplication, "PrepareToCloseApplication"}, {0x0023, nullptr, "PrepareToJumpToApplication"}, diff --git a/src/core/hle/service/apt/errors.h b/src/core/hle/service/apt/errors.h index 25bffb9af..4de973906 100644 --- a/src/core/hle/service/apt/errors.h +++ b/src/core/hle/service/apt/errors.h @@ -1,4 +1,4 @@ -// Copyright 2018 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -8,6 +8,7 @@ namespace Service::APT::ErrCodes { enum { ParameterPresent = 2, InvalidAppletSlot = 4, + IncorrectMemoryMode = 5, AppNotRunning = 11, }; } // namespace Service::APT::ErrCodes diff --git a/src/core/hle/service/apt/ns.cpp b/src/core/hle/service/apt/ns.cpp index c71c23419..785b83198 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. @@ -30,6 +30,23 @@ std::shared_ptr LaunchTitle(Core::System& system, FS::MediaType } } + { + // This is normally done by PM, but we don't emulate it + // so we do it here instead. + auto mem_mode_res = loader->LoadKernelMemoryMode(); + Kernel::MemoryMode mem_mode{}; + auto n3ds_cap_res = loader->LoadNew3dsHwCapabilities(); + Kernel::New3dsHwCapabilities n3ds_hw_cap{}; + + if (mem_mode_res.second == Loader::ResultStatus::Success && mem_mode_res.first) { + mem_mode = mem_mode_res.first.value(); + } + if (n3ds_cap_res.second == Loader::ResultStatus::Success && n3ds_cap_res.first) { + n3ds_hw_cap = n3ds_cap_res.first.value(); + } + system.Kernel().UpdateCPUAndMemoryState(title_id, mem_mode, n3ds_hw_cap); + } + std::shared_ptr process; Loader::ResultStatus result = loader->Load(process); @@ -41,7 +58,8 @@ std::shared_ptr LaunchTitle(Core::System& system, FS::MediaType return process; } -void RebootToTitle(Core::System& system, FS::MediaType media_type, u64 title_id) { +void RebootToTitle(Core::System& system, FS::MediaType media_type, u64 title_id, + std::optional mem_mode) { auto new_path = AM::GetTitleContentPath(media_type, title_id); if (new_path.empty() || !FileUtil::Exists(new_path)) { // TODO: This can happen if the requested title is not installed. Need a way to find @@ -51,7 +69,12 @@ void RebootToTitle(Core::System& system, FS::MediaType media_type, u64 title_id) new_path); new_path.clear(); } - system.RequestReset(new_path); + + std::optional mem_mode_u8; + if (mem_mode) { + mem_mode_u8 = static_cast(mem_mode.value()); + } + system.RequestReset(new_path, mem_mode_u8); } } // namespace Service::NS diff --git a/src/core/hle/service/apt/ns.h b/src/core/hle/service/apt/ns.h index 8fa80e11b..2a7dda254 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. @@ -20,6 +20,7 @@ std::shared_ptr LaunchTitle(Core::System& system, FS::MediaType u64 title_id); /// 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, + std::optional mem_mode); } // namespace Service::NS diff --git a/src/tests/audio_core/hle/hle.cpp b/src/tests/audio_core/hle/hle.cpp index 09e7ec5ab..9c4396973 100644 --- a/src/tests/audio_core/hle/hle.cpp +++ b/src/tests/audio_core/hle/hle.cpp @@ -1,4 +1,4 @@ -// Copyright 2023 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,8 +22,7 @@ TEST_CASE("DSP LLE vs HLE", "[audio_core][hle]") { Memory::MemorySystem lle_memory{system}; Core::Timing lle_core_timing(1, 100); Kernel::KernelSystem lle_kernel( - lle_memory, lle_core_timing, [] {}, Kernel::MemoryMode::Prod, 1, - Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy}); + lle_memory, lle_core_timing, [] {}, Kernel::MemoryMode::NewProd, 1); AudioCore::DspHle hle(system, hle_memory, hle_core_timing); AudioCore::DspLle lle(system, lle_memory, lle_core_timing, true); diff --git a/src/tests/core/hle/kernel/hle_ipc.cpp b/src/tests/core/hle/kernel/hle_ipc.cpp index f908e5f2c..372ea563f 100644 --- a/src/tests/core/hle/kernel/hle_ipc.cpp +++ b/src/tests/core/hle/kernel/hle_ipc.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. @@ -23,9 +23,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel Core::Timing timing(1, 100); Core::System system; Memory::MemorySystem memory{system}; - Kernel::KernelSystem kernel( - memory, timing, [] {}, Kernel::MemoryMode::Prod, 1, - Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy}); + Kernel::KernelSystem kernel(memory, timing, [] {}, Kernel::MemoryMode::NewProd, 1); auto [server, client] = kernel.CreateSessionPair(); HLERequestContext context(kernel, std::move(server), nullptr); @@ -256,9 +254,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { Core::Timing timing(1, 100); Core::System system; Memory::MemorySystem memory{system}; - Kernel::KernelSystem kernel( - memory, timing, [] {}, Kernel::MemoryMode::Prod, 1, - Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy}); + Kernel::KernelSystem kernel(memory, timing, [] {}, Kernel::MemoryMode::NewProd, 1); auto [server, client] = kernel.CreateSessionPair(); HLERequestContext context(kernel, std::move(server), nullptr); diff --git a/src/tests/core/memory/memory.cpp b/src/tests/core/memory/memory.cpp index 597ac5132..6254c3b0d 100644 --- a/src/tests/core/memory/memory.cpp +++ b/src/tests/core/memory/memory.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. @@ -12,9 +12,7 @@ TEST_CASE("memory.IsValidVirtualAddress", "[core][memory]") { Core::Timing timing(1, 100); Core::System system; Memory::MemorySystem memory{system}; - Kernel::KernelSystem kernel( - memory, timing, [] {}, Kernel::MemoryMode::Prod, 1, - Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy}); + Kernel::KernelSystem kernel(memory, timing, [] {}, Kernel::MemoryMode::NewProd, 1); SECTION("these regions should not be mapped on an empty process") { auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0)); CHECK(memory.IsValidVirtualAddress(*process, Memory::PROCESS_IMAGE_VADDR) == false); diff --git a/src/tests/core/memory/vm_manager.cpp b/src/tests/core/memory/vm_manager.cpp index f58ad2e5b..c15760d8a 100644 --- a/src/tests/core/memory/vm_manager.cpp +++ b/src/tests/core/memory/vm_manager.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. @@ -16,9 +16,7 @@ TEST_CASE("Memory Basics", "[kernel][memory]") { Core::Timing timing(1, 100); Core::System system; Memory::MemorySystem memory{system}; - Kernel::KernelSystem kernel( - memory, timing, [] {}, Kernel::MemoryMode::Prod, 1, - Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy}); + Kernel::KernelSystem kernel(memory, timing, [] {}, Kernel::MemoryMode::NewProd, 1); Kernel::Process process(kernel); SECTION("mapping memory") { // Because of the PageTable, Kernel::VMManager is too big to be created on the stack.