batch fcm->fm2 convert rough draft (look in the file menu)

the headers arent output fully correct.. and there is no error reporting.. but it works.
This commit is contained in:
zeromus 2008-06-22 06:53:49 +00:00
parent 69bc4b3f72
commit 67c4a6d6ab
9 changed files with 742 additions and 640 deletions

View File

@ -202,7 +202,7 @@ void UpdateReplayDialog(HWND hwndDlg)
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_UNDOCOUNT),"");
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_ROMUSED),"");
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_ROMCHECKSUM),"");
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_RECORDEDFROM),"Nothing (invalid movie)");
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_RECORDEDFROM),"");
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_EMULATORUSED),"");
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_CURRCHECKSUM),md5_asciistr(GameInfo->MD5));
SetDlgItemText(hwndDlg,IDC_EDIT_STOPFRAME,"");
@ -313,7 +313,7 @@ BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
continue;
// filter out everything that's not *.fcm, *.fm2
// filter out everything that's not *.fm2
// (because FindFirstFile is too dumb to do that)
{
char* dot=strrchr(wfd.cFileName,'.');
@ -324,7 +324,7 @@ BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
int k, extlen=strlen(ext);
for(k=0;k<extlen;k++)
ext[k]=tolower(ext[k]);
if(strcmp(ext,"fcm") && strcmp(ext,"fm2"))
if(strcmp(ext,"fm2"))
continue;
}
@ -442,7 +442,7 @@ BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwndDlg;
ofn.lpstrFilter = "Supported Movie Files (*.fcm|*.fm2)\0*.fcm;*.fm2\0FCEUX Movie Files (*.fm2)\0*.fm2\0FCEU Movie Files (*.fcm)\0*.fcm\0All files(*.*)\0*.*\0\0";
ofn.lpstrFilter = "FCEUX Movie Files (*.fm2)\0*.fm2\0All files(*.*)\0*.*\0\0";
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrInitialDir = pn;
@ -696,7 +696,7 @@ static BOOL CALLBACK RecordDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LP
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwndDlg;
ofn.lpstrFilter = "FCEUX Movie File (*.fm2)\0*.fm2\0FCEU Movie File(*.fcm)\0*.fcm\0All files(*.*)\0*.*\0\0";
ofn.lpstrFilter = "FCEUX Movie File (*.fm2)\0*.fm2\0All files(*.*)\0*.*\0\0";
ofn.lpstrFile = szChoice;
ofn.lpstrDefExt = "fm2";
ofn.nMaxFile = MAX_PATH;

View File

@ -49,6 +49,7 @@ BEGIN
MENUITEM "Record Movie...", MENU_RECORD_MOVIE
MENUITEM "Replay Movie...", MENU_REPLAY_MOVIE
MENUITEM "Stop Movie", MENU_STOP_MOVIE
MENUITEM "Convert FCM...", MENU_CONVERT_MOVIE
MENUITEM SEPARATOR
MENUITEM "Record AVI...", MENU_RECORD_AVI
MENUITEM "Stop AVI", MENU_STOP_AVI

View File

@ -523,6 +523,8 @@
#define ID_ 40146
#define MENU_DISPLAY_BG 40147
#define MENU_DISPLAY_OBJ 40148
#define ID_FILE_CONVERTMOVIE 40149
#define MENU_CONVERT_MOVIE 40150
#define MW_ValueLabel2 65423
#define MW_ValueLabel1 65426
#define GUI_BOT_DEBUG 65436
@ -533,7 +535,7 @@
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 114
#define _APS_NEXT_COMMAND_VALUE 40149
#define _APS_NEXT_COMMAND_VALUE 40151
#define _APS_NEXT_CONTROL_VALUE 1132
#define _APS_NEXT_SYMED_VALUE 101
#endif

View File

@ -45,6 +45,8 @@
#include "throttle.h"
#include "monitor.h"
#include "tasedit.h"
#include "oldmovie.h"
#include "movie.h"
#include "guiconfig.h"
#include "timing.h"
@ -54,6 +56,8 @@
#include "help.h"
#include "movie.h"
#include <fstream>
// Extern variables
extern FCEUGI *GameInfo;
@ -108,6 +112,61 @@ static int vchanged = 0;
// Internal functions
static void ConvertFCM(HWND hwndOwner)
{
std::string initdir = FCEU_GetPath(FCEUMKF_MOVIE);
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwndOwner;
ofn.lpstrFilter = "FCEU <2.0 Movie Files (*.fcm)\0*.fcm\0All files(*.*)\0*.*\0\0";
ofn.lpstrFile = new char[640*1024]; //640K should be enough for anyone
ofn.lpstrFile[0] = 0;
ofn.nMaxFile = 640*1024;
ofn.lpstrInitialDir = initdir.c_str();
ofn.Flags = OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT | OFN_EXPLORER;
ofn.lpstrDefExt = "fcm";
ofn.lpstrTitle = "Select old movie(s) for conversion";
if(GetOpenFileName(&ofn))
{
std::vector<std::string> todo;
if(ofn.nFileExtension==0)
{
//multiselect
std::string dir = ofn.lpstrFile;
char* cp = ofn.lpstrFile + dir.size() + 1;
while(*cp)
{
std::string fname = cp;
todo.push_back(dir + "/" + fname);
cp += fname.size() + 1;
}
}
else
{
todo.push_back(ofn.lpstrFile);
}
for(uint32 i=0;i<todo.size();i++)
{
std::string infname = todo[i];
std::string outname = infname + ".fm2";
MovieData md;
if(convert_fcm(md, infname)==FCM_CONVERTRESULT_SUCCESS)
{
std::fstream* outf = FCEUD_UTF8_fstream(outname, "wb");
md.dump(outf,false);
delete outf;
}
}
}
delete[] ofn.lpstrFile;
}
void CalcWindowSize(RECT *al)
{
al->left = 0;
@ -993,6 +1052,11 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
}
break;
case MENU_CONVERT_MOVIE:
ConvertFCM(hWnd);
break;
case MENU_SAVE_STATE:
// Save state as menu was selected
FCEUD_SaveStateAs();

