diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java index 8d193e75ec..e82de7fa01 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java @@ -294,8 +294,19 @@ public final class NativeLibrary * Saves a game state to the slot number. * * @param slot The slot location to save state to. + * @param wait If false, returns as early as possible. + * If true, returns once the savestate has been written to disk. */ - public static native void SaveState(int slot); + public static native void SaveState(int slot, boolean wait); + + /** + * Saves a game state to the specified path. + * + * @param path The path to save state to. + * @param wait If false, returns as early as possible. + * If true, returns once the savestate has been written to disk. + */ + public static native void SaveStateAs(String path, boolean wait); /** * Loads a game state from the slot number. @@ -304,6 +315,13 @@ public final class NativeLibrary */ public static native void LoadState(int slot); + /** + * Loads a game state from the specified path. + * + * @param path The path to load state from. + */ + public static native void LoadStateAs(String path); + /** * Sets the current working user directory * If not set, it auto-detects a location @@ -322,6 +340,11 @@ public final class NativeLibrary */ public static native void Run(String path); + /** + * Begins emulation from the specified savestate. + */ + public static native void Run(String path, String savestatePath, boolean deleteSavestate); + // Surface Handling public static native void SurfaceChanged(Surface surf); public static native void SurfaceDestroyed(); @@ -335,6 +358,9 @@ public final class NativeLibrary /** Stops emulation. */ public static native void StopEmulation(); + /** Returns true if emulation is running (or is paused). */ + public static native boolean IsRunning(); + /** * Enables or disables CPU block profiling * @param enable diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java index 56873cab76..80972f0c7f 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java @@ -2,7 +2,6 @@ package org.dolphinemu.dolphinemu.activities; import android.app.AlertDialog; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.hardware.usb.UsbManager; @@ -42,7 +41,6 @@ import org.dolphinemu.dolphinemu.utils.Animations; import org.dolphinemu.dolphinemu.utils.ControllerMappingHelper; import org.dolphinemu.dolphinemu.utils.Java_GCAdapter; import org.dolphinemu.dolphinemu.utils.Java_WiimoteAdapter; -import org.dolphinemu.dolphinemu.utils.Log; import java.lang.annotation.Retention; import java.util.List; @@ -68,8 +66,15 @@ public final class EmulationActivity extends AppCompatActivity private static boolean sIsGameCubeGame; + private boolean activityRecreated; private String mScreenPath; private String mSelectedTitle; + private String mPath; + + public static final String EXTRA_SELECTED_GAME = "SelectedGame"; + public static final String EXTRA_SELECTED_TITLE = "SelectedTitle"; + public static final String EXTRA_SCREEN_PATH = "ScreenPath"; + public static final String EXTRA_GRID_POSITION = "GridPosition"; @Retention(SOURCE) @IntDef({MENU_ACTION_EDIT_CONTROLS_PLACEMENT, MENU_ACTION_TOGGLE_CONTROLS, MENU_ACTION_ADJUST_SCALE, @@ -138,10 +143,10 @@ public final class EmulationActivity extends AppCompatActivity { Intent launcher = new Intent(activity, EmulationActivity.class); - launcher.putExtra("SelectedGame", path); - launcher.putExtra("SelectedTitle", title); - launcher.putExtra("ScreenPath", screenshotPath); - launcher.putExtra("GridPosition", position); + launcher.putExtra(EXTRA_SELECTED_GAME, path); + launcher.putExtra(EXTRA_SELECTED_TITLE, title); + launcher.putExtra(EXTRA_SCREEN_PATH, screenshotPath); + launcher.putExtra(EXTRA_GRID_POSITION, position); ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation( activity, @@ -158,13 +163,23 @@ public final class EmulationActivity extends AppCompatActivity { super.onCreate(savedInstanceState); - // Get params we were passed - Intent gameToEmulate = getIntent(); - String path = gameToEmulate.getStringExtra("SelectedGame"); - sIsGameCubeGame = Platform.fromNativeInt(NativeLibrary.GetPlatform(path)) == Platform.GAMECUBE; - mSelectedTitle = gameToEmulate.getStringExtra("SelectedTitle"); - mScreenPath = gameToEmulate.getStringExtra("ScreenPath"); - mPosition = gameToEmulate.getIntExtra("GridPosition", -1); + if (savedInstanceState == null) + { + // Get params we were passed + Intent gameToEmulate = getIntent(); + mPath = gameToEmulate.getStringExtra(EXTRA_SELECTED_GAME); + mSelectedTitle = gameToEmulate.getStringExtra(EXTRA_SELECTED_TITLE); + mScreenPath = gameToEmulate.getStringExtra(EXTRA_SCREEN_PATH); + mPosition = gameToEmulate.getIntExtra(EXTRA_GRID_POSITION, -1); + activityRecreated = false; + } + else + { + activityRecreated = true; + restoreState(savedInstanceState); + } + + sIsGameCubeGame = Platform.fromNativeInt(NativeLibrary.GetPlatform(mPath)) == Platform.GAMECUBE; mDeviceHasTouchScreen = getPackageManager().hasSystemFeature("android.hardware.touchscreen"); mControllerMappingHelper = new ControllerMappingHelper(); @@ -206,7 +221,7 @@ public final class EmulationActivity extends AppCompatActivity .findFragmentById(R.id.frame_emulation_fragment); if (mEmulationFragment == null) { - mEmulationFragment = EmulationFragment.newInstance(path); + mEmulationFragment = EmulationFragment.newInstance(mPath); getSupportFragmentManager().beginTransaction() .add(R.id.frame_emulation_fragment, mEmulationFragment) .commit(); @@ -256,6 +271,25 @@ public final class EmulationActivity extends AppCompatActivity } + @Override + protected void onSaveInstanceState(Bundle outState) + { + mEmulationFragment.saveTemporaryState(); + outState.putString(EXTRA_SELECTED_GAME, mPath); + outState.putString(EXTRA_SELECTED_TITLE, mSelectedTitle); + outState.putString(EXTRA_SCREEN_PATH, mScreenPath); + outState.putInt(EXTRA_GRID_POSITION, mPosition); + super.onSaveInstanceState(outState); + } + + protected void restoreState(Bundle savedInstanceState) + { + mPath = savedInstanceState.getString(EXTRA_SELECTED_GAME); + mSelectedTitle = savedInstanceState.getString(EXTRA_SELECTED_TITLE); + mScreenPath = savedInstanceState.getString(EXTRA_SCREEN_PATH); + mPosition = savedInstanceState.getInt(EXTRA_GRID_POSITION); + } + @Override public void onBackPressed() { @@ -412,7 +446,7 @@ public final class EmulationActivity extends AppCompatActivity // Quick save / load case MENU_ACTION_QUICK_SAVE: - NativeLibrary.SaveState(9); + NativeLibrary.SaveState(9, false); return; case MENU_ACTION_QUICK_LOAD: @@ -436,27 +470,27 @@ public final class EmulationActivity extends AppCompatActivity // Save state slots case MENU_ACTION_SAVE_SLOT1: - NativeLibrary.SaveState(0); + NativeLibrary.SaveState(0, false); return; case MENU_ACTION_SAVE_SLOT2: - NativeLibrary.SaveState(1); + NativeLibrary.SaveState(1, false); return; case MENU_ACTION_SAVE_SLOT3: - NativeLibrary.SaveState(2); + NativeLibrary.SaveState(2, false); return; case MENU_ACTION_SAVE_SLOT4: - NativeLibrary.SaveState(3); + NativeLibrary.SaveState(3, false); return; case MENU_ACTION_SAVE_SLOT5: - NativeLibrary.SaveState(4); + NativeLibrary.SaveState(4, false); return; case MENU_ACTION_SAVE_SLOT6: - NativeLibrary.SaveState(5); + NativeLibrary.SaveState(5, false); return; // Load state slots @@ -716,4 +750,9 @@ public final class EmulationActivity extends AppCompatActivity { return sIsGameCubeGame; } + + public boolean isActivityRecreated() + { + return activityRecreated; + } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java index 27d32db0d5..1d6a67e6c4 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java @@ -25,6 +25,8 @@ import org.dolphinemu.dolphinemu.services.DirectoryInitializationService.Directo import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver; import org.dolphinemu.dolphinemu.utils.Log; +import java.io.File; + import rx.functions.Action1; public final class EmulationFragment extends Fragment implements SurfaceHolder.Callback @@ -39,6 +41,8 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C private DirectoryStateReceiver directoryStateReceiver; + private EmulationActivity activity; + public static EmulationFragment newInstance(String gamePath) { @@ -57,6 +61,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C if (context instanceof EmulationActivity) { + activity = (EmulationActivity)context; NativeLibrary.setEmulationActivity((EmulationActivity) context); } else @@ -79,7 +84,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C mPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); String gamePath = getArguments().getString(KEY_GAMEPATH); - mEmulationState = new EmulationState(gamePath); + mEmulationState = new EmulationState(gamePath, getTemporaryStateFilePath()); } /** @@ -120,7 +125,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C super.onResume(); if (DirectoryInitializationService.areDolphinDirectoriesReady()) { - mEmulationState.run(); + mEmulationState.run(activity.isActivityRecreated()); } else { @@ -155,7 +160,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C directoryStateReceiver = new DirectoryStateReceiver(directoryInitializationState -> { if (directoryInitializationState == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) { - mEmulationState.run(); + mEmulationState.run(activity.isActivityRecreated()); } else if (directoryInitializationState == DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED) { Toast.makeText(getContext(), R.string.write_permission_needed, Toast.LENGTH_SHORT) .show(); @@ -249,10 +254,13 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C private State state; private Surface mSurface; private boolean mRunWhenSurfaceIsValid; + private boolean loadPreviousTemporaryState; + private final String temporaryStatePath; - EmulationState(String gamePath) + EmulationState(String gamePath, String temporaryStatePath) { mGamePath = gamePath; + this.temporaryStatePath = temporaryStatePath; // Starting state is stopped. state = State.STOPPED; } @@ -280,6 +288,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C { if (state != State.STOPPED) { + Log.debug("[EmulationFragment] Stopping emulation."); state = State.STOPPED; NativeLibrary.StopEmulation(); } @@ -307,8 +316,29 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C } } - public synchronized void run() + public synchronized void run(boolean isActivityRecreated) { + if (isActivityRecreated) + { + if (NativeLibrary.IsRunning()) + { + loadPreviousTemporaryState = false; + state = State.PAUSED; + deleteFile(temporaryStatePath); + } + else + { + loadPreviousTemporaryState = true; + } + } + else + { + Log.debug("[EmulationFragment] activity resumed or fresh start"); + loadPreviousTemporaryState = false; + // activity resumed without being killed or this is the first run + deleteFile(temporaryStatePath); + } + // If the surface is set, run now. Otherwise, wait for it to get set. if (mSurface != null) { @@ -362,12 +392,19 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C mRunWhenSurfaceIsValid = false; if (state == State.STOPPED) { - Log.debug("[EmulationFragment] Starting emulation thread."); - mEmulationThread = new Thread(() -> { NativeLibrary.SurfaceChanged(mSurface); - NativeLibrary.Run(mGamePath); + if (loadPreviousTemporaryState) + { + Log.debug("[EmulationFragment] Starting emulation thread from previous state."); + NativeLibrary.Run(mGamePath, temporaryStatePath, true); + } + else + { + Log.debug("[EmulationFragment] Starting emulation thread."); + NativeLibrary.Run(mGamePath); + } }, "NativeEmulation"); mEmulationThread.start(); @@ -385,4 +422,27 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C state = State.RUNNING; } } + + public void saveTemporaryState() + { + NativeLibrary.SaveStateAs(getTemporaryStateFilePath(), true); + } + + private String getTemporaryStateFilePath() + { + return getContext().getFilesDir() + File.separator + "temp.sav"; + } + + private static void deleteFile(String path) + { + try + { + File file = new File(path); + file.delete(); + } + catch (Exception ex) + { + // fail safely + } + } } diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index c6c40da097..56523d9eb4 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -11,8 +11,10 @@ #include #include #include +#include #include #include +#include #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 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 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 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 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 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 diff --git a/Source/Core/Core/Boot/Boot.h b/Source/Core/Core/Boot/Boot.h index 7581b2abb8..a6b7391b44 100644 --- a/Source/Core/Core/Boot/Boot.h +++ b/Source/Core/Core/Boot/Boot.h @@ -76,6 +76,7 @@ struct BootParameters Parameters parameters; std::optional savestate_path; + bool delete_savestate = false; }; class CBoot diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index 1d77f4e2fc..500885ffbb 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -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& savestate_path) +static void CpuThread(const std::optional& savestate_path, bool delete_savestate) { DeclareAsCPUThread(); @@ -342,7 +342,13 @@ static void CpuThread(const std::optional& 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& savestate_path) EMM::UninstallExceptionHandler(); } -static void FifoPlayerThread(const std::optional& savestate_path) +static void FifoPlayerThread(const std::optional& savestate_path, + bool delete_savestate) { DeclareAsCPUThread(); const SConfig& _CoreParameter = SConfig::GetInstance(); @@ -517,6 +524,7 @@ static void EmuThread(std::unique_ptr boot) } const std::optional 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 boot) PowerPC::SetMode(PowerPC::CoreMode::Interpreter); // Determine the CPU thread function - void (*cpuThreadFunc)(const std::optional& savestate_path); + void (*cpuThreadFunc)(const std::optional& savestate_path, bool delete_savestate); if (std::holds_alternative(boot->parameters)) cpuThreadFunc = FifoPlayerThread; else @@ -597,7 +605,7 @@ static void EmuThread(std::unique_ptr 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 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) {