movie: Add clock init time to CTM header
This adds a clock init time field to the CTM header. The clock settings would be overridden when playing a movie. And when recording a movie, if the clock is set to System Time, it would be set to fixed init time at the current moment as well. In this way this keeps consistency with the RNG even if the user does just no setting.
This commit is contained in:
parent
20e42592ff
commit
ae5c658997
5 changed files with 96 additions and 20 deletions
|
@ -5,6 +5,7 @@
|
|||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/optional.hpp>
|
||||
#include <cryptopp/hex.h>
|
||||
#include "common/bit_field.h"
|
||||
#include "common/common_types.h"
|
||||
|
@ -13,6 +14,7 @@
|
|||
#include "common/scm_rev.h"
|
||||
#include "common/string_util.h"
|
||||
#include "common/swap.h"
|
||||
#include "common/timer.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/service/hid/hid.h"
|
||||
#include "core/hle/service/ir/extra_hid.h"
|
||||
|
@ -112,8 +114,9 @@ struct CTMHeader {
|
|||
std::array<u8, 4> filetype; /// Unique Identifier to check the file type (always "CTM"0x1B)
|
||||
u64_le program_id; /// ID of the ROM being executed. Also called title_id
|
||||
std::array<u8, 20> revision; /// Git hash of the revision this movie was created with
|
||||
u64_le clock_init_time; /// The init time of the system clock
|
||||
|
||||
std::array<u8, 224> reserved; /// Make heading 256 bytes so it has consistent size
|
||||
std::array<u8, 216> reserved; /// Make heading 256 bytes so it has consistent size
|
||||
};
|
||||
static_assert(sizeof(CTMHeader) == 256, "CTMHeader should be 256 bytes");
|
||||
#pragma pack(pop)
|
||||
|
@ -129,6 +132,7 @@ void Movie::CheckInputEnd() {
|
|||
if (current_byte + sizeof(ControllerState) > recorded_input.size()) {
|
||||
LOG_INFO(Movie, "Playback finished");
|
||||
play_mode = PlayMode::None;
|
||||
init_time = 0;
|
||||
playback_completion_callback();
|
||||
}
|
||||
}
|
||||
|
@ -344,6 +348,10 @@ void Movie::Record(const Service::IR::ExtraHIDResponse& extra_hid_response) {
|
|||
Record(s);
|
||||
}
|
||||
|
||||
u64 Movie::GetOverrideInitTime() const {
|
||||
return init_time;
|
||||
}
|
||||
|
||||
Movie::ValidationResult Movie::ValidateHeader(const CTMHeader& header, u64 program_id) const {
|
||||
if (header_magic_bytes != header.filetype) {
|
||||
LOG_ERROR(Movie, "Playback file does not have valid header");
|
||||
|
@ -381,6 +389,7 @@ void Movie::SaveMovie() {
|
|||
|
||||
CTMHeader header = {};
|
||||
header.filetype = header_magic_bytes;
|
||||
header.clock_init_time = init_time;
|
||||
|
||||
Core::System::GetInstance().GetAppLoader().ReadProgramId(header.program_id);
|
||||
|
||||
|
@ -424,36 +433,53 @@ void Movie::StartRecording(const std::string& movie_file) {
|
|||
record_movie_file = movie_file;
|
||||
}
|
||||
|
||||
Movie::ValidationResult Movie::ValidateMovie(const std::string& movie_file, u64 program_id) const {
|
||||
LOG_INFO(Movie, "Validating Movie file '{}'", movie_file);
|
||||
static boost::optional<CTMHeader> ReadHeader(const std::string& movie_file) {
|
||||
FileUtil::IOFile save_record(movie_file, "rb");
|
||||
const u64 size = save_record.GetSize();
|
||||
|
||||
if (!save_record || size <= sizeof(CTMHeader)) {
|
||||
return ValidationResult::Invalid;
|
||||
}
|
||||
|
||||
CTMHeader header;
|
||||
save_record.ReadArray(&header, 1);
|
||||
return ValidateHeader(header, program_id);
|
||||
}
|
||||
|
||||
u64 Movie::GetMovieProgramID(const std::string& movie_file) const {
|
||||
FileUtil::IOFile save_record(movie_file, "rb");
|
||||
const u64 size = save_record.GetSize();
|
||||
|
||||
if (!save_record || size <= sizeof(CTMHeader)) {
|
||||
return 0;
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
CTMHeader header;
|
||||
save_record.ReadArray(&header, 1);
|
||||
|
||||
if (header_magic_bytes != header.filetype) {
|
||||
return 0;
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
return static_cast<u64>(header.program_id);
|
||||
return header;
|
||||
}
|
||||
|
||||
void Movie::PrepareForPlayback(const std::string& movie_file) {
|
||||
auto header = ReadHeader(movie_file);
|
||||
if (header != boost::none)
|
||||
return;
|
||||
|
||||
init_time = header.value().clock_init_time;
|
||||
}
|
||||
|
||||
void Movie::PrepareForRecording() {
|
||||
init_time = (Settings::values.init_clock == Settings::InitClock::SystemTime
|
||||
? Common::Timer::GetTimeSinceJan1970().count()
|
||||
: Settings::values.init_time);
|
||||
}
|
||||
|
||||
Movie::ValidationResult Movie::ValidateMovie(const std::string& movie_file, u64 program_id) const {
|
||||
LOG_INFO(Movie, "Validating Movie file '{}'", movie_file);
|
||||
auto header = ReadHeader(movie_file);
|
||||
if (header != boost::none)
|
||||
return ValidationResult::Invalid;
|
||||
|
||||
return ValidateHeader(header.value(), program_id);
|
||||
}
|
||||
|
||||
u64 Movie::GetMovieProgramID(const std::string& movie_file) const {
|
||||
auto header = ReadHeader(movie_file);
|
||||
if (header != boost::none)
|
||||
return 0;
|
||||
|
||||
return static_cast<u64>(header.value().program_id);
|
||||
}
|
||||
|
||||
void Movie::Shutdown() {
|
||||
|
@ -465,6 +491,7 @@ void Movie::Shutdown() {
|
|||
recorded_input.resize(0);
|
||||
record_movie_file.clear();
|
||||
current_byte = 0;
|
||||
init_time = 0;
|
||||
}
|
||||
|
||||
template <typename... Targs>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue