Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions src/program/GameEvents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ bool GameEvents::processEvent(GameEvents::EventType type, const HotKey &hk)
* Prompting a alert window must be done by the UI thread, so we are
* using std::future/std::promise mechanism.
*/
int frame_to_seek;
std::promise<bool> answer;
std::future<bool> future = answer.get_future();
emit askToShow(QString("There is a savestate in that slot from a previous game iteration. Do you want to load the associated movie?"), &answer);
Expand All @@ -220,17 +221,25 @@ bool GameEvents::processEvent(GameEvents::EventType type, const HotKey &hk)
return false;
}

/* Loading the movie */
movie->loadSavestateMovie(SaveStateList::get(statei).getMoviePath());
SaveState& s = SaveStateList::get(statei);
movie->inputs = s.movie->inputs;
s.save(context, *movie);

/* Return if we already are on the correct frame */
if (context->framecount == movie->header->savestate_framecount)
return false;
/* seek to either the current frame, or the max frame
* of the saved inputs */
if (s.movie->inputs->nbFrames() < context->framecount) {
frame_to_seek = context->framecount;
} else {
frame_to_seek = s.movie->inputs->nbFrames();
}

/* Find where movies diverge, load state and seek back there */
// todo

/* Fast-forward to savestate frame */
context->config.sc.recording = SharedConfig::RECORDING_READ;
context->config.sc.movie_framecount = movie->inputs->nbFrames();
context->seek_frame = movie->header->savestate_framecount;
context->config.sc.movie_framecount = s.movie->inputs->nbFrames();
context->seek_frame = frame_to_seek;
context->config.sc.running = true;
context->config.sc_modified = true;

Expand All @@ -239,6 +248,12 @@ bool GameEvents::processEvent(GameEvents::EventType type, const HotKey &hk)
return false;
}

if (error == SaveState::ESAVESTATEINPUTMISMATCH) {
if (!(context->config.sc.osd))
emit alertToShow(QString("Cannot load inputs from this savestate as earlier inputs mismatch. Please seek to an earlier state for this."));
return false;
}

if (error == SaveState::ENOSTATE) {
if (!(context->config.sc.osd))
emit alertToShow(QString("There is no savestate to load in this slot"));
Expand Down
32 changes: 15 additions & 17 deletions src/program/SaveState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,26 +120,24 @@ int SaveState::load(Context* context, const MovieFile& m, bool branch, bool inpu
* forked savestate of previous execution). */
if ((access(pagemap_path.c_str(), F_OK) != 0) || (access(pages_path.c_str(), F_OK) != 0) ||
(framecount == 0)) {
/* If there is no savestate but a movie file, offer to load
* the movie and fast-forward to the savestate movie frame.
/* If there is no savestate but inputs are saved in the save
* file, offer to load the movie and fast-forward to the
* savestate movie frame.
*/

if ((context->config.sc.recording != SharedConfig::NO_RECORDING) &&
(access(movie_path.c_str(), F_OK) == 0)) {

/* Load the savestate movie from disk */
MovieFile savedmovie(context);
int ret = savedmovie.loadSavestateMovie(movie_path);

/* Checking if our movie is a prefix of the savestate movie */
if ((ret == 0) && savedmovie.inputs->isEqual(m.inputs, 0, context->framecount)) {
return ENOSTATEMOVIEPREFIX;
}
/* Checking if our movie is a prefix of the savestate movie
* and if savestatefile input exists */
if (movie->inputs->nbFrames() > 0 && movie->inputs->isEqual(m.inputs, 0, context->framecount)) {
return ENOSTATEMOVIEPREFIX;
} else if (movie->inputs->nbFrames() > 0) {
sendMessage(MSGN_OSD_MSG);
sendString(std::string("Cannot load inputs from this savestate as earlier inputs mismatch"));
return ESAVESTATEINPUTMISMATCH;
} else {
sendMessage(MSGN_OSD_MSG);
sendString(no_state_msg);
return ENOSTATE;
}

sendMessage(MSGN_OSD_MSG);
sendString(no_state_msg);
return ENOSTATE;
}

/* Send the savestate index */
Expand Down
1 change: 1 addition & 0 deletions src/program/SaveState.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class SaveState {
ENOMOVIE = -3, // Could not moad movie
EINPUTMISMATCH = -4, // Mistmatch inputs
ENOLOAD = -5, // State loading failed
ESAVESTATEINPUTMISMATCH = -6, // Mismatch inputs with savestate file
};

/* Savestate number */
Expand Down
30 changes: 30 additions & 0 deletions src/program/movie/MovieFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,14 @@

#include "../shared/inputs/AllInputs.h"
#include "Context.h"
#include "SaveStateList.h"
#include "SaveState.h"

#include <sstream>
#include <iostream>
#include <filesystem>
#include <fstream>
#include <filesystem>
#include <fcntl.h> // O_RDONLY, O_WRONLY, O_CREAT
#include <errno.h>
#include <unistd.h>
Expand Down Expand Up @@ -84,6 +89,10 @@ int MovieFile::extractMovie(const std::string& moviefile)
unlink(configfile.c_str());
unlink(editorfile.c_str());
unlink(inputfile.c_str());
for (int i = 1; i <= 10; i++) {
std::filesystem::path p = std::filesystem::path(context->config.tempmoviedir) / ("inputs" + std::to_string(i));
unlink(p.c_str());
}
unlink(annotationsfile.c_str());

/* Build the tar command */
Expand Down Expand Up @@ -143,6 +152,20 @@ int MovieFile::loadMovie(const std::string& moviefile)
context->config.sc.movie_framecount = inputs->nbFrames();
}

/* Load savestate inputs */
for (int i = 1; i <= 10; i++) {
std::filesystem::path p = std::filesystem::path(context->config.tempmoviedir) / ("inputs" + std::to_string(i));

if (std::filesystem::exists(p)) {
SaveState& s = SaveStateList::get(i);
if (!s.movie)
s.movie = std::make_unique<MovieFile>(context);

s.movie->inputs->load(i);
s.framecount = s.movie->inputs->nbFrames();
}
}

return 0;
}

Expand Down Expand Up @@ -188,6 +211,13 @@ int MovieFile::saveMovie(const std::string& moviefile, uint64_t nb_frames)
oss << "\" -C ";
oss << context->config.tempmoviedir;
oss << " inputs config.ini editor.ini annotations.txt";
// Add only savestate input files that exist
for (int i = 1; i <= 10; i++) {
std::filesystem::path p = std::filesystem::path(context->config.tempmoviedir) / ("inputs" + std::to_string(i));
if (std::filesystem::exists(p)) {
oss << " inputs" << i;
}
}

/* Execute the tar command */
// std::cout << oss.str() << std::endl;
Expand Down
20 changes: 18 additions & 2 deletions src/program/movie/MovieFileInputs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "MovieActionInsertFrames.h"
#include "MovieActionPaint.h"
#include "MovieActionRemoveFrames.h"
#include "SaveStateList.h"
#include "SaveState.h"

#include "utils.h"
#include "Context.h"
Expand Down Expand Up @@ -74,7 +76,7 @@ void MovieFileInputs::clear()
emit inputsReset();
}

void MovieFileInputs::load()
void MovieFileInputs::load(int savestate)
{
emit inputsToBeReset();

Expand All @@ -87,6 +89,9 @@ void MovieFileInputs::load()

/* Open the input file and parse each line to fill our input list */
std::string input_file = context->config.tempmoviedir + "/inputs";
if (savestate > 0) {
input_file += std::to_string(savestate);
}
std::ifstream input_stream(input_file);

InputSerialization::readInputs(input_stream, input_list);
Expand All @@ -105,8 +110,19 @@ void MovieFileInputs::save()
std::ofstream input_stream(input_file, std::ofstream::trunc);

InputSerialization::writeInputs(input_stream, input_list);

input_stream.close();

// Save branches inputs
for (int i = 0; i <= 10; i++) {
SaveState& s = SaveStateList::get(i);
if (s.framecount != 0 && s.movie && s.movie->inputs) {
std::string branch_input_file = context->config.tempmoviedir + "/inputs" + std::to_string(i);
std::ofstream branch_stream(branch_input_file, std::ofstream::trunc);
InputSerialization::writeInputs(branch_stream, s.movie->inputs->input_list);
branch_stream.close();
}
}

}

uint64_t MovieFileInputs::nbFrames()
Expand Down
2 changes: 1 addition & 1 deletion src/program/movie/MovieFileInputs.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class MovieFileInputs : public QObject {

/* Import the inputs into a list, and all the parameters.
* Returns 0 if no error, or a negative value if an error occured */
void load();
void load(int savestate = 0);

/* Write the inputs into a file and compress to the whole moviefile */
void save();
Expand Down