2009-07-17 19:27:04 +02:00
|
|
|
#ifndef __MOVIE_H_
|
|
|
|
#define __MOVIE_H_
|
|
|
|
|
2016-09-18 05:43:24 +02:00
|
|
|
#include "input/zapper.h"
|
|
|
|
#include "utils/guid.h"
|
|
|
|
#include "utils/md5.h"
|
|
|
|
|
2009-07-17 19:27:04 +02:00
|
|
|
#include <vector>
|
|
|
|
#include <map>
|
|
|
|
#include <string>
|
|
|
|
#include <ostream>
|
2016-09-18 05:43:24 +02:00
|
|
|
#include <cstdlib>
|
2009-07-17 19:27:04 +02:00
|
|
|
|
|
|
|
struct FCEUFILE;
|
|
|
|
|
|
|
|
enum EMOVIE_FLAG
|
|
|
|
{
|
|
|
|
MOVIE_FLAG_NONE = 0,
|
|
|
|
|
|
|
|
//an ARCHAIC flag which means the movie was recorded from a soft reset.
|
|
|
|
//WHY would you do this?? do not create any new movies with this flag
|
|
|
|
MOVIE_FLAG_FROM_RESET = (1<<1),
|
2012-12-14 18:18:20 +01:00
|
|
|
|
2009-07-17 19:27:04 +02:00
|
|
|
MOVIE_FLAG_PAL = (1<<2),
|
|
|
|
|
|
|
|
//movie was recorded from poweron. the alternative is from a savestate (or from reset)
|
|
|
|
MOVIE_FLAG_FROM_POWERON = (1<<3),
|
|
|
|
|
|
|
|
// set in newer version, used for old movie compatibility
|
|
|
|
//TODO - only use this flag to print a warning that the sync might be bad
|
|
|
|
//so that we can get rid of the sync hack code
|
|
|
|
MOVIE_FLAG_NOSYNCHACK = (1<<4)
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
int movie_version; // version of the movie format in the file
|
|
|
|
uint32 num_frames;
|
|
|
|
uint32 rerecord_count;
|
2010-08-29 23:15:42 +02:00
|
|
|
bool poweron, pal, nosynchack, ppuflag;
|
2009-07-17 19:27:04 +02:00
|
|
|
bool reset; //mbg 6/21/08 - this flag isnt used anymore.. but maybe one day we can scan it out of the first record in the movie file
|
|
|
|
uint32 emu_version_used; // 9813 = 0.98.13
|
|
|
|
MD5DATA md5_of_rom_used;
|
|
|
|
std::string name_of_rom_used;
|
2010-03-11 07:30:34 +01:00
|
|
|
|
2009-07-17 19:27:04 +02:00
|
|
|
std::vector<std::wstring> comments;
|
|
|
|
std::vector<std::string> subtitles;
|
|
|
|
} MOVIE_INFO;
|
|
|
|
|
|
|
|
|
|
|
|
void FCEUMOV_AddInputState();
|
|
|
|
void FCEUMOV_AddCommand(int cmd);
|
|
|
|
void FCEU_DrawMovies(uint8 *);
|
|
|
|
void FCEU_DrawLagCounter(uint8 *);
|
|
|
|
|
|
|
|
enum EMOVIEMODE
|
|
|
|
{
|
|
|
|
MOVIEMODE_INACTIVE = 1,
|
|
|
|
MOVIEMODE_RECORD = 2,
|
|
|
|
MOVIEMODE_PLAY = 4,
|
2012-01-14 23:35:51 +01:00
|
|
|
MOVIEMODE_TASEDITOR = 8,
|
2010-08-29 23:15:42 +02:00
|
|
|
MOVIEMODE_FINISHED = 16
|
2009-07-17 19:27:04 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
enum EMOVIECMD
|
|
|
|
{
|
|
|
|
MOVIECMD_RESET = 1,
|
|
|
|
MOVIECMD_POWER = 2,
|
2009-09-15 10:20:48 +02:00
|
|
|
MOVIECMD_FDS_INSERT = 4,
|
2016-09-18 05:43:24 +02:00
|
|
|
MOVIECMD_FDS_SELECT = 8,
|
|
|
|
MOVIECMD_VS_INSERTCOIN = 16
|
2009-07-17 19:27:04 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
EMOVIEMODE FCEUMOV_Mode();
|
|
|
|
bool FCEUMOV_Mode(EMOVIEMODE modemask);
|
|
|
|
bool FCEUMOV_Mode(int modemask);
|
2010-08-29 23:15:42 +02:00
|
|
|
inline bool FCEUMOV_IsPlaying() { return (FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_FINISHED)); }
|
2009-07-17 19:27:04 +02:00
|
|
|
inline bool FCEUMOV_IsRecording() { return FCEUMOV_Mode(MOVIEMODE_RECORD); }
|
2010-08-29 23:15:42 +02:00
|
|
|
inline bool FCEUMOV_IsFinished() { return FCEUMOV_Mode(MOVIEMODE_FINISHED);}
|
|
|
|
inline bool FCEUMOV_IsLoaded() { return (FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED)); }
|
2009-07-17 19:27:04 +02:00
|
|
|
|
|
|
|
bool FCEUMOV_ShouldPause(void);
|
|
|
|
int FCEUMOV_GetFrame(void);
|
|
|
|
int FCEUI_GetLagCount(void);
|
|
|
|
bool FCEUI_GetLagged(void);
|
2012-12-14 18:18:20 +01:00
|
|
|
void FCEUI_SetLagFlag(bool value);
|
2009-07-17 19:27:04 +02:00
|
|
|
|
2010-08-29 23:15:42 +02:00
|
|
|
int FCEUMOV_WriteState(EMUFILE* os);
|
|
|
|
bool FCEUMOV_ReadState(EMUFILE* is, uint32 size);
|
2009-07-17 19:27:04 +02:00
|
|
|
void FCEUMOV_PreLoad();
|
|
|
|
bool FCEUMOV_PostLoad();
|
2016-09-18 05:43:24 +02:00
|
|
|
void FCEUMOV_IncrementRerecordCount();
|
2009-07-17 19:27:04 +02:00
|
|
|
|
2010-08-29 23:15:42 +02:00
|
|
|
bool FCEUMOV_FromPoweron();
|
2009-07-17 19:27:04 +02:00
|
|
|
|
2012-06-27 01:14:39 +02:00
|
|
|
void FCEUMOV_CreateCleanMovie();
|
|
|
|
void FCEUMOV_ClearCommands();
|
2012-01-09 02:59:06 +01:00
|
|
|
|
2009-07-17 19:27:04 +02:00
|
|
|
class MovieData;
|
|
|
|
class MovieRecord
|
|
|
|
{
|
|
|
|
|
|
|
|
public:
|
2010-08-29 23:15:42 +02:00
|
|
|
MovieRecord();
|
2009-07-17 19:27:04 +02:00
|
|
|
ValueArray<uint8,4> joysticks;
|
2012-12-14 18:18:20 +01:00
|
|
|
|
2009-07-17 19:27:04 +02:00
|
|
|
struct {
|
|
|
|
uint8 x,y,b,bogo;
|
|
|
|
uint64 zaphit;
|
|
|
|
} zappers[2];
|
|
|
|
|
|
|
|
//misc commands like reset, etc.
|
|
|
|
//small now to save space; we might need to support more commands later.
|
|
|
|
//the disk format will support up to 64bit if necessary
|
|
|
|
uint8 commands;
|
2016-09-18 05:43:24 +02:00
|
|
|
bool command_reset() { return (commands & MOVIECMD_RESET) != 0; }
|
|
|
|
bool command_power() { return (commands & MOVIECMD_POWER) != 0; }
|
|
|
|
bool command_fds_insert() { return (commands & MOVIECMD_FDS_INSERT) != 0; }
|
|
|
|
bool command_fds_select() { return (commands & MOVIECMD_FDS_SELECT) != 0; }
|
|
|
|
bool command_vs_insertcoin() { return (commands & MOVIECMD_VS_INSERTCOIN) != 0; }
|
2009-07-17 19:27:04 +02:00
|
|
|
|
|
|
|
void toggleBit(int joy, int bit)
|
|
|
|
{
|
|
|
|
joysticks[joy] ^= mask(bit);
|
|
|
|
}
|
|
|
|
|
|
|
|
void setBit(int joy, int bit)
|
|
|
|
{
|
|
|
|
joysticks[joy] |= mask(bit);
|
|
|
|
}
|
|
|
|
|
|
|
|
void clearBit(int joy, int bit)
|
|
|
|
{
|
|
|
|
joysticks[joy] &= ~mask(bit);
|
|
|
|
}
|
|
|
|
|
|
|
|
void setBitValue(int joy, int bit, bool val)
|
|
|
|
{
|
|
|
|
if(val) setBit(joy,bit);
|
|
|
|
else clearBit(joy,bit);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool checkBit(int joy, int bit)
|
|
|
|
{
|
|
|
|
return (joysticks[joy] & mask(bit))!=0;
|
|
|
|
}
|
|
|
|
|
2010-08-29 23:15:42 +02:00
|
|
|
bool Compare(MovieRecord& compareRec);
|
2012-01-09 02:59:06 +01:00
|
|
|
void Clone(MovieRecord& sourceRec);
|
2009-07-17 19:27:04 +02:00
|
|
|
void clear();
|
2012-12-14 18:18:20 +01:00
|
|
|
|
2010-08-29 23:15:42 +02:00
|
|
|
void parse(MovieData* md, EMUFILE* is);
|
|
|
|
bool parseBinary(MovieData* md, EMUFILE* is);
|
|
|
|
void dump(MovieData* md, EMUFILE* os, int index);
|
|
|
|
void dumpBinary(MovieData* md, EMUFILE* os, int index);
|
|
|
|
void parseJoy(EMUFILE* is, uint8& joystate);
|
|
|
|
void dumpJoy(EMUFILE* os, uint8 joystate);
|
2012-12-14 18:18:20 +01:00
|
|
|
|
2009-07-17 19:27:04 +02:00
|
|
|
static const char mnemonics[8];
|
|
|
|
|
|
|
|
private:
|
|
|
|
int mask(int bit) { return 1<<bit; }
|
|
|
|
};
|
|
|
|
|
|
|
|
class MovieData
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
MovieData();
|
2010-08-29 23:15:42 +02:00
|
|
|
// Default Values: MovieData::MovieData()
|
2009-07-17 19:27:04 +02:00
|
|
|
|
|
|
|
int version;
|
|
|
|
int emuVersion;
|
2010-03-11 07:30:34 +01:00
|
|
|
int fds;
|
2009-07-17 19:27:04 +02:00
|
|
|
//todo - somehow force mutual exclusion for poweron and reset (with an error in the parser)
|
|
|
|
bool palFlag;
|
2010-08-29 23:15:42 +02:00
|
|
|
bool PPUflag;
|
2009-07-17 19:27:04 +02:00
|
|
|
MD5DATA romChecksum;
|
|
|
|
std::string romFilename;
|
2010-08-29 23:15:42 +02:00
|
|
|
std::vector<uint8> savestate;
|
2009-07-17 19:27:04 +02:00
|
|
|
std::vector<MovieRecord> records;
|
|
|
|
std::vector<std::wstring> comments;
|
|
|
|
std::vector<std::string> subtitles;
|
|
|
|
//this is the RERECORD COUNT. please rename variable.
|
|
|
|
int rerecordCount;
|
|
|
|
FCEU_Guid guid;
|
|
|
|
|
|
|
|
//was the frame data stored in binary?
|
|
|
|
bool binaryFlag;
|
2012-01-09 02:59:06 +01:00
|
|
|
// TAS Editor project files contain additional data after input
|
|
|
|
int loadFrameCount;
|
2009-07-17 19:27:04 +02:00
|
|
|
|
|
|
|
//which ports are defined for the movie
|
|
|
|
int ports[3];
|
|
|
|
//whether fourscore is enabled
|
|
|
|
bool fourscore;
|
2010-08-29 23:15:42 +02:00
|
|
|
//whether microphone is enabled
|
|
|
|
bool microphone;
|
2012-12-14 18:18:20 +01:00
|
|
|
|
2009-07-17 19:27:04 +02:00
|
|
|
int getNumRecords() { return records.size(); }
|
|
|
|
|
|
|
|
class TDictionary : public std::map<std::string,std::string>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
bool containsKey(std::string key)
|
|
|
|
{
|
|
|
|
return find(key) != end();
|
|
|
|
}
|
|
|
|
|
|
|
|
void tryInstallBool(std::string key, bool& val)
|
|
|
|
{
|
|
|
|
if(containsKey(key))
|
|
|
|
val = atoi(operator [](key).c_str())!=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tryInstallString(std::string key, std::string& val)
|
|
|
|
{
|
|
|
|
if(containsKey(key))
|
|
|
|
val = operator [](key);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tryInstallInt(std::string key, int& val)
|
|
|
|
{
|
|
|
|
if(containsKey(key))
|
|
|
|
val = atoi(operator [](key).c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
void truncateAt(int frame);
|
|
|
|
void installValue(std::string& key, std::string& val);
|
2010-08-29 23:15:42 +02:00
|
|
|
int dump(EMUFILE* os, bool binary);
|
2009-12-23 01:15:33 +01:00
|
|
|
|
2009-07-17 19:27:04 +02:00
|
|
|
void clearRecordRange(int start, int len);
|
2012-12-14 18:18:20 +01:00
|
|
|
void eraseRecords(int at, int frames = 1);
|
2009-07-17 19:27:04 +02:00
|
|
|
void insertEmpty(int at, int frames);
|
2012-01-09 02:59:06 +01:00
|
|
|
void cloneRegion(int at, int frames);
|
2012-12-14 18:18:20 +01:00
|
|
|
|
2010-08-29 23:15:42 +02:00
|
|
|
static bool loadSavestateFrom(std::vector<uint8>* buf);
|
|
|
|
static void dumpSavestateTo(std::vector<uint8>* buf, int compressionLevel);
|
|
|
|
|
2009-07-17 19:27:04 +02:00
|
|
|
private:
|
|
|
|
void installInt(std::string& val, int& var)
|
|
|
|
{
|
|
|
|
var = atoi(val.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
void installBool(std::string& val, bool& var)
|
|
|
|
{
|
|
|
|
var = atoi(val.c_str())!=0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
extern MovieData currMovieData;
|
|
|
|
extern int currFrameCounter;
|
|
|
|
extern char curMovieFilename[512];
|
|
|
|
extern bool subtitlesOnAVI;
|
|
|
|
extern bool freshMovie;
|
|
|
|
extern bool movie_readonly;
|
|
|
|
extern bool autoMovieBackup;
|
2010-08-29 23:15:42 +02:00
|
|
|
extern bool fullSaveStateLoads;
|
2009-07-17 19:27:04 +02:00
|
|
|
//--------------------------------------------------
|
|
|
|
void FCEUI_MakeBackupMovie(bool dispMessage);
|
2009-07-18 00:54:58 +02:00
|
|
|
void FCEUI_CreateMovieFile(std::string fn);
|
2009-07-17 19:27:04 +02:00
|
|
|
void FCEUI_SaveMovie(const char *fname, EMOVIE_FLAG flags, std::wstring author);
|
2012-01-09 02:59:06 +01:00
|
|
|
bool FCEUI_LoadMovie(const char *fname, bool read_only, int _stopframe);
|
2009-07-17 19:27:04 +02:00
|
|
|
void FCEUI_MoviePlayFromBeginning(void);
|
|
|
|
void FCEUI_StopMovie(void);
|
|
|
|
bool FCEUI_MovieGetInfo(FCEUFILE* fp, MOVIE_INFO& info, bool skipFrameCount = false);
|
2010-08-29 23:15:42 +02:00
|
|
|
//char* FCEUI_MovieGetCurrentName(int addSlotNumber);
|
2009-07-17 19:27:04 +02:00
|
|
|
void FCEUI_MovieToggleReadOnly(void);
|
|
|
|
bool FCEUI_GetMovieToggleReadOnly();
|
|
|
|
void FCEUI_SetMovieToggleReadOnly(bool which);
|
|
|
|
int FCEUI_GetMovieLength();
|
|
|
|
int FCEUI_GetMovieRerecordCount();
|
|
|
|
std::string FCEUI_GetMovieName(void);
|
|
|
|
void FCEUI_MovieToggleFrameDisplay();
|
2012-01-09 02:59:06 +01:00
|
|
|
void FCEUI_MovieToggleRerecordDisplay();
|
2009-07-17 19:27:04 +02:00
|
|
|
void FCEUI_ToggleInputDisplay(void);
|
|
|
|
|
2010-08-29 23:15:42 +02:00
|
|
|
void LoadSubtitles(MovieData &);
|
2009-07-17 19:27:04 +02:00
|
|
|
void ProcessSubtitles(void);
|
|
|
|
void FCEU_DisplaySubtitles(char *format, ...);
|
|
|
|
|
2009-11-16 01:22:36 +01:00
|
|
|
void poweron(bool shouldDisableBatteryLoading);
|
|
|
|
|
|
|
|
|
2009-11-10 23:13:41 +01:00
|
|
|
#endif //__MOVIE_H_
|