From 2e41f1e6eae107ec5923da0abf415aec0fd089de Mon Sep 17 00:00:00 2001 From: Matt Hills Date: Fri, 10 Apr 2026 19:36:04 -0400 Subject: [PATCH] Add delete option for save state slots Add deleteState method to EmulatorCore interface and implement in Ps1Core and NesCore. Delete button (trash icon) in the in-game Save/Load menu removes the state file and its screenshot, then refreshes the slot list. --- .../lazy/emulate/emulation/EmulatorCore.kt | 2 ++ .../lazy/emulate/emulation/cores/NesCore.kt | 8 ++++++++ .../lazy/emulate/emulation/cores/Ps1Core.kt | 8 ++++++++ .../emulate/ui/screens/game/GameScreen.kt | 20 +++++++++++++++++++ 4 files changed, 38 insertions(+) diff --git a/app/src/main/java/com/lazy/emulate/emulation/EmulatorCore.kt b/app/src/main/java/com/lazy/emulate/emulation/EmulatorCore.kt index 57f081e..0ca196a 100644 --- a/app/src/main/java/com/lazy/emulate/emulation/EmulatorCore.kt +++ b/app/src/main/java/com/lazy/emulate/emulation/EmulatorCore.kt @@ -42,6 +42,8 @@ interface EmulatorCore { fun loadState(slot: Int): Boolean + fun deleteState(slot: Int): Boolean = false + fun getSaveSlotInfo(slot: Int): SaveSlotInfo fun getScreenshotPath(slot: Int): String? = null diff --git a/app/src/main/java/com/lazy/emulate/emulation/cores/NesCore.kt b/app/src/main/java/com/lazy/emulate/emulation/cores/NesCore.kt index d6b7a8d..fb4d0f0 100644 --- a/app/src/main/java/com/lazy/emulate/emulation/cores/NesCore.kt +++ b/app/src/main/java/com/lazy/emulate/emulation/cores/NesCore.kt @@ -120,6 +120,14 @@ class NesCore( return NativeLibretro.nativeLoadState(path) } + override fun deleteState(slot: Int): Boolean { + val state = File(savesDir, "state_$slot.sav") + val screenshot = File(savesDir, "state_$slot.jpg") + val deleted = state.exists() && state.delete() + if (screenshot.exists()) screenshot.delete() + return deleted + } + override fun getSaveSlotInfo(slot: Int): SaveSlotInfo { val file = File(savesDir, "state_$slot.sav") val screenshot = File(savesDir, "state_$slot.jpg") diff --git a/app/src/main/java/com/lazy/emulate/emulation/cores/Ps1Core.kt b/app/src/main/java/com/lazy/emulate/emulation/cores/Ps1Core.kt index c8fe62a..07aff7a 100644 --- a/app/src/main/java/com/lazy/emulate/emulation/cores/Ps1Core.kt +++ b/app/src/main/java/com/lazy/emulate/emulation/cores/Ps1Core.kt @@ -140,6 +140,14 @@ class Ps1Core( return NativeLibretro.nativeLoadState(path) } + override fun deleteState(slot: Int): Boolean { + val state = File(savesDir, "state_$slot.sav") + val screenshot = File(savesDir, "state_$slot.jpg") + val deleted = state.exists() && state.delete() + if (screenshot.exists()) screenshot.delete() + return deleted + } + override fun getSaveSlotInfo(slot: Int): SaveSlotInfo { val file = File(savesDir, "state_$slot.sav") val screenshot = File(savesDir, "state_$slot.jpg") diff --git a/app/src/main/java/com/lazy/emulate/ui/screens/game/GameScreen.kt b/app/src/main/java/com/lazy/emulate/ui/screens/game/GameScreen.kt index 447d12f..59bbd97 100644 --- a/app/src/main/java/com/lazy/emulate/ui/screens/game/GameScreen.kt +++ b/app/src/main/java/com/lazy/emulate/ui/screens/game/GameScreen.kt @@ -27,6 +27,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.AspectRatio +import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.Menu import androidx.compose.material.icons.filled.Pause import androidx.compose.material.icons.filled.PlayArrow @@ -309,6 +310,11 @@ fun GameScreen( if (!isPaused) c.resume() showGameMenu = false }, + onDelete = { slot -> + val c = core ?: return@GameMenu + c.deleteState(slot) + saveSlots = c.getAllSaveSlots() + }, onResume = { if (!isPaused) core?.resume() showGameMenu = false @@ -436,6 +442,7 @@ private fun GameMenu( slots: List, onSave: (slot: Int) -> Unit, onLoad: (slot: Int) -> Unit, + onDelete: (slot: Int) -> Unit, onResume: () -> Unit ) { val dateFormat = remember { SimpleDateFormat("MMM d, yyyy h:mm a", Locale.getDefault()) } @@ -534,6 +541,19 @@ private fun GameMenu( ) { Text("Load", style = MaterialTheme.typography.labelMedium) } + + // Delete button + IconButton( + onClick = { onDelete(slot.slot) }, + enabled = slot.exists, + modifier = Modifier.size(36.dp) + ) { + Icon( + Icons.Default.Delete, + contentDescription = "Delete save", + tint = if (slot.exists) Color.White.copy(alpha = 0.7f) else Color.White.copy(alpha = 0.2f) + ) + } } }