mirror of https://github.com/PCSX2/pcsx2.git
recording: recording file implementation
This commit is contained in:
parent
94c160401c
commit
5fefe28e39
|
@ -0,0 +1,464 @@
|
|||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "MemoryTypes.h"
|
||||
#include "App.h"
|
||||
#include "Common.h"
|
||||
#include "Counters.h"
|
||||
|
||||
#include "InputRecordingFile.h"
|
||||
|
||||
#define HEADER_SIZE (sizeof(InputRecordingHeader)+4+4)
|
||||
#define SAVESTATE_HEADER_SIZE (sizeof(bool) + sizeof(savestate.savestatesize) + sizeof(savestate.savestate[0]) * savestate.savestatesize)
|
||||
#define BLOCK_HEADER_SIZE (0)
|
||||
#define BLOCK_DATA_SIZE (18*2)
|
||||
#define BLOCK_SIZE (BLOCK_HEADER_SIZE+BLOCK_DATA_SIZE)
|
||||
|
||||
#define SEEKPOINT_FRAMEMAX (sizeof(InputRecordingHeader))
|
||||
#define SEEKPOINT_UNDOCOUNT (sizeof(InputRecordingHeader)+4)
|
||||
#define SEEKPOINT_SAVESTATE (SEEKPOINT_UNDOCOUNT+4)
|
||||
|
||||
long InputRecordingFile::_getBlockSeekPoint(const long & frame)
|
||||
{
|
||||
if (savestate.fromSavestate) {
|
||||
return HEADER_SIZE
|
||||
+ SAVESTATE_HEADER_SIZE
|
||||
+ frame * BLOCK_SIZE;
|
||||
}
|
||||
else {
|
||||
return HEADER_SIZE + sizeof(bool) + (frame)*BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
// Temporary Shim, probably a better cross-platform way to correct usages of fopen_s
|
||||
int fopen_s(FILE **f, const char *name, const char *mode) {
|
||||
int ret = 0;
|
||||
assert(f);
|
||||
*f = fopen(name, mode);
|
||||
if (!*f)
|
||||
ret = errno;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//----------------------------------
|
||||
// file
|
||||
//----------------------------------
|
||||
bool InputRecordingFile::Open(const wxString fn, bool fNewOpen, VmStateBuffer *ss)
|
||||
{
|
||||
Close();
|
||||
wxString mode = L"rb+";
|
||||
if (fNewOpen) {
|
||||
mode = L"wb+";
|
||||
MaxFrame = 0;
|
||||
UndoCount = 0;
|
||||
header.init();
|
||||
}
|
||||
if ( fopen_s(&fp, fn.c_str(), mode.c_str()) != 0)
|
||||
{
|
||||
recordingConLog(wxString::Format("[REC]: Movie file opening failed. Error - %s\n", strerror(errno)));
|
||||
return false;
|
||||
}
|
||||
filename = fn;
|
||||
|
||||
if (fNewOpen) {
|
||||
if (ss) {
|
||||
savestate.fromSavestate = true;
|
||||
savestate.savestatesize = ss->GetLength();
|
||||
savestate.savestate.MakeRoomFor(ss->GetLength());
|
||||
for (size_t i = 0; i < ss->GetLength(); i++) {
|
||||
savestate.savestate[i] = (*ss)[i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
sApp.SysExecute();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool InputRecordingFile::Close()
|
||||
{
|
||||
if (fp == NULL)return false;
|
||||
writeHeader();
|
||||
writeSavestate();
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
filename = "";
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------
|
||||
// write frame
|
||||
//----------------------------------
|
||||
bool InputRecordingFile::writeKeyBuf(const uint & frame, const uint port, const uint bufIndex, const u8 & buf)
|
||||
{
|
||||
if (fp == NULL)return false;
|
||||
|
||||
long seek = _getBlockSeekPoint(frame) + BLOCK_HEADER_SIZE + 18 * port + bufIndex;
|
||||
if (fseek(fp, seek, SEEK_SET) != 0){
|
||||
return false;
|
||||
}
|
||||
if (fwrite(&buf, 1, 1, fp) != 1) {
|
||||
return false;
|
||||
}
|
||||
fflush(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------
|
||||
// read frame
|
||||
//----------------------------------
|
||||
bool InputRecordingFile::readKeyBuf(u8 & result,const uint & frame, const uint port, const uint bufIndex)
|
||||
{
|
||||
if (fp == NULL)return false;
|
||||
|
||||
long seek = _getBlockSeekPoint(frame) + BLOCK_HEADER_SIZE + 18 * port + bufIndex;
|
||||
if (fseek(fp, seek, SEEK_SET) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (fread(&result, 1, 1, fp) != 1) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//===================================
|
||||
// pad
|
||||
//===================================
|
||||
void InputRecordingFile::getPadData(PadData & result, unsigned long frame)
|
||||
{
|
||||
result.fExistKey = false;
|
||||
if (fp == NULL)return;
|
||||
long seek = _getBlockSeekPoint(frame) + BLOCK_HEADER_SIZE;
|
||||
if (fseek(fp, seek, SEEK_SET) != 0)return;
|
||||
if (fread(result.buf, 1, BLOCK_DATA_SIZE, fp) == 0)return;
|
||||
result.fExistKey = true;
|
||||
}
|
||||
bool InputRecordingFile::DeletePadData(unsigned long frame)
|
||||
{
|
||||
if (fp == NULL)return false;
|
||||
|
||||
for (unsigned long i = frame; i < MaxFrame - 1; i++)
|
||||
{
|
||||
long seek1 = _getBlockSeekPoint(i+1) + BLOCK_HEADER_SIZE;
|
||||
long seek2 = _getBlockSeekPoint(i) + BLOCK_HEADER_SIZE;
|
||||
|
||||
u8 buf[2][18];
|
||||
fseek(fp, seek1, SEEK_SET);
|
||||
fread(buf, 1, BLOCK_DATA_SIZE, fp);
|
||||
fseek(fp, seek2, SEEK_SET);
|
||||
fwrite(buf,1, BLOCK_DATA_SIZE, fp);
|
||||
}
|
||||
MaxFrame--;
|
||||
writeMaxFrame();
|
||||
fflush(fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool InputRecordingFile::InsertPadData(unsigned long frame, const PadData& key)
|
||||
{
|
||||
if (fp == NULL)return false;
|
||||
if (!key.fExistKey)return false;
|
||||
|
||||
for (unsigned long i = MaxFrame - 1; i >= frame; i--)
|
||||
{
|
||||
long seek1 = _getBlockSeekPoint(i) + BLOCK_HEADER_SIZE;
|
||||
long seek2 = _getBlockSeekPoint(i+1) + BLOCK_HEADER_SIZE;
|
||||
|
||||
u8 buf[2][18];
|
||||
fseek(fp, seek1, SEEK_SET);
|
||||
fread(buf, 1, BLOCK_DATA_SIZE, fp);
|
||||
fseek(fp, seek2, SEEK_SET);
|
||||
fwrite(buf, 1, BLOCK_DATA_SIZE, fp);
|
||||
}
|
||||
{
|
||||
long seek = _getBlockSeekPoint(frame) + BLOCK_HEADER_SIZE;
|
||||
fseek(fp, seek, SEEK_SET);
|
||||
fwrite(key.buf, 1, BLOCK_DATA_SIZE, fp);
|
||||
}
|
||||
MaxFrame++;
|
||||
writeMaxFrame();
|
||||
fflush(fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool InputRecordingFile::UpdatePadData(unsigned long frame, const PadData& key)
|
||||
{
|
||||
if (fp == NULL)return false;
|
||||
if (!key.fExistKey)return false;
|
||||
|
||||
long seek = _getBlockSeekPoint(frame) + BLOCK_HEADER_SIZE;
|
||||
fseek(fp, seek, SEEK_SET);
|
||||
if (fwrite(key.buf, 1, BLOCK_DATA_SIZE, fp) == 0)return false;
|
||||
|
||||
fflush(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//===================================
|
||||
// header
|
||||
//===================================
|
||||
bool InputRecordingFile::readHeaderAndCheck()
|
||||
{
|
||||
if (fp == NULL)return false;
|
||||
rewind(fp);
|
||||
if (fread(&header, sizeof(InputRecordingHeader), 1, fp) != 1)return false;
|
||||
if (fread(&MaxFrame, 4, 1, fp) != 1)return false;
|
||||
if (fread(&UndoCount, 4, 1, fp) != 1)return false;
|
||||
if (fread(&savestate.fromSavestate, sizeof(bool), 1, fp) != 1) return false;
|
||||
if (savestate.fromSavestate) {
|
||||
// We read the size (and the savestate) only if we must
|
||||
if (fread(&savestate.savestatesize, sizeof(savestate.savestatesize), 1, fp) != 1) return false;
|
||||
if (savestate.savestatesize == 0) {
|
||||
recordingConLog(L"[REC]: Invalid size of the savestate.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
savestate.savestate.MakeRoomFor(savestate.savestatesize);
|
||||
// We read "savestatesize" * the size of a cell
|
||||
if (fread(savestate.savestate.GetPtr(), sizeof(savestate.savestate[0]), savestate.savestatesize, fp)
|
||||
!= savestate.savestatesize) return false;
|
||||
|
||||
// We load the savestate
|
||||
memLoadingState load(savestate.savestate);
|
||||
UI_DisableSysActions();
|
||||
GetCoreThread().Pause();
|
||||
SysClearExecutionCache();
|
||||
load.FreezeAll();
|
||||
GetCoreThread().Resume();
|
||||
}
|
||||
else {
|
||||
sApp.SysExecute();
|
||||
}
|
||||
|
||||
// ID
|
||||
if (header.ID != 0xCC) {
|
||||
return false;
|
||||
}
|
||||
// ver
|
||||
if (header.version != 3) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool InputRecordingFile::writeHeader()
|
||||
{
|
||||
if (fp == NULL)return false;
|
||||
rewind(fp);
|
||||
if (fwrite(&header, sizeof(InputRecordingHeader), 1, fp) != 1) return false;
|
||||
return true;
|
||||
}
|
||||
bool InputRecordingFile::writeSavestate()
|
||||
{
|
||||
if (fp == NULL) return false;
|
||||
fseek(fp, SEEKPOINT_SAVESTATE, SEEK_SET);
|
||||
if (fwrite(&savestate.fromSavestate, sizeof(bool), 1, fp) != 1) return false;
|
||||
|
||||
if (savestate.fromSavestate) {
|
||||
if (fwrite(&savestate.savestatesize, sizeof(savestate.savestatesize), 1, fp) != 1) return false;
|
||||
if (fwrite(savestate.savestate.GetPtr(), sizeof(savestate.savestate[0]), savestate.savestatesize, fp)
|
||||
!= savestate.savestatesize) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool InputRecordingFile::writeMaxFrame()
|
||||
{
|
||||
if (fp == NULL)return false;
|
||||
fseek(fp, SEEKPOINT_FRAMEMAX, SEEK_SET);
|
||||
if (fwrite(&MaxFrame, 4, 1, fp) != 1) return false;
|
||||
return true;
|
||||
}
|
||||
void InputRecordingFile::updateFrameMax(unsigned long frame)
|
||||
{
|
||||
if (MaxFrame >= frame) {
|
||||
return;
|
||||
}
|
||||
MaxFrame = frame;
|
||||
if (fp == NULL)return ;
|
||||
fseek(fp, SEEKPOINT_FRAMEMAX, SEEK_SET);
|
||||
fwrite(&MaxFrame, 4, 1, fp);
|
||||
}
|
||||
void InputRecordingFile::addUndoCount()
|
||||
{
|
||||
UndoCount++;
|
||||
if (fp == NULL)return;
|
||||
fseek(fp, SEEKPOINT_UNDOCOUNT, SEEK_SET);
|
||||
fwrite(&UndoCount, 4, 1, fp);
|
||||
|
||||
}
|
||||
|
||||
void InputRecordingHeader::setAuthor(wxString _author)
|
||||
{
|
||||
int max = ArraySize(author) - 1;
|
||||
strncpy(author, _author.c_str(), max);
|
||||
author[max] = 0;
|
||||
}
|
||||
void InputRecordingHeader::setCdrom(wxString _cdrom)
|
||||
{
|
||||
int max = ArraySize(cdrom) - 1;
|
||||
strncpy(cdrom, _cdrom.c_str(), max);
|
||||
cdrom[max] = 0;
|
||||
}
|
||||
void InputRecordingHeader::init()
|
||||
{
|
||||
memset(author, 0, ArraySize(author));
|
||||
memset(cdrom, 0, ArraySize(cdrom));
|
||||
}
|
||||
|
||||
void InputRecordingFile::ConvertV2ToV3(wxString filename)
|
||||
{
|
||||
// TODO, with the latest version of save states requiring a savestate integrated into the file
|
||||
// or it restarts as it assumes it is from power-on
|
||||
// I don't see how save states would be compatible
|
||||
}
|
||||
|
||||
|
||||
//===========================================================
|
||||
// ver 1.0~1.2 -> ver 2.0~
|
||||
// If the file does not have a version header, then we can assume it is prior to version....3?
|
||||
// takes far too long to iterate through with the new format because of the large space reserved for
|
||||
// the save state(s)
|
||||
//
|
||||
// Note - Save states are not even compatible from these two versions of PCSX2
|
||||
//===========================================================
|
||||
void InputRecordingFile::ConvertV1_XToV2(wxString filename)
|
||||
{
|
||||
recordingConLog(wxString::Format(L"[REC]: Conversion started - [%s]\n", WX_STR(filename)));
|
||||
FILE * fp;
|
||||
FILE * fp2;
|
||||
fopen_s(&fp, filename, "rb");
|
||||
if (fp == NULL) {
|
||||
recordingConLog(wxString::Format(L"[REC]: Conversion failed - Error - %s\n", WX_STR(wxString(strerror(errno)))));
|
||||
return;
|
||||
}
|
||||
wxString outfile = wxString::Format(L"%s_converted.p2m2", filename);
|
||||
fopen_s(&fp2, outfile, "wb");
|
||||
if (fp2 == NULL) {
|
||||
// TODO: keybindings for Recording inputs - not related to this code, just made a note here lol
|
||||
recordingConLog(wxString::Format(L"[REC]: Conversion failed - Error - %s\n", WX_STR(wxString(strerror(errno)))));
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
//---------
|
||||
// head
|
||||
//---------
|
||||
InputRecordingHeader header;
|
||||
header.version = 2;
|
||||
u32 maxframe =0;
|
||||
u32 undo = 0;
|
||||
fread(&maxframe, 4, 1, fp);
|
||||
fread(&undo, 4, 1, fp);
|
||||
MaxFrame = maxframe;
|
||||
UndoCount = undo;
|
||||
fwrite(&header, sizeof(InputRecordingHeader), 1, fp2);
|
||||
fwrite(&MaxFrame, 4, 1, fp2);
|
||||
fwrite(&UndoCount, 4, 1, fp2);
|
||||
|
||||
//---------
|
||||
// frame
|
||||
//---------
|
||||
// this routine runs forever, looks broken
|
||||
|
||||
for (unsigned long i = 0; i < maxframe; i++) {
|
||||
for (u8 port = 0; port < 2; port++) {
|
||||
for (u8 buf = 3; buf < 3+6 ; buf++) {
|
||||
long seekpoint1 = i;
|
||||
seekpoint1 <<= (1 + 5);
|
||||
seekpoint1 += port;
|
||||
seekpoint1 <<= 5;
|
||||
seekpoint1 += buf;
|
||||
seekpoint1 += 8;
|
||||
long seekpoint2 = _getBlockSeekPoint(i) + BLOCK_HEADER_SIZE + 6 * port + (buf - 3);
|
||||
u8 tmp = 0;
|
||||
fseek(fp, seekpoint1, SEEK_SET);
|
||||
fread(&tmp, 1, 1, fp);
|
||||
fseek(fp2, seekpoint2, SEEK_SET);
|
||||
fwrite(&tmp, 1, 1, fp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
fclose(fp2);
|
||||
recordingConLog(wxString::Format(L"[REC]: Conversion successful\n"));
|
||||
recordingConLog(wxString::Format(L"[REC]: Converted File - [%s]\n", WX_STR(outfile)));
|
||||
}
|
||||
|
||||
void InputRecordingFile::ConvertV1ToV2(wxString filename)
|
||||
{
|
||||
// TODO: Save states are not compatible across these releases
|
||||
// so unable to test
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// convert p2m -> p2m2
|
||||
// The p2m file is a file generated with the following URL.
|
||||
// https://code.google.com/archive/p/pcsx2-rr/
|
||||
// Legacy Conversion this will
|
||||
//===========================================================
|
||||
void InputRecordingFile::ConvertLegacy(wxString filename)
|
||||
{
|
||||
recordingConLog(wxString::Format(L"[REC]: Conversion started - [%s]\n", WX_STR(filename)));
|
||||
FILE * fp;
|
||||
FILE * fp2;
|
||||
fopen_s(&fp, filename, "rb");
|
||||
if (fp == NULL) {
|
||||
recordingConLog(wxString::Format(L"[REC]: Conversion failed - Error - %s\n", WX_STR(wxString(strerror(errno)))));
|
||||
return;
|
||||
}
|
||||
wxString outfile = wxString::Format(L"%s.p2m2", filename);
|
||||
fopen_s(&fp2, outfile, "wb");
|
||||
if (fp2 == NULL) {
|
||||
recordingConLog(wxString::Format(L"[REC]: Conversion failed - Error - %s\n", WX_STR(wxString(strerror(errno)))));
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// fread(&g_Movie.FrameMax, 4, 1, g_Movie.File);
|
||||
// fread(&g_Movie.Rerecs, 4, 1, g_Movie.File);
|
||||
// fread(g_PadData[0]+2, 6, 1, g_Movie.File);
|
||||
//--------------------------------------
|
||||
|
||||
//------
|
||||
//head
|
||||
//------
|
||||
InputRecordingHeader header;
|
||||
header.version = 2;
|
||||
u32 maxframe = 0;
|
||||
u32 undo = 0;
|
||||
fread(&maxframe, 4, 1, fp);
|
||||
fread(&undo, 4, 1, fp);
|
||||
MaxFrame = maxframe;
|
||||
UndoCount = undo;
|
||||
fwrite(&header, sizeof(InputRecordingHeader), 1, fp2);
|
||||
fwrite(&MaxFrame, 4, 1, fp2);
|
||||
fwrite(&UndoCount, 4, 1, fp2);
|
||||
|
||||
//------
|
||||
// frame
|
||||
//------
|
||||
for (unsigned long frame = 0; frame < maxframe; frame++)
|
||||
{
|
||||
u8 p1key[6];
|
||||
fread(p1key, 6, 1, fp);
|
||||
|
||||
long seek = _getBlockSeekPoint(frame) + BLOCK_HEADER_SIZE;
|
||||
fseek(fp2, seek, SEEK_SET);
|
||||
fwrite(p1key, 6, 1, fp2);
|
||||
|
||||
// 2p
|
||||
u8 p2key[6] = { 255,255,127,127,127,127 };
|
||||
fwrite(p2key, 6, 1, fp2);
|
||||
|
||||
}
|
||||
fclose(fp);
|
||||
fclose(fp2);
|
||||
recordingConLog(wxString::Format(L"[REC]: Conversion successful\n"));
|
||||
recordingConLog(wxString::Format(L"[REC]: Converted File - [%s]\n", WX_STR(outfile)));
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
#pragma once
|
||||
#ifndef __KEY_MOVIE_ONFILE_H__
|
||||
#define __KEY_MOVIE_ONFILE_H__
|
||||
|
||||
#include "PadData.h"
|
||||
#include "System.h"
|
||||
|
||||
//----------------------------
|
||||
// header
|
||||
// fseek since the direct place designation is done with, the order of the variables is important
|
||||
// Specifically, "FrameMax" +2 "UndoCount" is located at the position of +6 bytes
|
||||
// fseek<65>Œ<EFBFBD><C592>ڏꏊ<DA8F>w<EFBFBD>肵<EFBFBD>Ă<EFBFBD><C482><EFBFBD>̂ŕϐ<C595><CF90>̏<EFBFBD><CC8F>Ԃ͑厖
|
||||
// <20><>̓I<CC93>ɂ́uFrameMax<61>v<EFBFBD><76>+2<>uUndoCount<6E>v<EFBFBD><76>+6<>o<EFBFBD>C<EFBFBD>g<EFBFBD>̈ʒu<CA92>ɔz<C994>u
|
||||
//----------------------------
|
||||
struct InputRecordingHeader
|
||||
{
|
||||
u8 version = 3;
|
||||
u8 ID = 0xCC; // Especially, there is no meaning, a key file or ID for judgment
|
||||
// <20><><EFBFBD>ɈӖ<C988><D396>͂Ȃ<CD82><C882>Akey<65>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>p<EFBFBD><70>ID
|
||||
|
||||
char emu[50] = "PCSX2-1.4.0-rr";
|
||||
char author[50] = "";
|
||||
char cdrom[50] = "";
|
||||
|
||||
public:
|
||||
void setAuthor(wxString author);
|
||||
void setCdrom(wxString cdrom);
|
||||
void init();
|
||||
};
|
||||
|
||||
//----------------------------
|
||||
// InputRecordingSavestate
|
||||
// Contains info about the starting point of the movie
|
||||
//----------------------------
|
||||
struct InputRecordingSavestate
|
||||
{
|
||||
bool fromSavestate = false; // Whether we start from the savestate or from power-on
|
||||
unsigned int savestatesize; // The size of the savestate
|
||||
VmStateBuffer savestate; // The savestate
|
||||
};
|
||||
|
||||
//----------------------------
|
||||
// InputRecordingFile
|
||||
//----------------------------
|
||||
class InputRecordingFile {
|
||||
public:
|
||||
InputRecordingFile() {}
|
||||
~InputRecordingFile() { Close(); }
|
||||
public:
|
||||
|
||||
// file
|
||||
bool Open(const wxString fn, bool fNewOpen, VmStateBuffer *ss = nullptr);
|
||||
bool Close();
|
||||
|
||||
// movie
|
||||
bool writeKeyBuf(const uint & frame, const uint port, const uint bufIndex, const u8 & buf);
|
||||
bool readKeyBuf(u8 & result, const uint & frame, const uint port, const uint bufIndex);
|
||||
|
||||
// pad data
|
||||
void getPadData(PadData & result_pad, unsigned long frame);
|
||||
bool DeletePadData(unsigned long frame);
|
||||
bool InsertPadData(unsigned long frame, const PadData& key);
|
||||
bool UpdatePadData(unsigned long frame, const PadData& key);
|
||||
|
||||
// convert
|
||||
void ConvertV2ToV3(wxString filename);
|
||||
void ConvertV1_XToV2(wxString filename);
|
||||
void ConvertV1ToV2(wxString filename);
|
||||
void ConvertLegacy(wxString filename);
|
||||
|
||||
private:
|
||||
FILE * fp=NULL;
|
||||
wxString filename = "";
|
||||
|
||||
private:
|
||||
|
||||
//--------------------
|
||||
// block
|
||||
//--------------------
|
||||
long _getBlockSeekPoint(const long & frame);
|
||||
|
||||
|
||||
public:
|
||||
//--------------------
|
||||
// header
|
||||
//--------------------
|
||||
InputRecordingHeader& getHeader() { return header; }
|
||||
unsigned long& getMaxFrame() { return MaxFrame; }
|
||||
unsigned long& getUndoCount() { return UndoCount; }
|
||||
const wxString & getFilename() { return filename; }
|
||||
|
||||
bool writeHeader();
|
||||
bool writeSavestate();
|
||||
bool writeMaxFrame();
|
||||
|
||||
bool readHeaderAndCheck();
|
||||
void updateFrameMax(unsigned long frame);
|
||||
void addUndoCount();
|
||||
|
||||
private:
|
||||
InputRecordingHeader header;
|
||||
InputRecordingSavestate savestate;
|
||||
unsigned long MaxFrame = 0;
|
||||
unsigned long UndoCount = 0;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue