diff --git a/src/android/app/src/main/java/org/citra/citra_emu/model/GameInfo.kt b/src/android/app/src/main/java/org/citra/citra_emu/model/GameInfo.kt index de2c1860c..469ace945 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/model/GameInfo.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/model/GameInfo.kt @@ -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,6 +22,8 @@ class GameInfo(path: String) { external fun getTitle(): String + external fun isEncrypted(): Boolean + external fun getRegions(): String external fun getCompany(): String diff --git a/src/android/app/src/main/java/org/citra/citra_emu/utils/GameHelper.kt b/src/android/app/src/main/java/org/citra/citra_emu/utils/GameHelper.kt index 9ad2e88ff..771064d74 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/utils/GameHelper.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/utils/GameHelper.kt @@ -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. @@ -11,6 +11,7 @@ import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import org.citra.citra_emu.CitraApplication import org.citra.citra_emu.NativeLibrary +import org.citra.citra_emu.R import org.citra.citra_emu.model.CheapDocument import org.citra.citra_emu.model.Game import org.citra.citra_emu.model.GameInfo @@ -69,19 +70,25 @@ object GameHelper { fun getGame(uri: Uri, isInstalled: Boolean, addedToLibrary: Boolean): Game { val filePath = uri.toString() - val gameInfo: GameInfo? = try { + var gameInfo: GameInfo? = try { GameInfo(filePath) } catch (e: IOException) { null } + var isEncrypted = false + if (gameInfo?.isEncrypted() == true) { + gameInfo = null + isEncrypted = true + } + val newGame = Game( (gameInfo?.getTitle() ?: FileUtil.getFilename(uri)).replace("[\\t\\n\\r]+".toRegex(), " "), filePath.replace("\n", " "), filePath, NativeLibrary.getTitleId(filePath), gameInfo?.getCompany() ?: "", - gameInfo?.getRegions() ?: "Invalid region", + gameInfo?.getRegions() ?: (if (isEncrypted) { CitraApplication.appContext.getString(R.string.unsupported_encrypted) } else { CitraApplication.appContext.getString(R.string.invalid_region) }), isInstalled, NativeLibrary.getIsSystemTitle(filePath), gameInfo?.getIsVisibleSystemTitle() ?: false, diff --git a/src/android/app/src/main/jni/game_info.cpp b/src/android/app/src/main/jni/game_info.cpp index d9b7c8f12..3f5855452 100644 --- a/src/android/app/src/main/jni/game_info.cpp +++ b/src/android/app/src/main/jni/game_info.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. @@ -17,7 +17,7 @@ namespace { -std::vector GetSMDHData(const std::string& path) { +std::vector GetSMDHData(const std::string& path, bool& is_encrypted) { std::unique_ptr loader = Loader::GetLoader(path); if (!loader) { return {}; @@ -26,9 +26,13 @@ std::vector GetSMDHData(const std::string& path) { u64 program_id = 0; loader->ReadProgramId(program_id); - std::vector smdh = [program_id, &loader]() -> std::vector { + std::vector smdh = [program_id, &loader, &is_encrypted]() -> std::vector { std::vector original_smdh; - loader->ReadIcon(original_smdh); + auto result = loader->ReadIcon(original_smdh); + if (result == Loader::ResultStatus::ErrorEncrypted) { + is_encrypted = true; + return original_smdh; + } if (program_id < 0x00040000'00000000 || program_id > 0x00040000'FFFFFFFF) return original_smdh; @@ -62,16 +66,26 @@ static Loader::SMDH* GetPointer(JNIEnv* env, jobject obj) { JNIEXPORT jlong JNICALL Java_org_citra_citra_1emu_model_GameInfo_initialize(JNIEnv* env, jclass, jstring j_path) { - std::vector smdh_data = GetSMDHData(GetJString(env, j_path)); + bool is_encrypted = false; + std::vector smdh_data = GetSMDHData(GetJString(env, j_path), is_encrypted); Loader::SMDH* smdh = nullptr; - if (Loader::IsValidSMDH(smdh_data)) { + if (is_encrypted) { + smdh = new Loader::SMDH; + smdh->magic = 0xDEADDEAD; + } else if (Loader::IsValidSMDH(smdh_data)) { smdh = new Loader::SMDH; std::memcpy(smdh, smdh_data.data(), sizeof(Loader::SMDH)); } return reinterpret_cast(smdh); } +JNIEXPORT jboolean JNICALL Java_org_citra_citra_1emu_model_GameInfo_isEncrypted(JNIEnv* env, + jobject obj) { + Loader::SMDH* smdh = GetPointer(env, obj); + return smdh->magic == 0xDEADDEAD; +} + JNIEXPORT void JNICALL Java_org_citra_citra_1emu_model_GameInfo_finalize(JNIEnv* env, jobject obj) { delete GetPointer(env, obj); } diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 777a2239d..8afbc7d7e 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -465,6 +465,8 @@ Save/Load Error Fatal Error A fatal error occurred. Check the log for details.\nContinuing emulation may result in crashes and bugs. + Invalid region + Unsupported encrypted application Preparing Shaders