View File

@ -7,10 +7,6 @@
#include <fstream>
#include <limits.h>
#ifdef WIN32
#include <windows.h>
#endif
#include "types.h"
#include "utils/endian.h"
#include "palette.h"
@ -29,7 +25,7 @@
using namespace std;
#define MOVIE_VERSION 3 // still at 2 since the format itself is still compatible - to detect which version the movie was made with, check the fceu version stored in the movie header (e.g against FCEU_VERSION_NUMERIC)
#define MOVIE_VERSION 3
extern char FileBase[];
extern int EmulationPaused;
@ -234,11 +230,6 @@ void MovieRecord::dumpBinary(MovieData* md, std::ostream* os, int index)
void MovieRecord::dump(MovieData* md, std::ostream* os, int index)
{
//todo: if we want frame numbers in the output (which we dont since we couldnt cut and paste in movies)
//but someone would need to change the parser to ignore it
//fputc('|',fp);
//fprintf(fp,"%08d",index);
//dump the misc commands
//*os << '|' << setw(1) << (int)commands;
os->put('|');
@ -284,7 +275,7 @@ MovieData::MovieData()
, emuVersion(FCEU_VERSION_NUMERIC)
, palFlag(false)
, binaryFlag(false)
, recordCount(1)
, rerecordCount(1)
, greenZoneCount(0)
{
memset(&romChecksum,0,sizeof(MD5DATA));
@ -302,8 +293,8 @@ void MovieData::installValue(std::string& key, std::string& val)
installInt(val,version);
else if(key == "emuVersion")
installInt(val,emuVersion);
else if(key == "recordCount")
installInt(val,recordCount);
else if(key == "rerecordCount")
installInt(val,rerecordCount);
else if(key == "palFlag")
installBool(val,palFlag);
else if(key == "romFilename")
@ -338,7 +329,7 @@ int MovieData::dump(std::ostream *os, bool binary)
int start = os->tellp();
*os << "version " << version << endl;
*os << "emuVersion " << emuVersion << endl;
*os << "recordCount " << recordCount << endl;
*os << "rerecordCount " << rerecordCount << endl;
*os << "palFlag " << (palFlag?1:0) << endl;
*os << "romFilename " << romFilename << endl;
*os << "romChecksum " << BytesToString(romChecksum.data,MD5DATA::size) << endl;
@ -521,23 +512,30 @@ static void LoadFM2(MovieData& movieData, std::istream* fp, int size, bool stopA
}
}
static void closeRecordingMovie()
{
if(osRecordingMovie)
{
delete osRecordingMovie;
osRecordingMovie = 0;
}
}
/// Stop movie playback.
void StopPlayback()
static void StopPlayback()
{
FCEU_DispMessageOnMovie("Movie playback stopped.");
movieMode = MOVIEMODE_INACTIVE;
}
/// Stop movie recording
void StopRecording()
static void StopRecording()
{
FCEU_DispMessage("Movie recording stopped.");
movieMode = MOVIEMODE_INACTIVE;
//fclose(fpRecordingMovie);
//fpRecordingMovie = 0;
osRecordingMovie = 0;
closeRecordingMovie();
}
@ -654,11 +652,8 @@ void FCEUI_LoadMovie(char *fname, bool _read_only, bool tasedit, int _pauseframe
fp->close();
delete fp;
// fully reload the game to reinitialize everything before playing any movie
// to try fixing nondeterministic playback of some games
{
poweron(true);
}
//fully reload the game to reinitialize everything before playing any movie
poweron(true);
//WE NEED TO LOAD A SAVESTATE
if(currMovieData.savestate.size() != 0)
@ -699,15 +694,6 @@ void FCEUI_LoadMovie(char *fname, bool _read_only, bool tasedit, int _pauseframe
}
}
static void closeRecordingMovie()
{
if(osRecordingMovie)
{
delete osRecordingMovie;
osRecordingMovie = 0;
}
}
static void openRecordingMovie(const char* fname)
{
osRecordingMovie = FCEUD_UTF8_fstream(fname, "wb");
@ -925,7 +911,7 @@ bool FCEUMOV_ReadState(std::istream* is, uint32 size)
//truncate before we copy, just to save some time
tempMovieData.truncateAt(currFrameCounter);
currMovieData = tempMovieData;
currMovieData.recordCount++;
currMovieData.rerecordCount++;
openRecordingMovie(curMovieFilename);
currMovieData.dump(osRecordingMovie, false);
@ -1026,605 +1012,7 @@ bool FCEUI_MovieGetInfo(const std::string& fname, MOVIE_INFO* info, bool skipFra
info->md5_of_rom_used_present = 1;
info->emu_version_used = md.emuVersion;
info->name_of_rom_used = md.romFilename;
info->rerecord_count = md.recordCount;
info->rerecord_count = md.rerecordCount;
return true;
}
//int FCEUI_IsMovieActive(void)
//{
// //this is a lame method. we should change all the fceu code that uses it to call the
// //IsRecording or IsPlaying methods
// //return > 0 for recording, < 0 for playback
// if(FCEUMOV_IsRecording()) return 1;
// else if(FCEUMOV_IsPlaying()) return -1;
// else return 0;
//}
//struct MovieHeader
//{
//uint32 magic; // +0
//uint32 version=2; // +4
//uint8 flags[4]; // +8
//uint32 length_frames; // +12
//uint32 rerecord_count; // +16
//uint32 movie_data_size; // +20
//uint32 offset_to_savestate; // +24, should be 4-byte-aligned
//uint32 offset_to_movie_data; // +28, should be 4-byte-aligned
//uint8 md5_of_rom_used[16]; // +32
//uint32 version_of_emu_used // +48
//char name_of_rom_used[] // +52, utf-8, null-terminated
//char metadata[]; // utf-8, null-terminated
//uint8 padding[];
//uint8 savestate[]; // always present, even in a "from reset" recording
//uint8 padding[]; // used for byte-alignment
//uint8 movie_data[];
//}
// backwards compat
//static void FCEUI_LoadMovie_v1(char *fname, int _read_only);
//static int FCEUI_MovieGetInfo_v1(const char* fname, MOVIE_INFO* info);
//
//#define MOVIE_MAGIC 0x1a4d4346 // FCM\x1a
//
//int _old_FCEUI_MovieGetInfo(const char* fname, MOVIE_INFO* info)
//{
// //mbg: wtf?
// //MovieFlushHeader();
//
// // main get info part of function
// {
// uint32 magic;
// uint32 version;
// uint8 _flags[4];
//
// FILE* fp = FCEUD_UTF8fopen(fname, "rb");
// if(!fp)
// return 0;
//
// read32le(&magic, fp);
// if(magic != MOVIE_MAGIC)
// {
// fclose(fp);
// return 0;
// }
//
// read32le(&version, fp);
// if(version != MOVIE_VERSION)
// {
// fclose(fp);
// if(version == 1)
// return FCEUI_MovieGetInfo_v1(fname, info);
// else
// return 0;
// }
//
// info->movie_version = MOVIE_VERSION;
//
// fread(_flags, 1, 4, fp);
//
// info->flags = _flags[0];
// read32le(&info->num_frames, fp);
// read32le(&info->rerecord_count, fp);
//
// if(access(fname, W_OK))
// info->read_only = 1;
// else
// info->read_only = 0;
//
// fseek(fp, 12, SEEK_CUR); // skip movie_data_size, offset_to_savestate, and offset_to_movie_data
//
// fread(&info->md5_of_rom_used, 1, 16, fp);
// info->md5_of_rom_used_present = 1;
//
// read32le(&info->emu_version_used, fp);
//
// // I probably could have planned this better...
// {
// char str[256];
// size_t r;
// uint32 p; //mbg merge 7/17/06 change to uint32
// int p2=0;
// char last_c=32;
//
// if(info->name_of_rom_used && info->name_of_rom_used_size)
// info->name_of_rom_used[0]='\0';
//
// r=fread(str, 1, 256, fp);
// while(r > 0)
// {
// for(p=0; p<r && last_c != '\0'; ++p)
// {
// if(info->name_of_rom_used && info->name_of_rom_used_size && (p2 < info->name_of_rom_used_size-1))
// {
// info->name_of_rom_used[p2]=str[p];
// p2++;
// last_c=str[p];
// }
// }
// if(p<r)
// {
// memmove(str, str+p, r-p);
// r -= p;
// break;
// }
// r=fread(str, 1, 256, fp);
// }
//
// p2=0;
// last_c=32;
//
// if(info->metadata && info->metadata_size)
// info->metadata[0]='\0';
//
// while(r > 0)
// {
// for(p=0; p<r && last_c != '\0'; ++p)
// {
// if(info->metadata && info->metadata_size && (p2 < info->metadata_size-1))
// {
// info->metadata[p2]=str[p];
// p2++;
// last_c=str[p];
// }
// }
// if(p != r)
// break;
// r=fread(str, 1, 256, fp);
// }
//
// if(r<=0)
// {
// // somehow failed to read romname and metadata
// fclose(fp);
// return 0;
// }
// }
//
// // check what hacks are necessary
// fseek(fp, 24, SEEK_SET); // offset_to_savestate offset
// uint32 temp_savestate_offset;
// read32le(&temp_savestate_offset, fp);
// if(temp_savestate_offset != 0xFFFFFFFF)
// {
// if(fseek(fp, temp_savestate_offset, SEEK_SET))
// {
// fclose(fp);
// return 0;
// }
//
// //don't really load, just load to find what's there then load backup
// if(!FCEUSS_LoadFP(fp,SSLOADPARAM_DUMMY)) return 0;
// }
//
// fclose(fp);
// return 1;
// }
//}
/*
Backwards compat
*/
/*
struct MovieHeader_v1
{
uint32 magic;
uint32 version=1;
uint8 flags[4];
uint32 length_frames;
uint32 rerecord_count;
uint32 movie_data_size;
uint32 offset_to_savestate;
uint32 offset_to_movie_data;
uint16 metadata_ucs2[]; // ucs-2, ick! sizeof(metadata) = offset_to_savestate - MOVIE_HEADER_SIZE
}
*/
//
//#define MOVIE_V1_HEADER_SIZE 32
//
//static void FCEUI_LoadMovie_v1(char *fname, int _read_only)
//{
// FILE *fp;
// char *fn = NULL;
//
// FCEUI_StopMovie();
//
// if(!fname)
// fname = fn = FCEU_MakeFName(FCEUMKF_MOVIE,0,0);
//
// // check movie_readonly
// movie_readonly = _read_only;
// if(access(fname, W_OK))
// movie_readonly = 2;
//
// fp = FCEUD_UTF8fopen(fname, (movie_readonly>=2) ? "rb" : "r+b");
//
// if(fn)
// {
// free(fn);
// fname = NULL;
// }
//
// if(!fp) return;
//
// // read header
// {
// uint32 magic;
// uint32 version;
// uint8 flags[4];
// uint32 fc;
//
// read32le(&magic, fp);
// if(magic != MOVIE_MAGIC)
// {
// fclose(fp);
// return;
// }
//
// read32le(&version, fp);
// if(version != 1)
// {
// fclose(fp);
// return;
// }
//
// fread(flags, 1, 4, fp);
// read32le(&fc, fp);
// read32le(&rerecord_count, fp);
// read32le(&moviedatasize, fp);
// read32le(&savestate_offset, fp);
// read32le(&firstframeoffset, fp);
// if(fseek(fp, savestate_offset, SEEK_SET))
// {
// fclose(fp);
// return;
// }
//
// if(flags[0] & MOVIE_FLAG_NOSYNCHACK)
// movieSyncHackOn=0;
// else
// movieSyncHackOn=1;
// }
//
// // fully reload the game to reinitialize everything before playing any movie
// // to try fixing nondeterministic playback of some games
// {
// extern char lastLoadedGameName [2048];
// extern int disableBatteryLoading, suppressAddPowerCommand;
// suppressAddPowerCommand=1;
// suppressMovieStop=true;
// {
// FCEUGI * gi = FCEUI_LoadGame(lastLoadedGameName, 0);
// if(!gi)
// PowerNES();
// }
// suppressMovieStop=false;
// suppressAddPowerCommand=0;
// }
//
// if(!FCEUSS_LoadFP(fp,SSLOADPARAM_BACKUP)) return;
//
// ResetInputTypes();
//
// fseek(fp, firstframeoffset, SEEK_SET);
// moviedata = (uint8*)realloc(moviedata, moviedatasize);
// fread(moviedata, 1, moviedatasize, fp);
//
// framecount = 0; // movies start at frame 0!
// frameptr = 0;
// current = 0;
// slots = fp;
//
// memset(joop,0,sizeof(joop));
// current = -1 - current;
// framets=0;
// nextts=0;
// nextd = -1;
// FCEU_DispMessage("Movie playback started.");
//}
//
//static int FCEUI_MovieGetInfo_v1(const char* fname, MOVIE_INFO* info)
//{
// uint32 magic;
// uint32 version;
// uint8 _flags[4];
// uint32 savestateoffset;
// uint8 tmp[MOVIE_MAX_METADATA<<1];
// int metadata_length;
//
// FILE* fp = FCEUD_UTF8fopen(fname, "rb");
// if(!fp)
// return 0;
//
// read32le(&magic, fp);
// if(magic != MOVIE_MAGIC)
// {
// fclose(fp);
// return 0;
// }
//
// read32le(&version, fp);
// if(version != 1)
// {
// fclose(fp);
// return 0;
// }
//
// info->movie_version = 1;
// info->emu_version_used = 0; // unknown
//
// fread(_flags, 1, 4, fp);
//
// info->flags = _flags[0];
// read32le(&info->num_frames, fp);
// read32le(&info->rerecord_count, fp);
//
// if(access(fname, W_OK))
// info->read_only = 1;
// else
// info->read_only = 0;
//
// fseek(fp, 4, SEEK_CUR);
// read32le(&savestateoffset, fp);
//
// metadata_length = (int)savestateoffset - MOVIE_V1_HEADER_SIZE;
// if(metadata_length > 0)
// {
// //int i; //mbg merge 7/17/06 removed
//
// metadata_length >>= 1;
// if(metadata_length >= MOVIE_MAX_METADATA)
// metadata_length = MOVIE_MAX_METADATA-1;
//
// fseek(fp, MOVIE_V1_HEADER_SIZE, SEEK_SET);
// fread(tmp, 1, metadata_length<<1, fp);
// }
//
// // turn old ucs2 metadata into utf8
// if(info->metadata && info->metadata_size)
// {
// char* ptr=info->metadata;
// char* ptr_end=info->metadata+info->metadata_size-1;
// int c_ptr=0;
// while(ptr<ptr_end && c_ptr<metadata_length)
// {
// uint16 c=(tmp[c_ptr<<1] | (tmp[(c_ptr<<1)+1] << 8));
// //mbg merge 7/17/06 changed to if..elseif
// if(c<=0x7f)
// *ptr++ = (char)(c&0x7f);
// else if(c<=0x7FF)
// if(ptr+1>=ptr_end)
// ptr_end=ptr;
// else
// {
// *ptr++=(0xc0 | (c>>6));
// *ptr++=(0x80 | (c & 0x3f));
// }
// else
// if(ptr+2>=ptr_end)
// ptr_end=ptr;
// else
// {
// *ptr++=(0xe0 | (c>>12));
// *ptr++=(0x80 | ((c>>6) & 0x3f));
// *ptr++=(0x80 | (c & 0x3f));
// }
//
// c_ptr++;
// }
// *ptr='\0';
// }
//
// // md5 info not available from v1
// info->md5_of_rom_used_present = 0;
// // rom name used for the movie not available from v1
// if(info->name_of_rom_used && info->name_of_rom_used_size)
// info->name_of_rom_used[0] = '\0';
//
// // check what hacks are necessary
// fseek(fp, 24, SEEK_SET); // offset_to_savestate offset
// uint32 temp_savestate_offset;
// read32le(&temp_savestate_offset, fp);
// if(fseek(fp, temp_savestate_offset, SEEK_SET))
// {
// fclose(fp);
// return 0;
// }
// if(!FCEUSS_LoadFP(fp,SSLOADPARAM_DUMMY)) return 0; // 2 -> don't really load, just load to find what's there then load backup
//
//
// fclose(fp);
// return 1;
//}
//
//// PlayMovie / MoviePlay function
//void _old_FCEUI_LoadMovie(char *fname, int _read_only, int _stopframe)
//{
// char buffer [512];
// //fname = (char*)convertToFCM(fname,buffer);
//
// FILE *fp;
// char *fn = NULL;
//
// FCEUI_StopMovie();
//
// if(!fname)
// fname = fn = FCEU_MakeFName(FCEUMKF_MOVIE,0,0);
//
// char origname[512];
// strcpy(origname,fname);
//
// pauseframe = _stopframe;
//
// // check movie_readonly
// movie_readonly = _read_only;
// if(access(fname, W_OK))
// movie_readonly = 2;
//
// fp = FCEUD_UTF8fopen(fname, (movie_readonly>=2) ? "rb" : "r+b");
//
// if(fn)
// {
// free(fn);
// fname = NULL;
// }
//
// if(!fp) return;
//
// // read header
//
// uint32 magic;
// uint32 version;
// uint8 flags[4];
//
// read32le(&magic, fp);
// if(magic != MOVIE_MAGIC)
// {
// fclose(fp);
// return;
// }
// //DEBUG_COMPARE_RAM(__LINE__);
//
// read32le(&version, fp);
// if(version == 1)
// {
// // attempt to load previous version's format
// fclose(fp);
// FCEUI_LoadMovie_v1(fname, _read_only);
// return;
// }
// else if(version == MOVIE_VERSION)
// {}
// else
// {
// // unsupported version
// fclose(fp);
// return;
// }
//
// fread(flags, 1, 4, fp);
// read32le(&framecount, fp);
// read32le(&rerecord_count, fp);
// read32le(&moviedatasize, fp);
// read32le(&savestate_offset, fp);
// read32le(&firstframeoffset, fp);
//
// // FCEU_PrintError("flags[0] & MOVIE_FLAG_NOSYNCHACK=%d",flags[0] & MOVIE_FLAG_NOSYNCHACK);
// if(flags[0] & MOVIE_FLAG_NOSYNCHACK)
// movieSyncHackOn=0;
// else
// movieSyncHackOn=1;
//
// if(flags[0] & MOVIE_FLAG_PAL)
// {
// FCEUI_SetVidSystem(1);
// }
// else
// {
// FCEUI_SetVidSystem(0);
// }
//
//
// // fully reload the game to reinitialize everything before playing any movie
// // to try fixing nondeterministic playback of some games
// {
// extern char lastLoadedGameName [2048];
// extern int disableBatteryLoading, suppressAddPowerCommand;
// suppressAddPowerCommand=1;
// suppressMovieStop=true;
// {
// FCEUGI * gi = FCEUI_LoadGame(lastLoadedGameName, 0);
// if(!gi)
// PowerNES();
// }
// suppressMovieStop=false;
// suppressAddPowerCommand=0;
// }
//
// if(flags[0] & MOVIE_FLAG_FROM_POWERON)
// {
// //don't need to load a savestate
// //there shouldn't be a savestate!
// if(savestate_offset != 0xFFFFFFFF)
// FCEU_PrintError("Savestate found in a start-from-poweron movie!");
// }
// else
// {
// if(savestate_offset == 0xFFFFFFFF)
// FCEU_PrintError("No savestate found in a start-from-savestate movie!");
//
// if(fseek(fp, savestate_offset, SEEK_SET))
// {
// fclose(fp);
// return;
// }
//
// if(!FCEUSS_LoadFP(fp,SSLOADPARAM_BACKUP))
// return;
// }
//
// if(flags[0] & MOVIE_FLAG_PAL)
// {
// FCEUI_SetVidSystem(1);
// }
// else
// {
// FCEUI_SetVidSystem(0);
// }
// ResetInputTypes();
//
// fseek(fp, firstframeoffset, SEEK_SET);
// moviedata = (uint8*)realloc(moviedata, moviedatasize);
// fread(moviedata, 1, moviedatasize, fp);
//
// framecount = 0; // movies start at frame 0!
// frameptr = 0;
// current = 0;
// slots = fp;
//
// memset(joop,0,sizeof(joop));
// current = -1 - current;
// framets=0;
// nextts=0;
// nextd = -1;
//
// FCEU_DispMessage("Movie playback started.");
//
// strcpy(curMovieFilename, origname);
//}
//static void DoEncode(int joy, int button, int dummy)
//{
// uint8 d;
//
// d = 0;
//
// if(framets >= 65536)
// d = 3 << 5;
// else if(framets >= 256)
// d = 2 << 5;
// else if(framets > 0)
// d = 1 << 5;
//
// if(dummy) d|=0x80;
//
// d |= joy << 3;
// d |= button;
//
// movie_writechar(d);
// //printf("Wr: %02x, %d\n",d,slots[current-1]);
// while(framets)
// {
// movie_writechar(framets & 0xff);
// //printf("Wrts: %02x\n",framets & 0xff);
// framets >>= 8;
// }
//}

View File

@ -120,7 +120,7 @@ public:
std::vector<char> savestate;
std::vector<MovieRecord> records;
//this is the RERECORD COUNT. please rename variable.
int recordCount;
int rerecordCount;
FCEU_Guid guid;
//was the frame data stored in binary?

623
src/oldmovie.cpp Normal file
View File

@ -0,0 +1,623 @@
#include "types.h"
#include "fceu.h"
#include "driver.h"
#include "oldmovie.h"
#include "movie.h"
#include <fstream>
using namespace std;
// FCM\x1a
#define MOVIE_MAGIC 0x1a4d4346
// still at 2 since the format itself is still compatible
// to detect which version the movie was made with, check the fceu version stored in the movie header
// (e.g against FCEU_VERSION_NUMERIC)
#define MOVIE_VERSION 2
//-------
//this is just supposed to be a comment describing the disk format
//---
//struct MovieHeader
//{
//uint32 magic; // +0
//uint32 version=2; // +4
//uint8 flags[4]; // +8
//uint32 length_frames; // +12
//uint32 rerecord_count; // +16
//uint32 movie_data_size; // +20
//uint32 offset_to_savestate; // +24, should be 4-byte-aligned
//uint32 offset_to_movie_data; // +28, should be 4-byte-aligned
//uint8 md5_of_rom_used[16]; // +32
//uint32 version_of_emu_used // +48
//char name_of_rom_used[] // +52, utf-8, null-terminated
//char metadata[]; // utf-8, null-terminated
//uint8 padding[];
//uint8 savestate[]; // always present, even in a "from reset" recording
//uint8 padding[]; // used for byte-alignment
//uint8 movie_data[];
//};
//-------
static uint8 joop[4];
static uint32 framets = 0;
static uint32 frameptr = 0;
static uint8* moviedata = NULL;
static uint32 moviedatasize = 0;
static uint32 firstframeoffset = 0;
static uint32 savestate_offset = 0;
//Cache variables used for playback.
static uint32 nextts = 0;
static int32 nextd = 0;
static int movieConvertOffset1=0, movieConvertOffset2=0,movieSyncHackOn=0;
//backwards compat
static void FCEUI_LoadMovie_v1(char *fname, int _read_only);
//static int FCEUI_MovieGetInfo_v1(const char* fname, MOVIE_INFO* info);
//int _old_FCEUI_MovieGetInfo(const char* fname, MOVIE_INFO* info)
//{
// //mbg: wtf?
// //MovieFlushHeader();
//
// // main get info part of function
// {
// uint32 magic;
// uint32 version;
// uint8 _flags[4];
//
// FILE* fp = FCEUD_UTF8fopen(fname, "rb");
// if(!fp)
// return 0;
//
// read32le(&magic, fp);
// if(magic != MOVIE_MAGIC)
// {
// fclose(fp);
// return 0;
// }
//
// read32le(&version, fp);
// if(version != MOVIE_VERSION)
// {
// fclose(fp);
// if(version == 1)
// return FCEUI_MovieGetInfo_v1(fname, info);
// else
// return 0;
// }
//
// info->movie_version = MOVIE_VERSION;
//
// fread(_flags, 1, 4, fp);
//
// info->flags = _flags[0];
// read32le(&info->num_frames, fp);
// read32le(&info->rerecord_count, fp);
//
// if(access(fname, W_OK))
// info->read_only = 1;
// else
// info->read_only = 0;
//
// fseek(fp, 12, SEEK_CUR); // skip movie_data_size, offset_to_savestate, and offset_to_movie_data
//
// fread(&info->md5_of_rom_used, 1, 16, fp);
// info->md5_of_rom_used_present = 1;
//
// read32le(&info->emu_version_used, fp);
//
// // I probably could have planned this better...
// {
// char str[256];
// size_t r;
// uint32 p; //mbg merge 7/17/06 change to uint32
// int p2=0;
// char last_c=32;
//
// if(info->name_of_rom_used && info->name_of_rom_used_size)
// info->name_of_rom_used[0]='\0';
//
// r=fread(str, 1, 256, fp);
// while(r > 0)
// {
// for(p=0; p<r && last_c != '\0'; ++p)
// {
// if(info->name_of_rom_used && info->name_of_rom_used_size && (p2 < info->name_of_rom_used_size-1))
// {
// info->name_of_rom_used[p2]=str[p];
// p2++;
// last_c=str[p];
// }
// }
// if(p<r)
// {
// memmove(str, str+p, r-p);
// r -= p;
// break;
// }
// r=fread(str, 1, 256, fp);
// }
//
// p2=0;
// last_c=32;
//
// if(info->metadata && info->metadata_size)
// info->metadata[0]='\0';
//
// while(r > 0)
// {
// for(p=0; p<r && last_c != '\0'; ++p)
// {
// if(info->metadata && info->metadata_size && (p2 < info->metadata_size-1))
// {
// info->metadata[p2]=str[p];
// p2++;
// last_c=str[p];
// }
// }
// if(p != r)
// break;
// r=fread(str, 1, 256, fp);
// }
//
// if(r<=0)
// {
// // somehow failed to read romname and metadata
// fclose(fp);
// return 0;
// }
// }
//
// // check what hacks are necessary
// fseek(fp, 24, SEEK_SET); // offset_to_savestate offset
// uint32 temp_savestate_offset;
// read32le(&temp_savestate_offset, fp);
// if(temp_savestate_offset != 0xFFFFFFFF)
// {
// if(fseek(fp, temp_savestate_offset, SEEK_SET))
// {
// fclose(fp);
// return 0;
// }
//
// //don't really load, just load to find what's there then load backup
// if(!FCEUSS_LoadFP(fp,SSLOADPARAM_DUMMY)) return 0;
// }
//
// fclose(fp);
// return 1;
// }
//}
/*
Backwards compat
*/
/*
struct MovieHeader_v1
{
uint32 magic;
uint32 version=1;
uint8 flags[4];
uint32 length_frames;
uint32 rerecord_count;
uint32 movie_data_size;
uint32 offset_to_savestate;
uint32 offset_to_movie_data;
uint16 metadata_ucs2[]; // ucs-2, ick! sizeof(metadata) = offset_to_savestate - MOVIE_HEADER_SIZE
}
*/
#define MOVIE_V1_HEADER_SIZE 32
//static void FCEUI_LoadMovie_v1(char *fname, int _read_only)
//{
// FILE *fp;
// char *fn = NULL;
//
// FCEUI_StopMovie();
//
// if(!fname)
// fname = fn = FCEU_MakeFName(FCEUMKF_MOVIE,0,0);
//
// // check movie_readonly
// movie_readonly = _read_only;
// if(access(fname, W_OK))
// movie_readonly = 2;
//
// fp = FCEUD_UTF8fopen(fname, (movie_readonly>=2) ? "rb" : "r+b");
//
// if(fn)
// {
// free(fn);
// fname = NULL;
// }
//
// if(!fp) return;
//
// // read header
// {
// uint32 magic;
// uint32 version;
// uint8 flags[4];
// uint32 fc;
//
// read32le(&magic, fp);
// if(magic != MOVIE_MAGIC)
// {
// fclose(fp);
// return;
// }
//
// read32le(&version, fp);
// if(version != 1)
// {
// fclose(fp);
// return;
// }
//
// fread(flags, 1, 4, fp);
// read32le(&fc, fp);
// read32le(&rerecord_count, fp);
// read32le(&moviedatasize, fp);
// read32le(&savestate_offset, fp);
// read32le(&firstframeoffset, fp);
// if(fseek(fp, savestate_offset, SEEK_SET))
// {
// fclose(fp);
// return;
// }
//
// if(flags[0] & MOVIE_FLAG_NOSYNCHACK)
// movieSyncHackOn=0;
// else
// movieSyncHackOn=1;
// }
//
// // fully reload the game to reinitialize everything before playing any movie
// // to try fixing nondeterministic playback of some games
// {
// extern char lastLoadedGameName [2048];
// extern int disableBatteryLoading, suppressAddPowerCommand;
// suppressAddPowerCommand=1;
// suppressMovieStop=true;
// {
// FCEUGI * gi = FCEUI_LoadGame(lastLoadedGameName, 0);
// if(!gi)
// PowerNES();
// }
// suppressMovieStop=false;
// suppressAddPowerCommand=0;
// }
//
// if(!FCEUSS_LoadFP(fp,SSLOADPARAM_BACKUP)) return;
//
// ResetInputTypes();
//
// fseek(fp, firstframeoffset, SEEK_SET);
// moviedata = (uint8*)realloc(moviedata, moviedatasize);
// fread(moviedata, 1, moviedatasize, fp);
//
// framecount = 0; // movies start at frame 0!
// frameptr = 0;
// current = 0;
// slots = fp;
//
// memset(joop,0,sizeof(joop));
// current = -1 - current;
// framets=0;
// nextts=0;
// nextd = -1;
// FCEU_DispMessage("Movie playback started.");
//}
//
//static int FCEUI_MovieGetInfo_v1(const char* fname, MOVIE_INFO* info)
//{
// uint32 magic;
// uint32 version;
// uint8 _flags[4];
// uint32 savestateoffset;
// uint8 tmp[MOVIE_MAX_METADATA<<1];
// int metadata_length;
//
// FILE* fp = FCEUD_UTF8fopen(fname, "rb");
// if(!fp)
// return 0;
//
// read32le(&magic, fp);
// if(magic != MOVIE_MAGIC)
// {
// fclose(fp);
// return 0;
// }
//
// read32le(&version, fp);
// if(version != 1)
// {
// fclose(fp);
// return 0;
// }
//
// info->movie_version = 1;
// info->emu_version_used = 0; // unknown
//
// fread(_flags, 1, 4, fp);
//
// info->flags = _flags[0];
// read32le(&info->num_frames, fp);
// read32le(&info->rerecord_count, fp);
//
// if(access(fname, W_OK))
// info->read_only = 1;
// else
// info->read_only = 0;
//
// fseek(fp, 4, SEEK_CUR);
// read32le(&savestateoffset, fp);
//
// metadata_length = (int)savestateoffset - MOVIE_V1_HEADER_SIZE;
// if(metadata_length > 0)
// {
// //int i; //mbg merge 7/17/06 removed
//
// metadata_length >>= 1;
// if(metadata_length >= MOVIE_MAX_METADATA)
// metadata_length = MOVIE_MAX_METADATA-1;
//
// fseek(fp, MOVIE_V1_HEADER_SIZE, SEEK_SET);
// fread(tmp, 1, metadata_length<<1, fp);
// }
//
// // turn old ucs2 metadata into utf8
// if(info->metadata && info->metadata_size)
// {
// char* ptr=info->metadata;
// char* ptr_end=info->metadata+info->metadata_size-1;
// int c_ptr=0;
// while(ptr<ptr_end && c_ptr<metadata_length)
// {
// uint16 c=(tmp[c_ptr<<1] | (tmp[(c_ptr<<1)+1] << 8));
// //mbg merge 7/17/06 changed to if..elseif
// if(c<=0x7f)
// *ptr++ = (char)(c&0x7f);
// else if(c<=0x7FF)
// if(ptr+1>=ptr_end)
// ptr_end=ptr;
// else
// {
// *ptr++=(0xc0 | (c>>6));
// *ptr++=(0x80 | (c & 0x3f));
// }
// else
// if(ptr+2>=ptr_end)
// ptr_end=ptr;
// else
// {
// *ptr++=(0xe0 | (c>>12));
// *ptr++=(0x80 | ((c>>6) & 0x3f));
// *ptr++=(0x80 | (c & 0x3f));
// }
//
// c_ptr++;
// }
// *ptr='\0';
// }
//
// // md5 info not available from v1
// info->md5_of_rom_used_present = 0;
// // rom name used for the movie not available from v1
// if(info->name_of_rom_used && info->name_of_rom_used_size)
// info->name_of_rom_used[0] = '\0';
//
// // check what hacks are necessary
// fseek(fp, 24, SEEK_SET); // offset_to_savestate offset
// uint32 temp_savestate_offset;
// read32le(&temp_savestate_offset, fp);
// if(fseek(fp, temp_savestate_offset, SEEK_SET))
// {
// fclose(fp);
// return 0;
// }
// if(!FCEUSS_LoadFP(fp,SSLOADPARAM_DUMMY)) return 0; // 2 -> don't really load, just load to find what's there then load backup
//
//
// fclose(fp);
// return 1;
//}
static int movie_readchar()
{
if(frameptr >= moviedatasize)
{
return -1;
}
return (int)(moviedata[frameptr++]);
}
static void FCEUMOV_AddJoy()
{
while(nextts == framets || nextd == -1)
{
int tmp,ti;
uint8 d;
if(nextd != -1)
{
if(nextd&0x80)
{
//puts("Egads");
//FCEU_DoSimpleCommand(nextd&0x1F);
}
else
joop[(nextd >> 3)&0x3] ^= 1 << (nextd&0x7);
}
tmp = movie_readchar();
d = tmp;
if(tmp < 0)
{
return;
}
nextts = 0;
tmp >>= 5;
tmp &= 0x3;
ti=0;
int tmpfix = tmp;
while(tmp--) { nextts |= movie_readchar() << (ti * 8); ti++; }
// This fixes a bug in movies recorded before version 0.98.11
// It's probably not necessary, but it may keep away CRAZY PEOPLE who recorded
// movies on <= 0.98.10 and don't work on playback.
if(tmpfix == 1 && !nextts)
{nextts |= movie_readchar()<<8; }
else if(tmpfix == 2 && !nextts) {nextts |= movie_readchar()<<16; }
if(nextd != -1)
framets = 0;
nextd = d;
}
framets++;
}
EFCM_CONVERTRESULT convert_fcm(MovieData& md, std::string fname)
{
//convert EVEN OLDER movies to fcm
//fname = (char*)convertToFCM(fname,buffer);
uint32 framecount;
uint32 rerecord_count;
ifstream* fp = (ifstream*)FCEUD_UTF8_fstream(fname, "rb");
if(!fp) false;
// read header
uint32 magic;
uint32 version;
uint8 flags[4];
read32le(&magic, fp);
if(magic != MOVIE_MAGIC)
{
delete fp;
return FCM_CONVERTRESULT_FAILOPEN;
}
read32le(&version, fp);
if(version == 1)
{
// attempt to load previous version's format
//TODO
delete fp;
//FCEUI_LoadMovie_v1(fname, _read_only);
return FCM_CONVERTRESULT_OLDVERSION;
}
else if(version == MOVIE_VERSION)
{}
else
{
// unsupported version
delete fp;
return FCM_CONVERTRESULT_UNSUPPORTEDVERSION;
}
fp->read((char*)&flags,4);
read32le(&framecount, fp);
read32le(&rerecord_count, fp);
read32le(&moviedatasize, fp);
read32le(&savestate_offset, fp);
read32le(&firstframeoffset, fp);
// FCEU_PrintError("flags[0] & MOVIE_FLAG_NOSYNCHACK=%d",flags[0] & MOVIE_FLAG_NOSYNCHACK);
if(flags[0] & MOVIE_FLAG_NOSYNCHACK)
movieSyncHackOn=0;
else
movieSyncHackOn=1;
//if(flags[0] & MOVIE_FLAG_PAL)
//if(flags[0] & MOVIE_FLAG_FROM_POWERON)
//{
// //don't need to load a savestate
// //there shouldn't be a savestate!
// if(savestate_offset != 0xFFFFFFFF)
// FCEU_PrintError("Savestate found in a start-from-poweron movie!");
//}
//else
//{
// if(savestate_offset == 0xFFFFFFFF)
// FCEU_PrintError("No savestate found in a start-from-savestate movie!");
// if(fseek(fp, savestate_offset, SEEK_SET))
// {
// fclose(fp);
// return;
// }
// if(!FCEUSS_LoadFP(fp,SSLOADPARAM_BACKUP))
// return;
//}
//analyze input types?
//ResetInputTypes();
fp->seekg(firstframeoffset,ios::beg);
moviedata = (uint8*)realloc(moviedata, moviedatasize);
fp->read((char*)moviedata,moviedatasize);
frameptr = 0;
memset(joop,0,sizeof(joop));
framets=0;
nextts=0;
nextd = -1;
//prepare output structure
md.rerecordCount = rerecord_count;
md.records.resize(framecount);
//begin decoding.
//joymask is used to look for any joystick that has input.
//if joysticks 3 or 4 have input then we will enable fourscore
uint8 joymask[4] = {0,0,0,0};
for(uint32 i=0;i<framecount;i++)
{
FCEUMOV_AddJoy();
md.records[i].commands = 0;
for(int j=0;j<4;j++) {
joymask[j] |= joop[j];
md.records[i].joysticks[j] = joop[j];
}
}
md.ports[2] = SIS_NONE;
if(joymask[2] || joymask[3])
{
md.fourscore = true;
md.ports[0] = md.ports[1] = SI_NONE;
}
else
{
md.fourscore = false;
md.ports[0] = md.ports[1] = SI_GAMEPAD ;
}
free(moviedata);
moviedata = 0;
return FCM_CONVERTRESULT_SUCCESS;
}

16
src/oldmovie.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef _OLDMOVIE_H_
#define _OLDMOVIE_H_
#include "movie.h"
enum EFCM_CONVERTRESULT
{
FCM_CONVERTRESULT_SUCCESS,
FCM_CONVERTRESULT_FAILOPEN,
FCM_CONVERTRESULT_OLDVERSION,
FCM_CONVERTRESULT_UNSUPPORTEDVERSION,
};
EFCM_CONVERTRESULT convert_fcm(MovieData& md, std::string fname);
#endif

View File

@ -1579,6 +1579,10 @@
RelativePath="..\src\nsf.h"
>
</File>
<File
RelativePath="..\src\oldmovie.h"
>
</File>
<File
RelativePath="..\src\palette.h"
>
@ -2321,6 +2325,10 @@
RelativePath="..\src\nsf.cpp"
>
</File>
<File
RelativePath="..\src\oldmovie.cpp"
>
</File>
<File
RelativePath="..\src\palette.cpp"
>