core/movie: Movie refactor, add a completion callback

This commit is contained in:
zhupengfei 2018-07-07 22:30:37 +08:00 committed by fearlessTobi
parent 6cb9a45154
commit 0f44f7b481
5 changed files with 77 additions and 47 deletions

View file

@ -118,10 +118,10 @@ struct CTMHeader {
static_assert(sizeof(CTMHeader) == 256, "CTMHeader should be 256 bytes");
#pragma pack(pop)
bool Movie::IsPlayingInput() {
bool Movie::IsPlayingInput() const {
return play_mode == PlayMode::Playing;
}
bool Movie::IsRecordingInput() {
bool Movie::IsRecordingInput() const {
return play_mode == PlayMode::Recording;
}
@ -129,6 +129,7 @@ void Movie::CheckInputEnd() {
if (current_byte + sizeof(ControllerState) > recorded_input.size()) {
LOG_INFO(Movie, "Playback finished");
play_mode = PlayMode::None;
playback_completion_callback();
}
}
@ -343,33 +344,35 @@ void Movie::Record(const Service::IR::ExtraHIDResponse& extra_hid_response) {
Record(s);
}
bool Movie::ValidateHeader(const CTMHeader& header) {
Movie::ValidationResult Movie::ValidateHeader(const CTMHeader& header) const {
if (header_magic_bytes != header.filetype) {
LOG_ERROR(Movie, "Playback file does not have valid header");
return false;
return ValidationResult::Invalid;
}
std::string revision =
Common::ArrayToString(header.revision.data(), header.revision.size(), 21, false);
revision = Common::ToLower(revision);
if (revision != Common::g_scm_rev) {
LOG_WARNING(Movie,
"This movie was created on a different version of Citra, playback may desync");
}
u64 program_id;
Core::System::GetInstance().GetAppLoader().ReadProgramId(program_id);
if (program_id != header.program_id) {
LOG_WARNING(Movie, "This movie was recorded using a ROM with a different program id");
return ValidationResult::GameDismatch;
}
return true;
if (revision != Common::g_scm_rev) {
LOG_WARNING(Movie,
"This movie was created on a different version of Citra, playback may desync");
return ValidationResult::RevisionDismatch;
}
return ValidationResult::OK;
}
void Movie::SaveMovie() {
LOG_INFO(Movie, "Saving movie");
FileUtil::IOFile save_record(Settings::values.movie_record, "wb");
LOG_INFO(Movie, "Saving recorded movie to '{}'", record_movie_file);
FileUtil::IOFile save_record(record_movie_file, "wb");
if (!save_record.IsGood()) {
LOG_ERROR(Movie, "Unable to open file to save movie");
@ -394,31 +397,45 @@ void Movie::SaveMovie() {
}
}
void Movie::Init() {
if (!Settings::values.movie_play.empty()) {
LOG_INFO(Movie, "Loading Movie for playback");
FileUtil::IOFile save_record(Settings::values.movie_play, "rb");
u64 size = save_record.GetSize();
void Movie::StartPlayback(const std::string& movie_file,
std::function<void()> completion_callback) {
LOG_INFO(Movie, "Loading Movie for playback");
FileUtil::IOFile save_record(movie_file, "rb");
const u64 size = save_record.GetSize();
if (save_record.IsGood() && size > sizeof(CTMHeader)) {
CTMHeader header;
save_record.ReadArray(&header, 1);
if (ValidateHeader(header)) {
play_mode = PlayMode::Playing;
recorded_input.resize(size - sizeof(CTMHeader));
save_record.ReadArray(recorded_input.data(), recorded_input.size());
current_byte = 0;
}
} else {
LOG_ERROR(Movie, "Failed to playback movie: Unable to open '{}'",
Settings::values.movie_play);
if (save_record.IsGood() && size > sizeof(CTMHeader)) {
CTMHeader header;
save_record.ReadArray(&header, 1);
if (ValidateHeader(header) != ValidationResult::Invalid) {
play_mode = PlayMode::Playing;
recorded_input.resize(size - sizeof(CTMHeader));
save_record.ReadArray(recorded_input.data(), recorded_input.size());
current_byte = 0;
playback_completion_callback = completion_callback;
}
} else {
LOG_ERROR(Movie, "Failed to playback movie: Unable to open '{}'", movie_file);
}
}
void Movie::StartRecording(const std::string& movie_file) {
LOG_INFO(Movie, "Enabling Movie recording");
play_mode = PlayMode::Recording;
record_movie_file = movie_file;
}
Movie::ValidationResult Movie::ValidateMovie(const std::string& movie_file) const {
LOG_INFO(Movie, "Validating Movie file '{}'", movie_file);
FileUtil::IOFile save_record(movie_file, "rb");
const u64 size = save_record.GetSize();
if (!save_record || size <= sizeof(CTMHeader)) {
return ValidationResult::Invalid;
}
if (!Settings::values.movie_record.empty()) {
LOG_INFO(Movie, "Enabling Movie recording");
play_mode = PlayMode::Recording;
}
CTMHeader header;
save_record.ReadArray(&header, 1);
return ValidateHeader(header);
}
void Movie::Shutdown() {
@ -428,6 +445,7 @@ void Movie::Shutdown() {
play_mode = PlayMode::None;
recorded_input.resize(0);
record_movie_file.clear();
current_byte = 0;
}