Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backup Saves - automatically copies current save folder to backup location periodically #1967

Closed
wants to merge 5 commits into from

Conversation

rainmakerv3
Copy link
Contributor

Since crashes are a natural part of a complex emulator project, this PR mitigates save corruption by automatically copying the running game's save folder to a backup location.

Addresses #1909.

Backup saves can be enabled/disabled using the GUI, and the interval between backups can be configured as well. English only text has been added for the GUI, but placeholder English text is in place for each .ts file.

image

@ngoquang2708
Copy link
Contributor

I think this should somehow block savedata from creating new save while the backup is in progress to avoid corrupting of the backup, which is this PR try to avoid.

@hgh32
Copy link

hgh32 commented Dec 29, 2024

Does this support sdl too?

@Keklul404
Copy link

I can't test it right now, but could this disabled by default? (aka, the user need to actually enable it first)
It will be a real pain to constantly having to disable it everytime you want to test a new build (and seeing how many commit/builds are made per day, it will become tiresome very quickly)

@Missake212
Copy link

I can't test it right now, but could this disabled by default? (aka, the user need to actually enable it first) It will be a real pain to constantly having to disable it everytime you want to test a new build (and seeing how many commit/builds are made per day, it will become tiresome very quickly)

I just downloaded the latest commit and it's off by default already

@Keklul404
Copy link

Keklul404 commented Dec 29, 2024

Thank you

@GHU7924
Copy link

GHU7924 commented Dec 29, 2024

Nevertheless, I believe. that this function should not be automatic. I wrote my vision #1909 (comment) and consider it safer or something like that.
The response to this [Feature request] was also weak.

@rainmakerv3
Copy link
Contributor Author

rainmakerv3 commented Dec 29, 2024

I think this should somehow block savedata from creating new save while the backup is in progress to avoid corrupting of the backup, which is this PR try to avoid.

I tested this on Bloodborne (which autosaves a lot) for a couple of hours, hardcoding backups saves to occur every1 minute and couldn't seem to get any exception, (perhaps because the save directory is just read from, and not written to, or perhaps just because the files are very small) during the backup process. Since that was the case, I thought it might not be necessary to do this.

If it's decided otherwise though, I could do something like this, because I assume any saving errors would generate some sort of file access exception.

while (true) {
        std::this_thread::sleep_for(std::chrono::minutes(SaveInterval));
        bool backupsavecreated = false;
        while (backupsavecreated == false) {
            try {
                std::filesystem::copy(save_dir, backup_dir / game_serial,
                                      std::filesystem::copy_options::overwrite_existing |
                                          std::filesystem::copy_options::recursive);
                LOG_INFO(Frontend, "Backup saves created");
                backupsavecreated = true;
            } catch (std::exception& ex) {
                LOG_INFO(Frontend, "Error creating backup saves. Exception: {}\n", ex.what());
                backupsavecreated = false;
                std::this_thread::sleep_for(std::chrono::minutes(1));
            }
        }
    }

@hgh32 yes, for sdl you can edit the config file directly and it should work

@Foul-Tarnished
Copy link

Could we set a maximum number of backups ?
so it replace the oldest one automatically

@rainmakerv3
Copy link
Contributor Author

rainmakerv3 commented Dec 30, 2024

Could we set a maximum number of backups ? so it replace the oldest one automatically

Yes, I believe so. Using std::filesystem::last_write_time to check for the most recent file for each member of a set of backup directories, and setting oldest one as the next one to be written to. But I would like to leave that for a future PR if this one is merged, as I am expecting there to be some discussion on whether this feature in general is good to have on shadPS4.

@GHU7924
Copy link

GHU7924 commented Dec 30, 2024

I've been thinking about it a bit more, and I have some more ideas.
You can make 2 types of backups: manual and automatic.

