android: frontend: Add errors for unsupported ROM formats.
This commit is contained in:
parent
abfa49a6d7
commit
30ef4a1b7c
@ -8,11 +8,13 @@ package org.citra.citra_android;
|
|||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.preference.PreferenceManager;
|
import android.text.Html;
|
||||||
|
import android.text.method.LinkMovementMethod;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.citra.citra_android.activities.EmulationActivity;
|
import org.citra.citra_android.activities.EmulationActivity;
|
||||||
import org.citra.citra_android.utils.EmulationMenuSettings;
|
import org.citra.citra_android.utils.EmulationMenuSettings;
|
||||||
@ -444,6 +446,46 @@ public final class NativeLibrary {
|
|||||||
return alertPromptButton;
|
return alertPromptButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void exitEmulationActivity(int resultCode) {
|
||||||
|
final int Success = 0;
|
||||||
|
final int ErrorNotInitialized = 1;
|
||||||
|
final int ErrorGetLoader = 2;
|
||||||
|
final int ErrorSystemMode = 3;
|
||||||
|
final int ErrorLoader = 4;
|
||||||
|
final int ErrorLoader_ErrorEncrypted = 5;
|
||||||
|
final int ErrorLoader_ErrorInvalidFormat = 6;
|
||||||
|
final int ErrorSystemFiles = 7;
|
||||||
|
final int ErrorVideoCore = 8;
|
||||||
|
final int ErrorVideoCore_ErrorGenericDrivers = 9;
|
||||||
|
final int ErrorVideoCore_ErrorBelowGL33 = 10;
|
||||||
|
final int ShutdownRequested = 11;
|
||||||
|
final int ErrorUnknown = 12;
|
||||||
|
|
||||||
|
final EmulationActivity emulationActivity = sEmulationActivity.get();
|
||||||
|
if (emulationActivity == null) {
|
||||||
|
Log.warning("[NativeLibrary] EmulationActivity is null, can't exit.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int captionId = R.string.loader_error_invalid_format;
|
||||||
|
if (resultCode == ErrorLoader_ErrorEncrypted) {
|
||||||
|
captionId = R.string.loader_error_encrypted;
|
||||||
|
}
|
||||||
|
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(emulationActivity)
|
||||||
|
.setTitle(captionId)
|
||||||
|
.setMessage(Html.fromHtml("Please follow the guides to redump your <a href=\"https://citra-emu.org/wiki/dumping-game-cartridges/\">game cartidges</a> or <a href=\"https://citra-emu.org/wiki/dumping-installed-titles/\">installed titles</a>."))
|
||||||
|
.setPositiveButton(android.R.string.ok, (dialog, whichButton) -> emulationActivity.exitWithAnimation())
|
||||||
|
.setOnDismissListener(dialogInterface -> emulationActivity.exitWithAnimation());
|
||||||
|
emulationActivity.runOnUiThread(() -> {
|
||||||
|
AlertDialog alert = builder.create();
|
||||||
|
alert.show();
|
||||||
|
((TextView) alert.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
public static void setEmulationActivity(EmulationActivity emulationActivity) {
|
public static void setEmulationActivity(EmulationActivity emulationActivity) {
|
||||||
Log.verbose("[NativeLibrary] Registering EmulationActivity.");
|
Log.verbose("[NativeLibrary] Registering EmulationActivity.");
|
||||||
sEmulationActivity = new WeakReference<>(emulationActivity);
|
sEmulationActivity = new WeakReference<>(emulationActivity);
|
||||||
|
@ -140,7 +140,7 @@ public final class GameDatabase extends SQLiteOpenHelper {
|
|||||||
null); // Order of folders is irrelevant.
|
null); // Order of folders is irrelevant.
|
||||||
|
|
||||||
Set<String> allowedExtensions = new HashSet<String>(Arrays.asList(
|
Set<String> allowedExtensions = new HashSet<String>(Arrays.asList(
|
||||||
".3ds", ".3dsx", ".elf", ".axf", ".cci", ".cxi", ".app"));
|
".3ds", ".3dsx", ".elf", ".axf", ".cci", ".cxi", ".cia", ".app", ".rar", ".zip", ".7z", ".torrent", ".tar", ".gz"));
|
||||||
|
|
||||||
// Possibly overly defensive, but ensures that moveToNext() does not skip a row.
|
// Possibly overly defensive, but ensures that moveToNext() does not skip a row.
|
||||||
folderCursor.moveToPosition(-1);
|
folderCursor.moveToPosition(-1);
|
||||||
|
@ -21,6 +21,7 @@ static jmethodID s_display_alert_prompt;
|
|||||||
static jmethodID s_alert_prompt_button;
|
static jmethodID s_alert_prompt_button;
|
||||||
static jmethodID s_is_portrait_mode;
|
static jmethodID s_is_portrait_mode;
|
||||||
static jmethodID s_landscape_screen_layout;
|
static jmethodID s_landscape_screen_layout;
|
||||||
|
static jmethodID s_exit_emulation_activity;
|
||||||
|
|
||||||
namespace IDCache {
|
namespace IDCache {
|
||||||
|
|
||||||
@ -67,6 +68,10 @@ jmethodID GetLandscapeScreenLayout() {
|
|||||||
return s_landscape_screen_layout;
|
return s_landscape_screen_layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jmethodID GetExitEmulationActivity() {
|
||||||
|
return s_exit_emulation_activity;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace IDCache
|
} // namespace IDCache
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -103,6 +108,8 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
|||||||
s_is_portrait_mode = env->GetStaticMethodID(s_native_library_class, "isPortraitMode", "()Z");
|
s_is_portrait_mode = env->GetStaticMethodID(s_native_library_class, "isPortraitMode", "()Z");
|
||||||
s_landscape_screen_layout =
|
s_landscape_screen_layout =
|
||||||
env->GetStaticMethodID(s_native_library_class, "landscapeScreenLayout", "()I");
|
env->GetStaticMethodID(s_native_library_class, "landscapeScreenLayout", "()I");
|
||||||
|
s_exit_emulation_activity =
|
||||||
|
env->GetStaticMethodID(s_native_library_class, "exitEmulationActivity", "(I)V");
|
||||||
|
|
||||||
return JNI_VERSION;
|
return JNI_VERSION;
|
||||||
}
|
}
|
||||||
|
@ -15,5 +15,6 @@ jmethodID GetDisplayAlertPrompt();
|
|||||||
jmethodID GetAlertPromptButton();
|
jmethodID GetAlertPromptButton();
|
||||||
jmethodID GetIsPortraitMode();
|
jmethodID GetIsPortraitMode();
|
||||||
jmethodID GetLandscapeScreenLayout();
|
jmethodID GetLandscapeScreenLayout();
|
||||||
|
jmethodID GetExitEmulationActivity();
|
||||||
|
|
||||||
} // namespace IDCache
|
} // namespace IDCache
|
||||||
|
@ -109,7 +109,7 @@ public:
|
|||||||
void ShowError(const std::string& error) override {}
|
void ShowError(const std::string& error) override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
static int RunCitra(const std::string& filepath) {
|
static Core::System::ResultStatus RunCitra(const std::string& filepath) {
|
||||||
// Citra core only supports a single running instance
|
// Citra core only supports a single running instance
|
||||||
std::lock_guard<std::mutex> lock(running_mutex);
|
std::lock_guard<std::mutex> lock(running_mutex);
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ static int RunCitra(const std::string& filepath) {
|
|||||||
|
|
||||||
if (filepath.empty()) {
|
if (filepath.empty()) {
|
||||||
LOG_CRITICAL(Frontend, "Failed to load ROM: No ROM specified");
|
LOG_CRITICAL(Frontend, "Failed to load ROM: No ROM specified");
|
||||||
return -1;
|
return Core::System::ResultStatus::ErrorLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::System& system{Core::System::GetInstance()};
|
Core::System& system{Core::System::GetInstance()};
|
||||||
@ -143,33 +143,8 @@ static int RunCitra(const std::string& filepath) {
|
|||||||
SCOPE_EXIT({ window.reset(); });
|
SCOPE_EXIT({ window.reset(); });
|
||||||
|
|
||||||
const Core::System::ResultStatus load_result{system.Load(*window, filepath)};
|
const Core::System::ResultStatus load_result{system.Load(*window, filepath)};
|
||||||
switch (load_result) {
|
if (load_result != Core::System::ResultStatus::Success) {
|
||||||
case Core::System::ResultStatus::ErrorGetLoader:
|
return load_result;
|
||||||
LOG_CRITICAL(Frontend, "Failed to obtain loader for {}!", filepath);
|
|
||||||
return -1;
|
|
||||||
case Core::System::ResultStatus::ErrorLoader:
|
|
||||||
LOG_CRITICAL(Frontend, "Failed to load ROM!");
|
|
||||||
return -1;
|
|
||||||
case Core::System::ResultStatus::ErrorLoader_ErrorEncrypted:
|
|
||||||
LOG_CRITICAL(Frontend, "The game that you are trying to load must be decrypted before "
|
|
||||||
"being used with Citra. \n\n For more information on dumping and "
|
|
||||||
"decrypting games, please refer to: "
|
|
||||||
"https://citra-emu.org/wiki/dumping-game-cartridges/");
|
|
||||||
return -1;
|
|
||||||
case Core::System::ResultStatus::ErrorLoader_ErrorInvalidFormat:
|
|
||||||
LOG_CRITICAL(Frontend, "Error while loading ROM: The ROM format is not supported.");
|
|
||||||
return -1;
|
|
||||||
case Core::System::ResultStatus::ErrorNotInitialized:
|
|
||||||
LOG_CRITICAL(Frontend, "Core not initialized");
|
|
||||||
return -1;
|
|
||||||
case Core::System::ResultStatus::ErrorSystemMode:
|
|
||||||
LOG_CRITICAL(Frontend, "Failed to determine system mode!");
|
|
||||||
return -1;
|
|
||||||
case Core::System::ResultStatus::ErrorVideoCore:
|
|
||||||
LOG_CRITICAL(Frontend, "VideoCore not initialized");
|
|
||||||
return -1;
|
|
||||||
case Core::System::ResultStatus::Success:
|
|
||||||
break; // Expected case
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& telemetry_session = Core::System::GetInstance().TelemetrySession();
|
auto& telemetry_session = Core::System::GetInstance().TelemetrySession();
|
||||||
@ -192,7 +167,7 @@ static int RunCitra(const std::string& filepath) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return Core::System::ResultStatus::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Java_org_citra_citra_1android_NativeLibrary_SurfaceChanged(JNIEnv* env, jobject obj,
|
void Java_org_citra_citra_1android_NativeLibrary_SurfaceChanged(JNIEnv* env, jobject obj,
|
||||||
@ -483,5 +458,10 @@ void Java_org_citra_citra_1android_NativeLibrary_Run__Ljava_lang_String_2(JNIEnv
|
|||||||
is_running = false;
|
is_running = false;
|
||||||
running_cv.notify_all();
|
running_cv.notify_all();
|
||||||
}
|
}
|
||||||
RunCitra(path);
|
|
||||||
|
const Core::System::ResultStatus result{RunCitra(path)};
|
||||||
|
if (result != Core::System::ResultStatus::Success) {
|
||||||
|
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
|
||||||
|
IDCache::GetExitEmulationActivity(), static_cast<int>(result));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,6 +103,10 @@
|
|||||||
<string name="preferences_graphics">Graphics</string>
|
<string name="preferences_graphics">Graphics</string>
|
||||||
<string name="preferences_audio">Audio</string>
|
<string name="preferences_audio">Audio</string>
|
||||||
|
|
||||||
|
<!-- ROM loading errors -->
|
||||||
|
<string name="loader_error_encrypted">Your ROM is encrypted</string>
|
||||||
|
<string name="loader_error_invalid_format">Invalid ROM format</string>
|
||||||
|
|
||||||
<!-- Emulation Menu -->
|
<!-- Emulation Menu -->
|
||||||
<string name="emulation_screenshot">Take Screenshot</string>
|
<string name="emulation_screenshot">Take Screenshot</string>
|
||||||
<string name="emulation_exit">Exit</string>
|
<string name="emulation_exit">Exit</string>
|
||||||
|
@ -516,15 +516,17 @@ void System::RegisterImageInterface(std::shared_ptr<Frontend::ImageInterface> im
|
|||||||
|
|
||||||
void System::Shutdown(bool is_deserializing) {
|
void System::Shutdown(bool is_deserializing) {
|
||||||
// Log last frame performance stats
|
// Log last frame performance stats
|
||||||
const auto perf_results = GetAndResetPerfStats();
|
if (telemetry_session) {
|
||||||
telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_EmulationSpeed",
|
const auto perf_results = GetAndResetPerfStats();
|
||||||
perf_results.emulation_speed * 100.0);
|
telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_EmulationSpeed",
|
||||||
telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_Framerate",
|
perf_results.emulation_speed * 100.0);
|
||||||
perf_results.game_fps);
|
telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_Framerate",
|
||||||
telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_Frametime",
|
perf_results.game_fps);
|
||||||
perf_results.frametime * 1000.0);
|
telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_Frametime",
|
||||||
telemetry_session->AddField(Telemetry::FieldType::Performance, "Mean_Frametime_MS",
|
perf_results.frametime * 1000.0);
|
||||||
perf_stats->GetMeanFrametime());
|
telemetry_session->AddField(Telemetry::FieldType::Performance, "Mean_Frametime_MS",
|
||||||
|
perf_stats->GetMeanFrametime());
|
||||||
|
}
|
||||||
|
|
||||||
// Shutdown emulation session
|
// Shutdown emulation session
|
||||||
VideoCore::Shutdown();
|
VideoCore::Shutdown();
|
||||||
@ -544,7 +546,7 @@ void System::Shutdown(bool is_deserializing) {
|
|||||||
cpu_cores.clear();
|
cpu_cores.clear();
|
||||||
timing.reset();
|
timing.reset();
|
||||||
|
|
||||||
if (video_dumper->IsDumping()) {
|
if (video_dumper && video_dumper->IsDumping()) {
|
||||||
video_dumper->StopDumping();
|
video_dumper->StopDumping();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user