mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-21 02:09:05 +02:00
Loading a state from the pause menu closed it right away, and the game ran a few frames from where it was (seen and heard) before the state was applied. Now savestate operations run while the game is paused under the menu, and the menu closes once the load (or rewind, or load undo) is done. Rewind snapshots aren't taken while paused. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
155 lines
6.1 KiB
C++
155 lines
6.1 KiB
C++
// Copyright (c) 2012- PPSSPP Project.
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, version 2.0 or later versions.
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License 2.0 for more details.
|
|
|
|
// A copy of the GPL 2.0 should have been included with the program.
|
|
// If not, see http://www.gnu.org/licenses/
|
|
|
|
// Official git repository and contact information can be found at
|
|
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
|
|
|
#pragma once
|
|
|
|
#include <functional>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
#include "Common/File/Path.h"
|
|
#include "Common/Serialize/Serializer.h"
|
|
|
|
class ParamSFOData;
|
|
#undef Process
|
|
|
|
namespace SaveState {
|
|
enum class Status {
|
|
FAILURE,
|
|
WARNING,
|
|
SUCCESS,
|
|
};
|
|
typedef std::function<void(Status status, std::string_view message, std::string_view metadata)> Callback;
|
|
|
|
// The whole state, for CChunkFileReader. libretro uses it directly.
|
|
struct SaveStart {
|
|
void DoState(PointerWrap &p);
|
|
// Rewind snapshots and verification don't count towards IsStale().
|
|
bool countsAsSave = true;
|
|
};
|
|
|
|
static const char * const SCREENSHOT_EXTENSION = "jpg";
|
|
|
|
void Init();
|
|
void Shutdown();
|
|
|
|
// Cycle through the 5 savestate slots
|
|
void PrevSlot();
|
|
void NextSlot();
|
|
|
|
std::string GetGamePrefix(const ParamSFOData ¶mSFO);
|
|
|
|
// Run the various actions directly.
|
|
void SaveSlot(std::string_view gamePrefix, int slot, Callback callback);
|
|
void LoadSlot(std::string_view gamePrefix, int slot, Callback callback);
|
|
bool UndoSaveSlot(std::string_view gamePrefix, int slot);
|
|
bool UndoLastSave(std::string_view gamePrefix);
|
|
bool UndoLoad(std::string_view gamePrefix, Callback callback);
|
|
void DeleteSlot(std::string_view gamePrefix, int slot);
|
|
|
|
// This will rescan the save state directory for files associated with the specified game.
|
|
// Note that when we have many save states, this is really important on Android.
|
|
void Rescan(std::string_view gamePrefix);
|
|
|
|
// Checks whether there's an existing save in the specified slot.
|
|
bool HasSaveInSlot(std::string_view gamePrefix, int slot);
|
|
bool HasUndoSaveInSlot(std::string_view gamePrefix, int slot);
|
|
bool HasUndoLastSave(std::string_view gamePrefix);
|
|
bool HasUndoLoad(std::string_view gamePrefix);
|
|
bool HasScreenshotInSlot(std::string_view gamePrefix, int slot);
|
|
|
|
// Just returns the current slot from config.
|
|
int GetCurrentSlot();
|
|
|
|
// Returns -1 if there's no oldest/newest slot.
|
|
int GetNewestSlot(std::string_view gamePrefix);
|
|
int GetOldestSlot(std::string_view gamePrefix);
|
|
|
|
std::string GetSlotDateAsString(std::string_view gamePrefix, int slot);
|
|
|
|
std::string GetSlotCustomName(std::string_view gamePrefix, int slot);
|
|
Path GenerateSaveSlotPath(std::string_view gamePrefix, int slot, const char *extension);
|
|
void SetSlotCustomName(std::string_view gamePrefix, int slot, std::string_view newName);
|
|
|
|
// The files that sit beside a savestate and mean nothing without it: its screenshot, and the
|
|
// slot's custom name if it was given one. Anything deleting a .ppst from outside DeleteSlot -
|
|
// the savestate browser does exactly that - has to take these along, or they stay in the
|
|
// savestate folder for good. Returns nothing for a path that isn't a savestate.
|
|
std::vector<Path> GetCompanionFilePaths(const Path &statePath);
|
|
|
|
std::string GetTitle(const Path &filename);
|
|
|
|
// Load the specified file into the current state (async.) The file is read while emulation goes
|
|
// on, and the state applied in a later Process().
|
|
// Returns true if queued. The callback runs from Process(), once the state has been applied.
|
|
bool Load(const Path &filename, int slot, Callback callback = Callback());
|
|
|
|
// Save the current state to the specified file (async.) The state is captured in the next
|
|
// Process(), and compressed and written on the worker.
|
|
// Returns true if queued. The callback runs from Process(), once the file has been written.
|
|
// Saving to a path that already has a save pending counts as a repeat of that save.
|
|
bool Save(const Path &filename, int slot, Callback callback = Callback());
|
|
|
|
CChunkFileReader::Error SaveToRam(std::vector<u8> &state);
|
|
CChunkFileReader::Error LoadFromRam(std::vector<u8> &state, std::string *errorString);
|
|
|
|
// For testing / automated tests. Runs a save state verification pass (async.)
|
|
// The callback runs from Process().
|
|
bool Verify(Callback callback = Callback());
|
|
|
|
// To go back to a previous snapshot (only if enabled.)
|
|
// The callback runs from Process(), once the snapshot has been applied.
|
|
bool Rewind(Callback callback = Callback());
|
|
|
|
// Returns true if there are rewind snapshots available.
|
|
bool CanRewind();
|
|
|
|
// Returns true while a save, load or rewind is queued or still in progress (rewind snapshots
|
|
// don't count). Saves are done once the file is written.
|
|
bool IsBusy();
|
|
|
|
// Returns true if a savestate has been used during this session.
|
|
bool HasLoadedState();
|
|
|
|
// Returns true if the state has been reused instead of real saves many times.
|
|
bool IsStale();
|
|
|
|
// Returns true if state is from an older PPSSPP version.
|
|
bool IsOldVersion();
|
|
|
|
// Check if there's any save stating needing to be done. Normally called once per frame.
|
|
// While the game is paused (under the pause menu, say), pass false: there's nothing new to take
|
|
// rewind snapshots of.
|
|
void Process(bool takeRewindSnapshots = true);
|
|
|
|
// Notify save state code that new save data has been written.
|
|
void NotifySaveData();
|
|
|
|
// Checks whether a bad load required the caller to trigger a restart (and if returns true, resets the flag internally).
|
|
bool PollRestartNeeded();
|
|
|
|
// Returns the time since last save. -1 if N/A.
|
|
double SecondsSinceLastSavestate();
|
|
|
|
// The savestate worker thread, for compression and file I/O away from the emu thread. Jobs run
|
|
// one at a time, in the order they were queued, and mustn't touch emulator state.
|
|
void RunOnWorker(std::function<void()> job);
|
|
// Waits until every job queued so far has finished.
|
|
void WaitForWorker();
|
|
} // namespace SaveState
|