clean up movie some code; no longer write savestate with play-from-poweron movies; change main logging format to text (the header still needs to be changed)
This commit is contained in:
parent
9477c03c09
commit
047808ba93
|
@ -23,15 +23,17 @@ FCEU MM - CaH4e3\n\
|
||||||
FCEU TAS - blip & nitsuja\n\
|
FCEU TAS - blip & nitsuja\n\
|
||||||
FCEU TAS+ - Luke Gustafson\n\
|
FCEU TAS+ - Luke Gustafson\n\
|
||||||
FCEUX\n\
|
FCEUX\n\
|
||||||
- CaH4e3, Luke Gustafson\n\
|
- rheiny, zeromus\n\
|
||||||
- Matthew Gambrell, Sebastian Porst\n\
|
- CaH4e3, Luke Gustafson, Sebastian Porst\n\
|
||||||
|
- adelikat, _mz\n\
|
||||||
\n\
|
\n\
|
||||||
"__TIME__" "__DATE__"\n";
|
"__TIME__" "__DATE__"\n";
|
||||||
|
|
||||||
|
if(aboutString) return aboutString;
|
||||||
|
|
||||||
const char *compilerString = FCEUD_GetCompilerString();
|
const char *compilerString = FCEUD_GetCompilerString();
|
||||||
|
|
||||||
//allocate the string and concatenate the template with the compiler string
|
//allocate the string and concatenate the template with the compiler string
|
||||||
if(aboutString) free(aboutString);
|
|
||||||
aboutString = (char*)malloc(strlen(aboutTemplate) + strlen(compilerString) + 1);
|
aboutString = (char*)malloc(strlen(aboutTemplate) + strlen(compilerString) + 1);
|
||||||
sprintf(aboutString,"%s%s",aboutTemplate,compilerString);
|
sprintf(aboutString,"%s%s",aboutTemplate,compilerString);
|
||||||
return aboutString;
|
return aboutString;
|
||||||
|
|
|
@ -175,9 +175,11 @@ void FCEUI_LoadState(char *fname);
|
||||||
void FCEUD_SaveStateAs(void);
|
void FCEUD_SaveStateAs(void);
|
||||||
void FCEUD_LoadStateFrom(void);
|
void FCEUD_LoadStateFrom(void);
|
||||||
|
|
||||||
#define MOVIE_FLAG_FROM_RESET (1<<1)
|
//movie was recorded from poweron. the alternative is from a savestate
|
||||||
|
#define MOVIE_FLAG_FROM_POWERON (1<<3)
|
||||||
|
|
||||||
#define MOVIE_FLAG_PAL (1<<2)
|
#define MOVIE_FLAG_PAL (1<<2)
|
||||||
#define MOVIE_FLAG_FROM_POWERON (1<<3) // value is temporary onle, gets converted to reset
|
|
||||||
#define MOVIE_MAX_METADATA 512
|
#define MOVIE_MAX_METADATA 512
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|
|
@ -223,7 +223,7 @@ void UpdateReplayDialog(HWND hwndDlg)
|
||||||
EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK_READONLY),(info.read_only)? FALSE : TRUE); // disable read-only checkbox if the file access is read-only
|
EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK_READONLY),(info.read_only)? FALSE : TRUE); // disable read-only checkbox if the file access is read-only
|
||||||
SendDlgItemMessage(hwndDlg,IDC_CHECK_READONLY,BM_SETCHECK,info.read_only ? BST_CHECKED : (ReplayDialogReadOnlyStatus ? BST_CHECKED : BST_UNCHECKED), 0);
|
SendDlgItemMessage(hwndDlg,IDC_CHECK_READONLY,BM_SETCHECK,info.read_only ? BST_CHECKED : (ReplayDialogReadOnlyStatus ? BST_CHECKED : BST_UNCHECKED), 0);
|
||||||
|
|
||||||
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_RECORDEDFROM),(info.flags & MOVIE_FLAG_FROM_RESET) ? "Reset or Power-On" : "Savestate");
|
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_RECORDEDFROM),(info.flags & MOVIE_FLAG_FROM_POWERON) ? "Power-On" : "Savestate");
|
||||||
if(info.movie_version > 1)
|
if(info.movie_version > 1)
|
||||||
{
|
{
|
||||||
char emuStr[128];
|
char emuStr[128];
|
||||||
|
@ -863,10 +863,9 @@ void FCEUD_MovieRecordTo()
|
||||||
free(p.szSavestateFilename);
|
free(p.szSavestateFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
FCEUI_SaveMovie(
|
uint8 flags = 0;
|
||||||
p.szFilename,
|
if(p.recordFrom == 0) flags = MOVIE_FLAG_FROM_POWERON;
|
||||||
(p.recordFrom == 0) ? MOVIE_FLAG_FROM_POWERON : ((p.recordFrom == 1) ? MOVIE_FLAG_FROM_RESET : 0),
|
FCEUI_SaveMovie(p.szFilename, flags, meta);
|
||||||
meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(p.szFilename)
|
if(p.szFilename)
|
||||||
|
|
|
@ -506,7 +506,7 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski
|
||||||
|
|
||||||
if(EmulationPaused&2)
|
if(EmulationPaused&2)
|
||||||
EmulationPaused &= ~1; // clear paused flag temporarily (frame advance)
|
EmulationPaused &= ~1; // clear paused flag temporarily (frame advance)
|
||||||
else if(EmulationPaused&1 || FCEU_BotMode())
|
else if((EmulationPaused&1) || FCEU_BotMode())
|
||||||
{
|
{
|
||||||
memcpy(XBuf, XBackBuf, 256*256);
|
memcpy(XBuf, XBackBuf, 256*256);
|
||||||
FCEU_PutImage();
|
FCEU_PutImage();
|
||||||
|
|
333
src/movie.cpp
333
src/movie.cpp
|
@ -1,7 +1,8 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
//#include <unistd.h> //mbgm erge 7/17/06 removed
|
#include <assert.h>
|
||||||
|
|
||||||
#ifdef MSVC
|
#ifdef MSVC
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,28 +33,28 @@ extern char FileBase[];
|
||||||
/*
|
/*
|
||||||
struct MovieHeader
|
struct MovieHeader
|
||||||
{
|
{
|
||||||
uint32 magic; // +0
|
uint32 magic; // +0
|
||||||
uint32 version=2; // +4
|
uint32 version=2; // +4
|
||||||
uint8 flags[4]; // +8
|
uint8 flags[4]; // +8
|
||||||
uint32 length_frames; // +12
|
uint32 length_frames; // +12
|
||||||
uint32 rerecord_count; // +16
|
uint32 rerecord_count; // +16
|
||||||
uint32 movie_data_size; // +20
|
uint32 movie_data_size; // +20
|
||||||
uint32 offset_to_savestate; // +24, should be 4-byte-aligned
|
uint32 offset_to_savestate; // +24, should be 4-byte-aligned
|
||||||
uint32 offset_to_movie_data; // +28, should be 4-byte-aligned
|
uint32 offset_to_movie_data; // +28, should be 4-byte-aligned
|
||||||
uint8 md5_of_rom_used[16]; // +32
|
uint8 md5_of_rom_used[16]; // +32
|
||||||
uint32 version_of_emu_used // +48
|
uint32 version_of_emu_used // +48
|
||||||
char name_of_rom_used[] // +52, utf-8, null-terminated
|
char name_of_rom_used[] // +52, utf-8, null-terminated
|
||||||
char metadata[]; // utf-8, null-terminated
|
char metadata[]; // utf-8, null-terminated
|
||||||
uint8 padding[];
|
uint8 padding[];
|
||||||
uint8 savestate[]; // always present, even in a "from reset" recording
|
uint8 savestate[]; // always present, even in a "from reset" recording
|
||||||
uint8 padding[]; // used for byte-alignment
|
uint8 padding[]; // used for byte-alignment
|
||||||
uint8 movie_data[];
|
uint8 movie_data[];
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int current = 0; // > 0 for recording, < 0 for playback
|
static int current = 0; // > 0 for recording, < 0 for playback
|
||||||
static FILE *slots[10]={0};
|
static FILE *slots[10]={0};
|
||||||
static uint8 joop[4];
|
static uint8 joop[4]; //mbg 5/22/08 - seems to be a snapshot of the joystates for delta compression
|
||||||
static uint32 framets = 0;
|
static uint32 framets = 0;
|
||||||
static uint32 frameptr = 0;
|
static uint32 frameptr = 0;
|
||||||
static uint8* moviedata = NULL;
|
static uint8* moviedata = NULL;
|
||||||
|
@ -311,7 +312,7 @@ static const char* convertToFCM(const char *fname, char *buffer)
|
||||||
if(movieConvertOffset2) sprintf(offset, "-o %d:%d", movieConvertOffset2,movieConvertOffset1);
|
if(movieConvertOffset2) sprintf(offset, "-o %d:%d", movieConvertOffset2,movieConvertOffset1);
|
||||||
else sprintf(offset, "-o %d", movieConvertOffset1);
|
else sprintf(offset, "-o %d", movieConvertOffset1);
|
||||||
sprintf(cmd, ".\\util\\nesmock\\nesmock.exe %s %s -spal=%c -sfceuver=%d \"%s\" \"%s\" ", offset, romInfo, FCEUI_GetCurrentVidSystem(0,0)?'1':'0', fceuver, fname, buffer);
|
sprintf(cmd, ".\\util\\nesmock\\nesmock.exe %s %s -spal=%c -sfceuver=%d \"%s\" \"%s\" ", offset, romInfo, FCEUI_GetCurrentVidSystem(0,0)?'1':'0', fceuver, fname, buffer);
|
||||||
// FCEU_PrintError(cmd);
|
// FCEU_PrintError(cmd);
|
||||||
executeCommand(cmd);
|
executeCommand(cmd);
|
||||||
|
|
||||||
FILE* file = FCEUD_UTF8fopen(buffer,"rb");
|
FILE* file = FCEUD_UTF8fopen(buffer,"rb");
|
||||||
|
@ -405,8 +406,8 @@ void FCEUI_LoadMovie(char *fname, int _read_only, int _stopframe)
|
||||||
if(!fname)
|
if(!fname)
|
||||||
fname = fn = FCEU_MakeFName(FCEUMKF_MOVIE,CurrentMovie,0);
|
fname = fn = FCEU_MakeFName(FCEUMKF_MOVIE,CurrentMovie,0);
|
||||||
|
|
||||||
char origname[512];
|
char origname[512];
|
||||||
strcpy(origname,fname);
|
strcpy(origname,fname);
|
||||||
|
|
||||||
stopframe = _stopframe;
|
stopframe = _stopframe;
|
||||||
|
|
||||||
|
@ -437,7 +438,7 @@ strcpy(origname,fname);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//DEBUG_COMPARE_RAM(__LINE__);
|
//DEBUG_COMPARE_RAM(__LINE__);
|
||||||
|
|
||||||
read32le(&version, fp);
|
read32le(&version, fp);
|
||||||
if(version == 1)
|
if(version == 1)
|
||||||
|
@ -462,13 +463,8 @@ strcpy(origname,fname);
|
||||||
read32le(&moviedatasize, fp);
|
read32le(&moviedatasize, fp);
|
||||||
read32le(&savestate_offset, fp);
|
read32le(&savestate_offset, fp);
|
||||||
read32le(&firstframeoffset, fp);
|
read32le(&firstframeoffset, fp);
|
||||||
if(fseek(fp, savestate_offset, SEEK_SET))
|
|
||||||
{
|
|
||||||
fclose(fp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FCEU_PrintError("flags[0] & MOVIE_FLAG_NOSYNCHACK=%d",flags[0] & MOVIE_FLAG_NOSYNCHACK);
|
// FCEU_PrintError("flags[0] & MOVIE_FLAG_NOSYNCHACK=%d",flags[0] & MOVIE_FLAG_NOSYNCHACK);
|
||||||
if(flags[0] & MOVIE_FLAG_NOSYNCHACK)
|
if(flags[0] & MOVIE_FLAG_NOSYNCHACK)
|
||||||
movieSyncHackOn=0;
|
movieSyncHackOn=0;
|
||||||
else
|
else
|
||||||
|
@ -500,7 +496,28 @@ strcpy(origname,fname);
|
||||||
suppressAddPowerCommand=0;
|
suppressAddPowerCommand=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!FCEUSS_LoadFP(fp,1)) return;
|
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)
|
if(flags[0] & MOVIE_FLAG_PAL)
|
||||||
{
|
{
|
||||||
FCEUI_SetVidSystem(1);
|
FCEUI_SetVidSystem(1);
|
||||||
|
@ -539,7 +556,6 @@ void FCEUI_SaveMovie(char *fname, uint8 flags, const char* metadata)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *fn;
|
char *fn;
|
||||||
int poweron=0;
|
|
||||||
uint8 padding[4] = {0,0,0,0};
|
uint8 padding[4] = {0,0,0,0};
|
||||||
int n_padding;
|
int n_padding;
|
||||||
|
|
||||||
|
@ -568,13 +584,6 @@ void FCEUI_SaveMovie(char *fname, uint8 flags, const char* metadata)
|
||||||
if(FCEUI_GetCurrentVidSystem(0,0))
|
if(FCEUI_GetCurrentVidSystem(0,0))
|
||||||
flags |= MOVIE_FLAG_PAL;
|
flags |= MOVIE_FLAG_PAL;
|
||||||
|
|
||||||
if(flags & MOVIE_FLAG_FROM_POWERON)
|
|
||||||
{
|
|
||||||
poweron=1;
|
|
||||||
flags &= ~MOVIE_FLAG_FROM_POWERON;
|
|
||||||
flags |= MOVIE_FLAG_FROM_RESET;
|
|
||||||
}
|
|
||||||
|
|
||||||
// write header
|
// write header
|
||||||
write32le(MOVIE_MAGIC, fp);
|
write32le(MOVIE_MAGIC, fp);
|
||||||
write32le(MOVIE_VERSION, fp);
|
write32le(MOVIE_VERSION, fp);
|
||||||
|
@ -604,9 +613,7 @@ void FCEUI_SaveMovie(char *fname, uint8 flags, const char* metadata)
|
||||||
n_padding = (4 - (ftell(fp) & 0x3)) & 0x3;
|
n_padding = (4 - (ftell(fp) & 0x3)) & 0x3;
|
||||||
fwrite(padding, 1, n_padding, fp);
|
fwrite(padding, 1, n_padding, fp);
|
||||||
|
|
||||||
if(flags & MOVIE_FLAG_FROM_RESET)
|
if(flags & MOVIE_FLAG_FROM_POWERON)
|
||||||
{
|
|
||||||
if(poweron)
|
|
||||||
{
|
{
|
||||||
// make a for-movie-recording power-on clear the game's save data, too
|
// make a for-movie-recording power-on clear the game's save data, too
|
||||||
// (note: FCEU makes a save state immediately after this and that loads that on movie playback)
|
// (note: FCEU makes a save state immediately after this and that loads that on movie playback)
|
||||||
|
@ -624,11 +631,16 @@ void FCEUI_SaveMovie(char *fname, uint8 flags, const char* metadata)
|
||||||
suppressMovieStop=0;
|
suppressMovieStop=0;
|
||||||
disableBatteryLoading=0;
|
disableBatteryLoading=0;
|
||||||
suppressAddPowerCommand=0;
|
suppressAddPowerCommand=0;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//no savestate
|
||||||
|
savestate_offset = 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
savestate_offset = ftell(fp);
|
savestate_offset = ftell(fp);
|
||||||
FCEUSS_SaveFP(fp);
|
FCEUSS_SaveFP(fp);
|
||||||
|
}
|
||||||
|
|
||||||
fseek(fp, 0, SEEK_END);
|
fseek(fp, 0, SEEK_END);
|
||||||
|
|
||||||
ResetInputTypes();
|
ResetInputTypes();
|
||||||
|
@ -659,16 +671,18 @@ void FCEUI_SaveMovie(char *fname, uint8 flags, const char* metadata)
|
||||||
framets=0;
|
framets=0;
|
||||||
nextd = -1;
|
nextd = -1;
|
||||||
|
|
||||||
// trigger a reset
|
//mbg 5/22/08 - I didnt delete this because I thought it was interesting
|
||||||
if(flags & MOVIE_FLAG_FROM_RESET)
|
//// trigger a reset
|
||||||
{
|
//if(flags & MOVIE_FLAG_FROM_RESET)
|
||||||
if(poweron)
|
//{
|
||||||
{
|
// if(poweron)
|
||||||
PowerNES(); // NOTE: this will write an FCEUNPCMD_POWER into the movie file
|
// {
|
||||||
}
|
// PowerNES(); // NOTE: this will write an FCEUNPCMD_POWER into the movie file
|
||||||
else
|
// }
|
||||||
ResetNES(); // NOTE: this will write an FCEUNPCMD_RESET into the movie file
|
// else
|
||||||
}
|
// ResetNES(); // NOTE: this will write an FCEUNPCMD_RESET into the movie file
|
||||||
|
//}
|
||||||
|
|
||||||
if(!fname)
|
if(!fname)
|
||||||
FCEUI_SelectMovie(CurrentMovie,1); /* Quick hack to display status. */
|
FCEUI_SelectMovie(CurrentMovie,1); /* Quick hack to display status. */
|
||||||
else
|
else
|
||||||
|
@ -725,87 +739,141 @@ static void DoEncode(int joy, int button, int dummy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: make this function legible! (what are all these magic numbers and weirdly named variables and crazy unexplained loops?)
|
//the main interaction point between the emulator and the movie system.
|
||||||
|
//either dumps the current joystick state or loads one state from the movie
|
||||||
void FCEUMOV_AddJoy(uint8 *js, int SkipFlush)
|
void FCEUMOV_AddJoy(uint8 *js, int SkipFlush)
|
||||||
{
|
{
|
||||||
int x,y;
|
int x,y;
|
||||||
|
|
||||||
// if(!current) return; // Not playback nor recording.
|
// if(!current) return; // Not playback nor recording.
|
||||||
|
|
||||||
if(current < 0) // Playback
|
if(current < 0) // Playback
|
||||||
{
|
{
|
||||||
while(nextts == framets || nextd == -1)
|
//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)
|
||||||
|
// {
|
||||||
|
// StopPlayback();
|
||||||
|
// memcpy(&cur_input_display,js,4);
|
||||||
|
// 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;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//memcpy(js,joop,4);
|
||||||
|
|
||||||
|
//TODO - rock solid stability and error detection
|
||||||
|
|
||||||
|
//for each joystick
|
||||||
|
for(int i=0;i<4;i++)
|
||||||
{
|
{
|
||||||
int tmp,ti;
|
uint8 &joystate = js[i];
|
||||||
uint8 d;
|
joystate = 0;
|
||||||
|
for(int bit=7;bit>=0;bit--)
|
||||||
if(nextd != -1)
|
|
||||||
{
|
{
|
||||||
if(nextd&0x80)
|
int c = movie_readchar();
|
||||||
{
|
if(c == -1)
|
||||||
//puts("Egads");
|
|
||||||
FCEU_DoSimpleCommand(nextd&0x1F);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
joop[(nextd >> 3)&0x3] ^= 1 << (nextd&0x7);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
tmp = movie_readchar();
|
|
||||||
d = tmp;
|
|
||||||
|
|
||||||
if(tmp < 0)
|
|
||||||
{
|
{
|
||||||
StopPlayback();
|
StopPlayback();
|
||||||
memcpy(&cur_input_display,js,4);
|
goto bail;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
if(c != ' ')
|
||||||
nextts = 0;
|
joystate |= (1<<bit);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
//eat the separator (a pipe or a newline)
|
||||||
|
movie_readchar();
|
||||||
|
}
|
||||||
|
bail: ;
|
||||||
|
|
||||||
memcpy(js,joop,4);
|
|
||||||
}
|
}
|
||||||
else if(current > 0) // Recording
|
else if(current > 0) // Recording
|
||||||
{
|
{
|
||||||
// flush header info every 300 frames in case of crash
|
//mbg 5/22/08 - keep dumping the header for now
|
||||||
//Don't if in bot mode--we don't need extra overhead
|
|
||||||
if(!SkipFlush)
|
|
||||||
{
|
|
||||||
static int fcounter=0;
|
|
||||||
fcounter++;
|
|
||||||
if(!(fcounter%300))
|
|
||||||
MovieFlushHeader();
|
MovieFlushHeader();
|
||||||
|
//// flush header info every 300 frames in case of crash
|
||||||
|
////Don't if in bot mode--we don't need extra overhead
|
||||||
|
//if(!SkipFlush)
|
||||||
|
//{
|
||||||
|
// static int fcounter=0;
|
||||||
|
// fcounter++;
|
||||||
|
// if(!(fcounter%300))
|
||||||
|
// MovieFlushHeader();
|
||||||
|
//}
|
||||||
|
|
||||||
|
//for(x=0;x<4;x++)
|
||||||
|
//{
|
||||||
|
// if(js[x] != joop[x])
|
||||||
|
// {
|
||||||
|
// for(y=0;y<8;y++)
|
||||||
|
// if((js[x] ^ joop[x]) & (1 << y))
|
||||||
|
// DoEncode(x, y, 0);
|
||||||
|
// joop[x] = js[x];
|
||||||
|
// }
|
||||||
|
// else if(framets == ((1<<24)-1)) DoEncode(0,0,1); // Overflow will happen, so do dummy update.
|
||||||
|
//}
|
||||||
|
|
||||||
|
//for each joystick
|
||||||
|
for(int i=0;i<4;i++)
|
||||||
|
{
|
||||||
|
//these are mnemonics for each joystick bit.
|
||||||
|
//since we usually use the regular joypad, these will be more helpful.
|
||||||
|
//but any character other than ' ' should count as a set bit
|
||||||
|
//maybe other input types will need to be encoded another way..
|
||||||
|
const char mnemonics[] = {'A','B','S','T','U','D','L','R'};
|
||||||
|
for(int bit=7;bit>=0;bit--)
|
||||||
|
{
|
||||||
|
uint8 &joystate = js[i];
|
||||||
|
int bitmask = (1<<bit);
|
||||||
|
char mnemonic = mnemonics[bit];
|
||||||
|
//if the bit is set write the mnemonic
|
||||||
|
if(joystate & bitmask)
|
||||||
|
movie_writechar(mnemonic);
|
||||||
|
else //otherwise write a space
|
||||||
|
movie_writechar(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
for(x=0;x<4;x++)
|
//separate the joysticks
|
||||||
{
|
if(i != 3) movie_writechar('|');
|
||||||
if(js[x] != joop[x])
|
|
||||||
{
|
|
||||||
for(y=0;y<8;y++)
|
|
||||||
if((js[x] ^ joop[x]) & (1 << y))
|
|
||||||
DoEncode(x, y, 0);
|
|
||||||
joop[x] = js[x];
|
|
||||||
}
|
|
||||||
else if(framets == ((1<<24)-1)) DoEncode(0,0,1); // Overflow will happen, so do dummy update.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//each frame is on a new line
|
||||||
|
movie_writechar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(current)
|
if(current)
|
||||||
|
@ -977,7 +1045,7 @@ int FCEUMOV_ReadState(FILE* st, uint32 size)
|
||||||
nextd = -1;
|
nextd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if(current > 0 || (!movie_readonly && current < 0)) /* Recording or Playback (!read-only) */
|
// if(current > 0 || (!movie_readonly && current < 0)) /* Recording or Playback (!read-only) */
|
||||||
if(current!=0 && !movie_readonly)
|
if(current!=0 && !movie_readonly)
|
||||||
{
|
{
|
||||||
// copy movie data from savestate
|
// copy movie data from savestate
|
||||||
|
@ -994,7 +1062,7 @@ int FCEUMOV_ReadState(FILE* st, uint32 size)
|
||||||
rerecord_count++;
|
rerecord_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// else if(current < 0) /* Playback (read-only) */
|
// else if(current < 0) /* Playback (read-only) */
|
||||||
else if(current!=0 && movie_readonly)
|
else if(current!=0 && movie_readonly)
|
||||||
{
|
{
|
||||||
if(current > 0) // switch to playback
|
if(current > 0) // switch to playback
|
||||||
|
@ -1109,8 +1177,8 @@ int FCEUI_MovieGetInfo(const char* fname, MOVIE_INFO* info)
|
||||||
fname = (const char*)convertToFCM(fname,buffer);
|
fname = (const char*)convertToFCM(fname,buffer);
|
||||||
strncpy(lastMovieInfoFilename, fname, 512);
|
strncpy(lastMovieInfoFilename, fname, 512);
|
||||||
|
|
||||||
// main get info part of function
|
// main get info part of function
|
||||||
{
|
{
|
||||||
uint32 magic;
|
uint32 magic;
|
||||||
uint32 version;
|
uint32 version;
|
||||||
uint8 _flags[4];
|
uint8 _flags[4];
|
||||||
|
@ -1222,34 +1290,39 @@ int FCEUI_MovieGetInfo(const char* fname, MOVIE_INFO* info)
|
||||||
fseek(fp, 24, SEEK_SET); // offset_to_savestate offset
|
fseek(fp, 24, SEEK_SET); // offset_to_savestate offset
|
||||||
uint32 temp_savestate_offset;
|
uint32 temp_savestate_offset;
|
||||||
read32le(&temp_savestate_offset, fp);
|
read32le(&temp_savestate_offset, fp);
|
||||||
|
if(temp_savestate_offset != 0xFFFFFFFF)
|
||||||
|
{
|
||||||
if(fseek(fp, temp_savestate_offset, SEEK_SET))
|
if(fseek(fp, temp_savestate_offset, SEEK_SET))
|
||||||
{
|
{
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(!FCEUSS_LoadFP(fp,2)) return 0; // 2 -> don't really load, just load to find what's there then load backup
|
|
||||||
|
//don't really load, just load to find what's there then load backup
|
||||||
|
if(!FCEUSS_LoadFP(fp,SSLOADPARAM_DUMMY)) return 0;
|
||||||
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
Backwards compat
|
Backwards compat
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
struct MovieHeader_v1
|
struct MovieHeader_v1
|
||||||
{
|
{
|
||||||
uint32 magic;
|
uint32 magic;
|
||||||
uint32 version=1;
|
uint32 version=1;
|
||||||
uint8 flags[4];
|
uint8 flags[4];
|
||||||
uint32 length_frames;
|
uint32 length_frames;
|
||||||
uint32 rerecord_count;
|
uint32 rerecord_count;
|
||||||
uint32 movie_data_size;
|
uint32 movie_data_size;
|
||||||
uint32 offset_to_savestate;
|
uint32 offset_to_savestate;
|
||||||
uint32 offset_to_movie_data;
|
uint32 offset_to_movie_data;
|
||||||
uint16 metadata_ucs2[]; // ucs-2, ick! sizeof(metadata) = offset_to_savestate - MOVIE_HEADER_SIZE
|
uint16 metadata_ucs2[]; // ucs-2, ick! sizeof(metadata) = offset_to_savestate - MOVIE_HEADER_SIZE
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1335,7 +1408,7 @@ static void FCEUI_LoadMovie_v1(char *fname, int _read_only)
|
||||||
suppressAddPowerCommand=0;
|
suppressAddPowerCommand=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!FCEUSS_LoadFP(fp,1)) return;
|
if(!FCEUSS_LoadFP(fp,SSLOADPARAM_BACKUP)) return;
|
||||||
|
|
||||||
ResetInputTypes();
|
ResetInputTypes();
|
||||||
|
|
||||||
|
@ -1467,7 +1540,7 @@ static int FCEUI_MovieGetInfo_v1(const char* fname, MOVIE_INFO* info)
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(!FCEUSS_LoadFP(fp,2)) return 0; // 2 -> don't really load, just load to find what's there then load backup
|
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);
|
fclose(fp);
|
||||||
|
|
|
@ -311,7 +311,7 @@ void NetplayUpdate(uint8 *joyp)
|
||||||
{
|
{
|
||||||
FILE *fp = FetchFile(FCEU_de32lsb(buf));
|
FILE *fp = FetchFile(FCEU_de32lsb(buf));
|
||||||
if(!fp) return;
|
if(!fp) return;
|
||||||
if(FCEUSS_LoadFP(fp,1))
|
if(FCEUSS_LoadFP(fp,SSLOADPARAM_BACKUP))
|
||||||
{
|
{
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
FCEU_DispMessage("Remote state loaded.");
|
FCEU_DispMessage("Remote state loaded.");
|
||||||
|
|
|
@ -391,9 +391,9 @@ void FCEUSS_Save(char *fname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int FCEUSS_LoadFP(FILE *st, int make_backup)
|
int FCEUSS_LoadFP(FILE *st, ENUM_SSLOADPARAMS params)
|
||||||
{
|
{
|
||||||
if(make_backup==2 && suppress_scan_chunks)
|
if(params==SSLOADPARAM_DUMMY && suppress_scan_chunks)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
int x;
|
int x;
|
||||||
|
@ -401,8 +401,8 @@ int FCEUSS_LoadFP(FILE *st, int make_backup)
|
||||||
int stateversion;
|
int stateversion;
|
||||||
char* fn=0;
|
char* fn=0;
|
||||||
|
|
||||||
/* Make temporary savestate in case something screws up during the load */
|
//Make temporary savestate in case something screws up during the load
|
||||||
if(make_backup==1)
|
if(params == SSLOADPARAM_BACKUP)
|
||||||
{
|
{
|
||||||
fn=FCEU_MakeFName(FCEUMKF_NPTEMP,0,0);
|
fn=FCEU_MakeFName(FCEUMKF_NPTEMP,0,0);
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
@ -423,7 +423,7 @@ int FCEUSS_LoadFP(FILE *st, int make_backup)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(make_backup!=2)
|
if(params!=SSLOADPARAM_DUMMY)
|
||||||
{
|
{
|
||||||
FCEUMOV_PreLoad();
|
FCEUMOV_PreLoad();
|
||||||
}
|
}
|
||||||
|
@ -440,12 +440,12 @@ int FCEUSS_LoadFP(FILE *st, int make_backup)
|
||||||
{
|
{
|
||||||
stateversion=header[3] * 100;
|
stateversion=header[3] * 100;
|
||||||
}
|
}
|
||||||
if(make_backup==2)
|
if(params == SSLOADPARAM_DUMMY)
|
||||||
{
|
{
|
||||||
scan_chunks=1;
|
scan_chunks=1;
|
||||||
}
|
}
|
||||||
x=ReadStateChunks(st,*(uint32*)(header+4));
|
x=ReadStateChunks(st,*(uint32*)(header+4));
|
||||||
if(make_backup==2)
|
if(params == SSLOADPARAM_DUMMY)
|
||||||
{
|
{
|
||||||
scan_chunks=0;
|
scan_chunks=0;
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -467,14 +467,14 @@ int FCEUSS_LoadFP(FILE *st, int make_backup)
|
||||||
|
|
||||||
if(fn)
|
if(fn)
|
||||||
{
|
{
|
||||||
if(!x || make_backup==2) //is make_backup==2 possible?? oh well.
|
if(!x || params == SSLOADPARAM_DUMMY) //is make_backup==2 possible?? oh well.
|
||||||
{
|
{
|
||||||
/* Oops! Load the temporary savestate */
|
/* Oops! Load the temporary savestate */
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
if((fp=fopen(fn,"rb")))
|
if((fp=fopen(fn,"rb")))
|
||||||
{
|
{
|
||||||
FCEUSS_LoadFP(fp,0);
|
FCEUSS_LoadFP(fp,SSLOADPARAM_NOBACKUP);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
unlink(fn);
|
unlink(fn);
|
||||||
|
@ -521,7 +521,7 @@ int FCEUSS_Load(char *fname)
|
||||||
//If in bot mode, don't do a backup when loading.
|
//If in bot mode, don't do a backup when loading.
|
||||||
//Otherwise you eat at the hard disk, since so many
|
//Otherwise you eat at the hard disk, since so many
|
||||||
//states are being loaded.
|
//states are being loaded.
|
||||||
if(FCEUSS_LoadFP(st,FCEU_BotMode()?0:1))
|
if(FCEUSS_LoadFP(st,FCEU_BotMode()?SSLOADPARAM_NOBACKUP:SSLOADPARAM_BACKUP))
|
||||||
{
|
{
|
||||||
if(!fname)
|
if(!fname)
|
||||||
{
|
{
|
||||||
|
|
11
src/state.h
11
src/state.h
|
@ -20,10 +20,17 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
enum ENUM_SSLOADPARAMS
|
||||||
|
{
|
||||||
|
SSLOADPARAM_NOBACKUP,
|
||||||
|
SSLOADPARAM_BACKUP,
|
||||||
|
SSLOADPARAM_DUMMY
|
||||||
|
};
|
||||||
|
|
||||||
void FCEUSS_Save(char *);
|
void FCEUSS_Save(char *);
|
||||||
int FCEUSS_Load(char *);
|
int FCEUSS_Load(char *);
|
||||||
int FCEUSS_SaveFP(FILE *);
|
int FCEUSS_SaveFP(FILE *);
|
||||||
int FCEUSS_LoadFP(FILE *, int);
|
int FCEUSS_LoadFP(FILE *, ENUM_SSLOADPARAMS);
|
||||||
|
|
||||||
extern int CurrentState;
|
extern int CurrentState;
|
||||||
void FCEUSS_CheckStates(void);
|
void FCEUSS_CheckStates(void);
|
||||||
|
@ -34,6 +41,8 @@ typedef struct {
|
||||||
char *desc;
|
char *desc;
|
||||||
} SFORMAT;
|
} SFORMAT;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ResetExState(void (*PreSave)(void),void (*PostSave)(void));
|
void ResetExState(void (*PreSave)(void),void (*PostSave)(void));
|
||||||
void AddExState(void *v, uint32 s, int type, char *desc);
|
void AddExState(void *v, uint32 s, int type, char *desc);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue