diff --git a/src/android/app/src/main/jni/game_info.cpp b/src/android/app/src/main/jni/game_info.cpp index 99ebfd3ae..ebf61820a 100644 --- a/src/android/app/src/main/jni/game_info.cpp +++ b/src/android/app/src/main/jni/game_info.cpp @@ -222,7 +222,7 @@ jboolean Java_org_citra_citra_1emu_model_GameInfo_getIsVisibleSystemTitle(JNIEnv return false; } - return smdh->flags & Loader::SMDH::Flags::Visible; + return smdh->flags.visible; } jstring Java_org_citra_citra_1emu_model_GameInfo_getFileType(JNIEnv* env, jobject obj) { diff --git a/src/citra_qt/game_list_worker.cpp b/src/citra_qt/game_list_worker.cpp index b6376261f..7e5c4650f 100644 --- a/src/citra_qt/game_list_worker.cpp +++ b/src/citra_qt/game_list_worker.cpp @@ -92,7 +92,7 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign if (Loader::IsValidSMDH(smdh)) { if (system_title) { auto smdh_struct = reinterpret_cast(smdh.data()); - if (!(smdh_struct->flags & Loader::SMDH::Flags::Visible)) { + if (!smdh_struct->flags.visible) { // Skip system titles without the visible flag. return true; } diff --git a/src/core/core.cpp b/src/core/core.cpp index e960571a7..d00de677c 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -362,8 +362,7 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st 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) { + if (!Settings::values.is_new_3ds.GetValue() && app_loader->IsN3DSExclusive()) { return ResultStatus::ErrorN3DSApplication; } @@ -374,14 +373,10 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st // 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) { - + // If we are on the Old 3DS prod mode 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_mem_mode != system_mem_mode) { system_mem_mode = app_mem_mode; } @@ -389,7 +384,6 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st // 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; } } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index d49bcb2d1..21ca655db 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -7,6 +7,7 @@ #include #include "common/archives.h" #include "common/serialization/atomic.h" +#include "common/settings.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/config_mem.h" #include "core/hle/kernel/handle_table.h" @@ -172,7 +173,9 @@ void KernelSystem::ResetThreadIDs() { void KernelSystem::UpdateCPUAndMemoryState(u64 title_id, MemoryMode memory_mode, New3dsHwCapabilities n3ds_hw_cap) { - SetRunning804MHz(n3ds_hw_cap.enable_804MHz_cpu); + if (Settings::values.is_new_3ds) { + SetRunning804MHz(n3ds_hw_cap.enable_804MHz_cpu); + } u32 tid_high = static_cast(title_id >> 32); diff --git a/src/core/loader/artic.cpp b/src/core/loader/artic.cpp index 30f62dc57..9c7aefbeb 100644 --- a/src/core/loader/artic.cpp +++ b/src/core/loader/artic.cpp @@ -134,6 +134,16 @@ Apploader_Artic::LoadNew3dsHwCapabilities() { return std::make_pair(std::move(caps), ResultStatus::Success); } +bool Apploader_Artic::IsN3DSExclusive() { + std::vector smdh_buffer; + if (ReadIcon(smdh_buffer) == ResultStatus::Success && IsValidSMDH(smdh_buffer)) { + SMDH* smdh = reinterpret_cast(smdh_buffer.data()); + return smdh->flags.n3ds_exclusive != 0; + } + + return false; +} + ResultStatus Apploader_Artic::LoadExec(std::shared_ptr& process) { if (!is_loaded) diff --git a/src/core/loader/artic.h b/src/core/loader/artic.h index 13b92c189..a6de6e0fd 100644 --- a/src/core/loader/artic.h +++ b/src/core/loader/artic.h @@ -56,6 +56,8 @@ public: std::pair, ResultStatus> LoadNew3dsHwCapabilities() override; + bool IsN3DSExclusive() override; + ResultStatus IsExecutable(bool& out_executable) override; ResultStatus ReadCode(std::vector& buffer) override; diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index 2c5ef952f..392b6025d 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -163,6 +163,10 @@ public: ResultStatus::Success); } + virtual bool IsN3DSExclusive() { + return false; + } + /** * Get whether this application is executable. * @param out_executable Reference to store the executable flag into. diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index ef33c42d3..0b2058293 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -125,6 +125,23 @@ AppLoader_NCCH::LoadNew3dsHwCapabilities() { return std::make_pair(std::move(caps), ResultStatus::Success); } +bool AppLoader_NCCH::IsN3DSExclusive() { + if (!is_loaded) { + ResultStatus res = base_ncch.Load(); + if (res != ResultStatus::Success) { + return false; + } + } + + std::vector smdh_buffer; + if (ReadIcon(smdh_buffer) == ResultStatus::Success && IsValidSMDH(smdh_buffer)) { + SMDH* smdh = reinterpret_cast(smdh_buffer.data()); + return smdh->flags.n3ds_exclusive != 0; + } + + return false; +} + ResultStatus AppLoader_NCCH::LoadExec(std::shared_ptr& process) { using Kernel::CodeSet; diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h index d36e4c249..c5b1b45d5 100644 --- a/src/core/loader/ncch.h +++ b/src/core/loader/ncch.h @@ -50,6 +50,8 @@ public: std::pair, ResultStatus> LoadNew3dsHwCapabilities() override; + bool IsN3DSExclusive() override; + ResultStatus IsExecutable(bool& out_executable) override; ResultStatus ReadCode(std::vector& buffer) override; diff --git a/src/core/loader/smdh.h b/src/core/loader/smdh.h index 2913b195b..04a97f5d4 100644 --- a/src/core/loader/smdh.h +++ b/src/core/loader/smdh.h @@ -7,6 +7,7 @@ #include #include #include +#include "common/bit_field.h" #include "common/common_funcs.h" #include "common/common_types.h" #include "common/swap.h" @@ -37,7 +38,23 @@ struct SMDH { u32_le region_lockout; u32_le match_maker_id; u64_le match_maker_bit_id; - u32_le flags; + union { + u32_le raw; + + BitField<0, 1, u32> visible; + BitField<1, 1, u32> autoboot; + BitField<2, 1, u32> allow_3D; + BitField<3, 1, u32> require_eula; + BitField<4, 1, u32> autosave; + BitField<5, 1, u32> extended_banner; + BitField<6, 1, u32> rating_required; + BitField<7, 1, u32> uses_savedata; + BitField<8, 1, u32> record_usage; + BitField<10, 1, u32> disable_save_backup; + BitField<12, 1, u32> n3ds_exclusive; + BitField<14, 1, u32> parental_restricted; + } flags; + u16_le eula_version; INSERT_PADDING_BYTES(2); float_le banner_animation_frame; @@ -73,10 +90,6 @@ struct SMDH { Taiwan = 6, }; - enum Flags { - Visible = 1 << 0, - }; - /** * Checks if SMDH is valid. */