Skip to content

Accept .srm save file extension - #2741

Open
Davey-Hughes wants to merge 2 commits into
melonDS-emu:masterfrom
Davey-Hughes:save-file-extension
Open

Davey-Hughes wants to merge 2 commits into
melonDS-emu:masterfrom
Davey-Hughes:save-file-extension

Conversation

@Davey-Hughes

@Davey-Hughes Davey-Hughes commented Sep 3, 2026

Copy link
Copy Markdown

I use both the standalone melonDS as well as the RetroArch core, and realized the .sav files melonDS creates and the .srm files RA uses are the same files, just with a different extension. For my personal usage I don't really mind setting up softlinks but it is a bit annoying and from researching this online it's confusing for others who have to manually rename files.

This PR has 2 parts, and I think many of the UX decisions I'm very open to changing based on feedback.

Part 1: .srm selection

The first commit allows a user to set .srm as the save file extension. From a fresh setup with zero saves, this basically just equates to allowing users to point their melonDS save path to the same as where RA saves, and if you set .srm then you can seamlessly use the same saves (assuming the ROM name matches as well).

The decision this opens which I think is very much a UX decision that can change is whether to read the other file extension if it exists. Say a .srm file exists but you are using .sav then should this be detected and prompt the user to help with confusion? The decision I made was a dialogue box to tell the user that they're using a different save file extension than what's detected. (The exact wording is a result of Part 2)

image

Part 2: file conversion

"File conversion" is really just file extension renaming, and it's done using fs::rename which is an atomic operation and should be the safest way to perform this operation. I think this is both a nice UX as well as prevents file renaming mistakes. This does open some other questions about what to do when there's name collisions, such as if you had an existing filename.sav and filename.srm, and the decision here is to show in the dialogue that these files will be skipped.

The other thing this handles properly is when you use the multiple instance feature of melonDS, where files like filename.sav.2 will be properly renamed as filename.srm.2,

image

A small last detail is that an "open folder" option is added to give a convenient UX to manually copy/fix saves.

image

Testing

All four CI platforms build, and tested the rename semantics on Linux, Windows, and MacOS including case-insensitive collision (filename.srm and FILENAME.srm).

I tested this the most with the Qt Linux build, but I will update this when I am able to build and test manually in Windows. I also made a github actions test file to test some of the platform differences, but I'm not sure if we want that to be included in this PR or not. I'm happy to share it if it's helpful.

RetroArch writes DS cart saves as <romname>.srm, byte-identical to the .sav
melonDS writes, so a shared save directory ends up holding two copies of the
same data under two names with no way to make melonDS use the other one.

Add a per-instance SaveFileExtension setting, selectable in path settings,
and fall back to reading the other extension when the configured one has no
file. Writes always use the configured extension.

Reading and writing different files is not new here: for instance 2 melonDS
already reads game.sav and writes game.sav.2. This applies the same idea to a
second axis, and warns when it happens so a stale file isn't a surprise. The
warning can be dismissed permanently.

Applying a save path or extension change retargets the live SaveManager,
which flushes the in-memory save to the new path and truncates whatever is
already there. Confirm by name before doing that, since it destroys a save.

The writability check now targets the file actually written rather than the
unsuffixed path, which the old code only ever read from.
Switching the save file extension otherwise means the mismatch warning fires
on every game in a library until each has been written once under the new
name. Add a Convert button that renames the existing save files in the save
directory, listing up front exactly what will be renamed and what will be
skipped and why, and rewriting that list with the outcome afterwards.

std::filesystem::rename is used rather than copying: it is atomic within a
filesystem and never touches the file's data. It does replace an existing
destination silently, so the destination is checked immediately before each
rename and the file skipped if anything is there at all, a dangling symlink
included. Symlinks, collisions and unreadable entries are skipped, never
renamed. The multi-instance suffix is handled, so game.sav.2 becomes
game.srm.2.

A successful conversion saves the extension setting with it, since the rename
cannot be undone and the two must not disagree, and says up front that the
running game will be restarted.

Also adds a button to open the save directory.
@Davey-Hughes Davey-Hughes changed the title Save file extension Accept .srm save file extension Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant