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.
This commit is contained in:
2026-04-10 19:36:04 -04:00
parent 981ac2eed9
commit 2e41f1e6ea
4 changed files with 38 additions and 0 deletions

View File

@@ -42,6 +42,8 @@ interface EmulatorCore {
fun loadState(slot: Int): Boolean fun loadState(slot: Int): Boolean
fun deleteState(slot: Int): Boolean = false
fun getSaveSlotInfo(slot: Int): SaveSlotInfo fun getSaveSlotInfo(slot: Int): SaveSlotInfo
fun getScreenshotPath(slot: Int): String? = null fun getScreenshotPath(slot: Int): String? = null

View File

@@ -120,6 +120,14 @@ class NesCore(
return NativeLibretro.nativeLoadState(path) 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 { override fun getSaveSlotInfo(slot: Int): SaveSlotInfo {
val file = File(savesDir, "state_$slot.sav") val file = File(savesDir, "state_$slot.sav")
val screenshot = File(savesDir, "state_$slot.jpg") val screenshot = File(savesDir, "state_$slot.jpg")

View File

@@ -140,6 +140,14 @@ class Ps1Core(
return NativeLibretro.nativeLoadState(path) 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 { override fun getSaveSlotInfo(slot: Int): SaveSlotInfo {
val file = File(savesDir, "state_$slot.sav") val file = File(savesDir, "state_$slot.sav")
val screenshot = File(savesDir, "state_$slot.jpg") val screenshot = File(savesDir, "state_$slot.jpg")

View File

@@ -27,6 +27,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.AspectRatio 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.Menu
import androidx.compose.material.icons.filled.Pause import androidx.compose.material.icons.filled.Pause
import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material.icons.filled.PlayArrow
@@ -309,6 +310,11 @@ fun GameScreen(
if (!isPaused) c.resume() if (!isPaused) c.resume()
showGameMenu = false showGameMenu = false
}, },
onDelete = { slot ->
val c = core ?: return@GameMenu
c.deleteState(slot)
saveSlots = c.getAllSaveSlots()
},
onResume = { onResume = {
if (!isPaused) core?.resume() if (!isPaused) core?.resume()
showGameMenu = false showGameMenu = false
@@ -436,6 +442,7 @@ private fun GameMenu(
slots: List<SaveSlotInfo>, slots: List<SaveSlotInfo>,
onSave: (slot: Int) -> Unit, onSave: (slot: Int) -> Unit,
onLoad: (slot: Int) -> Unit, onLoad: (slot: Int) -> Unit,
onDelete: (slot: Int) -> Unit,
onResume: () -> Unit onResume: () -> Unit
) { ) {
val dateFormat = remember { SimpleDateFormat("MMM d, yyyy h:mm a", Locale.getDefault()) } 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) 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)
)
}
} }
} }