@@ -11,8 +11,10 @@
#include <jni.h>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <thread>
#include <utility>

#include "ButtonManager.h"

@@ -403,6 +405,8 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_PauseEmulati
jobject obj);
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_StopEmulation(JNIEnv* env,
jobject obj);
JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_IsRunning(JNIEnv* env,
jobject obj);
JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_onGamePadEvent(
JNIEnv* env, jobject obj, jstring jDevice, jint Button, jint Action);
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_onGamePadMoveEvent(
@@ -447,10 +451,18 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetFilename(
jstring jFile);
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveState(JNIEnv* env,
jobject obj,
jint slot);
jint slot,
jboolean wait);
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveStateAs(JNIEnv* env,
jobject obj,
jstring path,
jboolean wait);
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_LoadState(JNIEnv* env,
jobject obj,
jint slot);
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_LoadStateAs(JNIEnv* env,
jobject obj,
jstring path);
JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_services_DirectoryInitializationService_CreateUserDirectories(
JNIEnv* env, jobject obj);
@@ -467,8 +479,11 @@ JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_NativeLibrary_WriteProfileResults(JNIEnv* env, jobject obj);
JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_NativeLibrary_CacheClassesAndMethods(JNIEnv* env, jobject obj);
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv* env, jobject obj,
jstring jFile);
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run__Ljava_lang_String_2(
JNIEnv* env, jobject obj, jstring jFile);
JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_NativeLibrary_Run__Ljava_lang_String_2Ljava_lang_String_2Z(
JNIEnv* env, jobject obj, jstring jFile, jstring jSavestate, jboolean jDeleteSavestate);
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceChanged(JNIEnv* env,
jobject obj,
jobject surf);
@@ -496,11 +511,19 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_StopEmulatio
Core::Stop();
s_update_main_frame_event.Set(); // Kick the waiting event
}

JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_IsRunning(JNIEnv* env,
jobject obj)
{
return Core::IsRunning();
}

JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_onGamePadEvent(
JNIEnv* env, jobject obj, jstring jDevice, jint Button, jint Action)
{
return ButtonManager::GamepadEvent(GetJString(env, jDevice), Button, Action);
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_onGamePadMoveEvent(
JNIEnv* env, jobject obj, jstring jDevice, jint Axis, jfloat Value)
{
@@ -643,10 +666,20 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetConfig(

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveState(JNIEnv* env,
jobject obj,
jint slot)
jint slot,
jboolean wait)
{
std::lock_guard<std::mutex> guard(s_host_identity_lock);
State::Save(slot);
State::Save(slot, wait);
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveStateAs(JNIEnv* env,
jobject obj,
jstring path,
jboolean wait)
{
std::lock_guard<std::mutex> guard(s_host_identity_lock);
State::SaveAs(GetJString(env, path), wait);
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_LoadState(JNIEnv* env,
@@ -657,6 +690,14 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_LoadState(JN
State::Load(slot);
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_LoadStateAs(JNIEnv* env,
jobject obj,
jstring path)
{
std::lock_guard<std::mutex> guard(s_host_identity_lock);
State::LoadAs(GetJString(env, path));
}

JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_services_DirectoryInitializationService_SetSysDirectory(
JNIEnv* env, jobject obj, jstring jPath)
@@ -762,10 +803,9 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_RefreshWiimo
WiimoteReal::Refresh();
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv* env, jobject obj,
jstring jFile)
static void Run(const std::string& path, std::optional<std::string> savestate_path = {},
bool delete_savestate = false)
{
const std::string path = GetJString(env, jFile);
__android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Running : %s", path.c_str());

// Install our callbacks
@@ -781,7 +821,9 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv*

// No use running the loop when booting fails
s_have_wm_user_stop = false;
if (BootManager::BootCore(BootParameters::GenerateFromFile(path)))
std::unique_ptr<BootParameters> boot = BootParameters::GenerateFromFile(path, savestate_path);
boot->delete_savestate = delete_savestate;
if (BootManager::BootCore(std::move(boot)))
{
static constexpr int TIMEOUT = 10000;
static constexpr int WAIT_STEP = 25;
@@ -812,6 +854,19 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv*
}
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run__Ljava_lang_String_2(
JNIEnv* env, jobject obj, jstring jFile)
{
Run(GetJString(env, jFile));
}

JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_NativeLibrary_Run__Ljava_lang_String_2Ljava_lang_String_2Z(
JNIEnv* env, jobject obj, jstring jFile, jstring jSavestate, jboolean jDeleteSavestate)
{
Run(GetJString(env, jFile), GetJString(env, jSavestate), jDeleteSavestate);
}

#ifdef __cplusplus
}
#endif
@@ -76,6 +76,7 @@ struct BootParameters

Parameters parameters;
std::optional<std::string> savestate_path;
bool delete_savestate = false;
};

class CBoot
@@ -318,7 +318,7 @@ static void CPUSetInitialExecutionState()
}

// Create the CPU thread, which is a CPU + Video thread in Single Core mode.
static void CpuThread(const std::optional<std::string>& savestate_path)
static void CpuThread(const std::optional<std::string>& savestate_path, bool delete_savestate)
{
DeclareAsCPUThread();

@@ -342,7 +342,13 @@ static void CpuThread(const std::optional<std::string>& savestate_path)
EMM::InstallExceptionHandler(); // Let's run under memory watch

if (savestate_path)
QueueHostJob([&savestate_path] { ::State::LoadAs(*savestate_path); });
{
QueueHostJob([&savestate_path, delete_savestate] {
::State::LoadAs(*savestate_path);
if (delete_savestate)
File::Delete(*savestate_path);
});
}

s_is_started = true;
CPUSetInitialExecutionState();
@@ -380,7 +386,8 @@ static void CpuThread(const std::optional<std::string>& savestate_path)
EMM::UninstallExceptionHandler();
}

static void FifoPlayerThread(const std::optional<std::string>& savestate_path)
static void FifoPlayerThread(const std::optional<std::string>& savestate_path,
bool delete_savestate)
{
DeclareAsCPUThread();
const SConfig& _CoreParameter = SConfig::GetInstance();
@@ -517,6 +524,7 @@ static void EmuThread(std::unique_ptr<BootParameters> boot)
}

const std::optional<std::string> savestate_path = boot->savestate_path;
const bool delete_savestate = boot->delete_savestate;

// Load and Init Wiimotes - only if we are booting in Wii mode
if (core_parameter.bWii && !SConfig::GetInstance().m_bt_passthrough_enabled)
@@ -556,7 +564,7 @@ static void EmuThread(std::unique_ptr<BootParameters> boot)
PowerPC::SetMode(PowerPC::CoreMode::Interpreter);

// Determine the CPU thread function
void (*cpuThreadFunc)(const std::optional<std::string>& savestate_path);
void (*cpuThreadFunc)(const std::optional<std::string>& savestate_path, bool delete_savestate);
if (std::holds_alternative<BootParameters::DFF>(boot->parameters))
cpuThreadFunc = FifoPlayerThread;
else
@@ -597,7 +605,7 @@ static void EmuThread(std::unique_ptr<BootParameters> boot)
Host_Message(WM_USER_CREATE);

// Spawn the CPU thread
s_cpu_thread = std::thread(cpuThreadFunc, savestate_path);
s_cpu_thread = std::thread(cpuThreadFunc, savestate_path, delete_savestate);

// become the GPU thread
Fifo::RunGpuLoop();
@@ -615,7 +623,7 @@ static void EmuThread(std::unique_ptr<BootParameters> boot)
Common::SetCurrentThreadName("Emuthread - Idle");

// Spawn the CPU+GPU thread
s_cpu_thread = std::thread(cpuThreadFunc, savestate_path);
s_cpu_thread = std::thread(cpuThreadFunc, savestate_path, delete_savestate);

while (CPU::GetState() != CPU::State::PowerDown)
{