Manual - makes a backup at the touch of a key (if the developers don't mind, we can use the F5 key for this)
But here you need to check if a save is currently being performed. Depending on this, you will need to display a message saying that a save is in progress, you cannot create a backup, otherwise the backup has been created.
The saving will take place in the "My Documents" folder - ShadPS4 Backup Saves.
Saving should happen for the game you are currently playing and only for it.

Automatic - occurs at a set time (as you have now).
It is desirable that this information is visible, that the function is activated, something like an FPS counter - automatic backup of the save is enabled.
Saves will occur along the way, as you have implemented now (although I have not tested your PR), but I saw the address in the description.
It is also necessary to make the game do 3 different backups, you need to add alternation, that is, slots.
For example, a save will be made every 5 minutes, the first save will be made in slot 1, the second in slot 2, the third in slot 3,
then the slots will be repeated, 1-2-3, 1-2-3, 1-2-3, and so on.

5 minutes - slot 1, 20 minutes - slot 1, 35 minutes - slot 1.
10 minutes - slot 2, 25 minutes - slot 2, 40 minutes - slot 2.
15 minutes - slot 3, 30 minutes - slot 3, 45 minutes - slot 3.

I saw that you have an interval of 5-30 minutes, you need to fix it, a minimum of 5 minutes, a maximum of 20 minutes, I think this is more than enough.

5-20 minutes and 3 slots It should be enough for everyone.

@rainmakerv3
Copy link
Contributor Author

I've been thinking about it a bit more, and I have some more ideas. You can make 2 types of backups: manual and automatic.

Manual - makes a backup at the touch of a key (if the developers don't mind, we can use the F5 key for this) But here you need to check if a save is currently being performed. Depending on this, you will need to display a message saying that a save is in progress, you cannot create a backup, otherwise the backup has been created. The saving will take place in the "My Documents" folder - ShadPS4 Backup Saves. Saving should happen for the game you are currently playing and only for it.

I'm not so sure about this manual backup, I feel that type of feature is almost the same as simply copying your save folder if you would want it. But either way, this probably can be a separate PR.

Automatic - occurs at a set time (as you have now). It is desirable that this information is visible, that the function is activated, something like an FPS counter - automatic backup of the save is enabled. Saves will occur along the way, as you have implemented now (although I have not tested your PR), but I saw the address in the description. It is also necessary to make the game do 3 different backups, you need to add alternation, that is, slots. For example, a save will be made every 5 minutes, the first save will be made in slot 1, the second in slot 2, the third in slot 3, then the slots will be repeated, 1-2-3, 1-2-3, 1-2-3, and so on.

5 minutes - slot 1, 20 minutes - slot 1, 35 minutes - slot 1. 10 minutes - slot 2, 25 minutes - slot 2, 40 minutes - slot 2. 15 minutes - slot 3, 30 minutes - slot 3, 45 minutes - slot 3.

Thinking on it more, I think this is a fairly necessary additional feature so I will include this in the next commit.

The implementation I thought of is that Backup1 is always the first backup, and then during each save creation, backup1 will be newly copied from the save directory, the previous backup1 will be transferred to backup 2, backup 2 to 3 and so on. This way, the users always know where the newest/next newest backups are. This is also more efficient than indexing all files in each backup folder for their last write times.

I saw that you have an interval of 5-30 minutes, you need to fix it, a minimum of 5 minutes, a maximum of 20 minutes, I think this is more than enough.

5-20 minutes and 3 slots It should be enough for everyone.

I mostly agree, but I also see no harm in having up to 30 minutes and 5 slots, so I think it's fine to leave it like that.

@GHU7924
Copy link

GHU7924 commented Dec 30, 2024

I'm not so sure about this manual backup, I feel that type of feature is almost the same as simply copying your save folder if you would want it. But either way, this probably can be a separate PR.

But it's a backup)) The only difference is that you do it by pressing F5, rather than looking for what to copy and where.

The implementation I thought of is that Backup1 is always the first backup, and then during each save creation, backup1 will be newly copied from the save directory, the previous backup1 will be transferred to backup 2, backup 2 to 3 and so on. This way, the users always know where the newest/next newest backups are. This is also more efficient than indexing all files in each backup folder for their last write times.

Oh, I thought about it too, but I didn't suggest it, because I don't know how difficult it is to implement and whether it will affect anything. But if you have such thoughts, then perhaps I should have suggested it))

I mostly agree, but I also see no harm in having up to 30 minutes and 5 slots, so I think it's fine to leave it like that.

I suggest this because if the time exceeds 20 minutes, you will probably have less desire to re-go through the missed time. Not everyone will want to immediately replay the missed 30 minutes again, this is a simple protection for the user.

But either way, this probably can be a separate PR.

Just rename this one to make the name more consistent with the introduction of new features.

You can also assign the F6 key to enable/disable automatic backups.

reuse

Cleanup

Additional folder check

Update translation files
@rainmakerv3
Copy link
Contributor Author

With the new commits tested, no further changes are planned, so this is ready for review

}

while (true) {
std::this_thread::sleep_for(std::chrono::minutes(SaveInterval));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably better to be in separate thread? sleep main thread can be dangerous for other primitives

Copy link
Contributor Author

@rainmakerv3 rainmakerv3 Jan 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup, this is actually running on a detached thread called here in emulator.cpp line 274:

if (Config::getBackupSaveEnabled()) {
#if (!game_info.game_serial.empty()) {
std::thread savethread(StartAutosave, game_info.game_serial);
savethread.detach();
}
}

@viniciuslrangel
Copy link
Collaborator

We already have save backups embedded. It would be better to fix the existing code

@rainmakerv3
Copy link
Contributor Author

We already have save backups embedded. It would be better to fix the existing code

Oh I wasn't aware. In this case, this PR would be redundant so I'll just close this and see if I can look at that instead

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.

9 participants