android: Show unsupported encrypted app message instead of invalid region

This commit is contained in:
PabloMK7 2025-03-22 16:45:33 +01:00 committed by OpenSauce04
parent 9ee1801d32
commit cc7625e87c
4 changed files with 35 additions and 10 deletions

View File

@ -1,4 +1,4 @@
// Copyright 2023 Citra Emulator Project // Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
@ -22,6 +22,8 @@ class GameInfo(path: String) {
external fun getTitle(): String external fun getTitle(): String
external fun isEncrypted(): Boolean
external fun getRegions(): String external fun getRegions(): String
external fun getCompany(): String external fun getCompany(): String

View File

@ -1,4 +1,4 @@
// Copyright 2023 Citra Emulator Project // Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
@ -11,6 +11,7 @@ import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import org.citra.citra_emu.CitraApplication import org.citra.citra_emu.CitraApplication
import org.citra.citra_emu.NativeLibrary 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.CheapDocument
import org.citra.citra_emu.model.Game import org.citra.citra_emu.model.Game
import org.citra.citra_emu.model.GameInfo import org.citra.citra_emu.model.GameInfo
@ -69,19 +70,25 @@ object GameHelper {
fun getGame(uri: Uri, isInstalled: Boolean, addedToLibrary: Boolean): Game { fun getGame(uri: Uri, isInstalled: Boolean, addedToLibrary: Boolean): Game {
val filePath = uri.toString() val filePath = uri.toString()
val gameInfo: GameInfo? = try { var gameInfo: GameInfo? = try {
GameInfo(filePath) GameInfo(filePath)
} catch (e: IOException) { } catch (e: IOException) {
null null
} }
var isEncrypted = false
if (gameInfo?.isEncrypted() == true) {
gameInfo = null
isEncrypted = true
}
val newGame = Game( val newGame = Game(
(gameInfo?.getTitle() ?: FileUtil.getFilename(uri)).replace("[\\t\\n\\r]+".toRegex(), " "), (gameInfo?.getTitle() ?: FileUtil.getFilename(uri)).replace("[\\t\\n\\r]+".toRegex(), " "),
filePath.replace("\n", " "), filePath.replace("\n", " "),
filePath, filePath,
NativeLibrary.getTitleId(filePath), NativeLibrary.getTitleId(filePath),
gameInfo?.getCompany() ?: "", 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, isInstalled,
NativeLibrary.getIsSystemTitle(filePath), NativeLibrary.getIsSystemTitle(filePath),
gameInfo?.getIsVisibleSystemTitle() ?: false, gameInfo?.getIsVisibleSystemTitle() ?: false,

View File

@ -1,4 +1,4 @@
// Copyright 2017 Citra Emulator Project // Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
@ -17,7 +17,7 @@
namespace { namespace {
std::vector<u8> GetSMDHData(const std::string& path) { std::vector<u8> GetSMDHData(const std::string& path, bool& is_encrypted) {
std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(path); std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(path);
if (!loader) { if (!loader) {
return {}; return {};
@ -26,9 +26,13 @@ std::vector<u8> GetSMDHData(const std::string& path) {
u64 program_id = 0; u64 program_id = 0;
loader->ReadProgramId(program_id); loader->ReadProgramId(program_id);
std::vector<u8> smdh = [program_id, &loader]() -> std::vector<u8> { std::vector<u8> smdh = [program_id, &loader, &is_encrypted]() -> std::vector<u8> {
std::vector<u8> original_smdh; std::vector<u8> 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) if (program_id < 0x00040000'00000000 || program_id > 0x00040000'FFFFFFFF)
return original_smdh; 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, JNIEXPORT jlong JNICALL Java_org_citra_citra_1emu_model_GameInfo_initialize(JNIEnv* env, jclass,
jstring j_path) { jstring j_path) {
std::vector<u8> smdh_data = GetSMDHData(GetJString(env, j_path)); bool is_encrypted = false;
std::vector<u8> smdh_data = GetSMDHData(GetJString(env, j_path), is_encrypted);
Loader::SMDH* smdh = nullptr; 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; smdh = new Loader::SMDH;
std::memcpy(smdh, smdh_data.data(), sizeof(Loader::SMDH)); std::memcpy(smdh, smdh_data.data(), sizeof(Loader::SMDH));
} }
return reinterpret_cast<jlong>(smdh); return reinterpret_cast<jlong>(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) { JNIEXPORT void JNICALL Java_org_citra_citra_1emu_model_GameInfo_finalize(JNIEnv* env, jobject obj) {
delete GetPointer(env, obj); delete GetPointer(env, obj);
} }

View File

@ -465,6 +465,8 @@
<string name="save_load_error">Save/Load Error</string> <string name="save_load_error">Save/Load Error</string>
<string name="fatal_error">Fatal Error</string> <string name="fatal_error">Fatal Error</string>
<string name="fatal_error_message">A fatal error occurred. Check the log for details.\nContinuing emulation may result in crashes and bugs.</string> <string name="fatal_error_message">A fatal error occurred. Check the log for details.\nContinuing emulation may result in crashes and bugs.</string>
<string name="invalid_region">Invalid region</string>
<string name="unsupported_encrypted">Unsupported encrypted application</string>
<!-- Disk Shader Cache --> <!-- Disk Shader Cache -->
<string name="preparing_shaders">Preparing Shaders</string> <string name="preparing_shaders">Preparing Shaders</string>