phase 1 of new movie system

we can now round trip a text movie format
This commit is contained in:
zeromus 2008-05-23 09:58:38 +00:00
parent 91733a146a
commit 1e539ad681
19 changed files with 1211 additions and 1288 deletions

View File

@ -18,6 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

View File

@ -2,6 +2,7 @@
#define __DRIVER_H_
#include <stdio.h>
#include <string>
#include "types.h"
#include "git.h"
@ -191,18 +192,16 @@ typedef struct
int movie_version; // version of the movie format in the file
uint32 num_frames;
uint32 rerecord_count;
uint8 flags;
bool poweron, reset, pal, nosynchack;
int read_only;
uint32 emu_version_used; // 9813 = 0.98.13
char* metadata; // caller-supplied buffer to store metadata. can be NULL.
int metadata_size; // size of the buffer pointed to by metadata
uint8 md5_of_rom_used[16];
int md5_of_rom_used_present; // v1 movies don't have md5 info available
char* name_of_rom_used; // caller-supplied buffer to store metadata. can be NULL.
int name_of_rom_used_size; // size of the buffer pointer to by name_of_rom_used
MD5DATA md5_of_rom_used;
bool md5_of_rom_used_present; // v1 movies don't have md5 info available
std::string name_of_rom_used;
} MOVIE_INFO;
int FCEUI_SelectMovie(int, int);
void FCEUI_SaveMovie(char *fname, uint8 flags, const char* metadata);
void FCEUI_LoadMovie(char *fname, int read_only, int _stopframe);
void FCEUI_StopMovie(void);

View File

@ -32,6 +32,7 @@
#include "../../types.h"
#include "../../driver.h"
#include "../../utils/xstring.h"
#include "config.h"
static int FReadString(FILE *fp, char *str, int n)
@ -240,77 +241,6 @@ void LoadParse(CFGSTRUCT *cfgst, FILE *fp)
}
static void StringToBytes(std::string& str, void* data, int len)
{
if(str.size()>2 && str[0] == '0' && toupper(str[1]) == 'X')
goto hex;
if(len==1) {
int x = atoi(str.c_str());
*(unsigned char*)data = x;
return;
} else if(len==2) {
int x = atoi(str.c_str());
*(unsigned short*)data = x;
return;
} else if(len==4) {
int x = atoi(str.c_str());
*(unsigned int*)data = x;
return;
}
//else it had better be hex
FCEUD_PrintError("Config error: no hex data found somewhere it is required");
hex:
int amt = len;
int bytesAvailable = str.size()/2;
if(bytesAvailable < amt)
amt = bytesAvailable;
const char* cstr = str.c_str()+2;
for(int i=0;i<amt;i++) {
char a = toupper(cstr[i*2]);
char b = toupper(cstr[i*2+1]);
if(a>='A') a=a-'A'+10;
else a-='0';
if(b>='A') b=b-'A'+10;
else b-='0';
unsigned char val = ((unsigned char)a<<4)|(unsigned char)b;
((unsigned char*)data)[i] = val;
}
}
static std::string BytesToString(void* data, int len)
{
char temp[16];
if(len==1) {
sprintf(temp,"%d",*(unsigned char*)data);
return temp;
} else if(len==2) {
sprintf(temp,"%d",*(unsigned short*)data);
return temp;
} else if(len==4) {
sprintf(temp,"%d",*(unsigned int*)data);
return temp;
}
std::string ret;
ret.resize(len*2+2);
char* str= (char*)ret.c_str();
str[0] = '0';
str[1] = 'x';
str += 2;
for(int i=0;i<len;i++)
{
int a = (((unsigned char*)data)[i]>>4);
int b = (((unsigned char*)data)[i])&15;
if(a>9) a += 'A'-10;
else a += '0';
if(b>9) b += 'A'-10;
else b += '0';
str[i*2] = a;
str[i*2+1] = b;
}
return ret;
}
static void cfg_OldToNew(const CFGSTRUCT *cfgst)
{
int x=0;
@ -364,7 +294,8 @@ void cfg_NewToOld(CFGSTRUCT *cfgst)
if(cfgst[x].len)
{
//binary data
StringToBytes(cfgmap[cfgst[x].name],cfgst[x].ptr,cfgst[x].len);
if(!StringToBytes(cfgmap[cfgst[x].name],cfgst[x].ptr,cfgst[x].len))
FCEUD_PrintError("Config error: error parsing parameter");
}
else
{

View File

@ -14,7 +14,6 @@ static int ReplayDialogStopFrame = 0;
static int movieHackType = 3;
char *md5_asciistr(uint8 digest[16]);
void RefreshThrottleFPS();
static char* GetReplayPath(HWND hwndDlg)
@ -114,21 +113,15 @@ void UpdateReplayDialog(HWND hwndDlg)
if(fn)
{
MOVIE_INFO info;
char metadata[MOVIE_MAX_METADATA];
char rom_name[MAX_PATH];
memset(&info, 0, sizeof(info));
info.metadata = metadata;
info.metadata_size = sizeof(metadata);
info.name_of_rom_used = rom_name;
info.name_of_rom_used_size = sizeof(rom_name);
if(FCEUI_MovieGetInfo(fn, &info))
{
#define MOVIE_FLAG_NOSYNCHACK (1<<4) // set in newer version, used for old movie compatibility
extern int resetDMCacc;
extern int justAutoConverted;
int noNoSyncHack=!(info.flags&MOVIE_FLAG_NOSYNCHACK) && resetDMCacc;
int noNoSyncHack=!(info.nosynchack) && resetDMCacc;
EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT_OFFSET),justAutoConverted || noNoSyncHack);
EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT_FROM),justAutoConverted || noNoSyncHack);
if(justAutoConverted)
@ -206,28 +199,30 @@ void UpdateReplayDialog(HWND hwndDlg)
SetWindowTextA(GetDlgItem(hwndDlg,IDC_LABEL_LENGTH), tmp); // length
sprintf(tmp, "%lu", info.rerecord_count);
SetWindowTextA(GetDlgItem(hwndDlg,IDC_LABEL_UNDOCOUNT), tmp); // rerecord
//SetWindowTextA(GetDlgItem(hwndDlg,IDC_LABEL_UNDOCOUNT), tmp); // rerecord
{
// convert utf8 metadata to windows widechar
WCHAR wszMeta[MOVIE_MAX_METADATA];
if(MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, metadata, -1, wszMeta, MOVIE_MAX_METADATA))
{
if(wszMeta[0])
SetWindowTextW(GetDlgItem(hwndDlg,IDC_LABEL_AUTHORINFO), wszMeta); // metadata
else
SetWindowTextW(GetDlgItem(hwndDlg,IDC_LABEL_AUTHORINFO), L"(this movie has no author info)"); // metadata
}
//// convert utf8 metadata to windows widechar
//WCHAR wszMeta[MOVIE_MAX_METADATA];
//if(MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, metadata, -1, wszMeta, MOVIE_MAX_METADATA))
//{
// if(wszMeta[0])
// SetWindowTextW(GetDlgItem(hwndDlg,IDC_LABEL_AUTHORINFO), wszMeta); // metadata
// else
// SetWindowTextW(GetDlgItem(hwndDlg,IDC_LABEL_AUTHORINFO), L"(this movie has no author info)"); // metadata
//}
SetDlgItemTextW(hwndDlg,IDC_LABEL_AUTHORINFO,L"Temporarily non-functional");
}
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);
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_RECORDEDFROM),(info.flags & MOVIE_FLAG_FROM_POWERON) ? "Power-On" : "Savestate");
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_RECORDEDFROM),info.poweron ? "Power-On" : (info.reset?"Soft-Reset":"Savestate"));
if(info.movie_version > 1)
{
char emuStr[128];
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_ROMUSED),info.name_of_rom_used);
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_ROMUSED),info.name_of_rom_used.c_str());
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_ROMCHECKSUM),md5_asciistr(info.md5_of_rom_used));
if(info.emu_version_used > 64)
sprintf(emuStr, "FCEU %d.%02d.%02d%s", info.emu_version_used/10000, (info.emu_version_used/100)%100, (info.emu_version_used)%100, info.emu_version_used < 9813 ? " (blip)" : "");
@ -283,7 +278,7 @@ void UpdateReplayDialog(HWND hwndDlg)
{
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_LENGTH),"");
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_FRAMES),"");
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_UNDOCOUNT),"");
//SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_UNDOCOUNT),"");
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_AUTHORINFO),"");
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_ROMUSED),"");
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_ROMCHECKSUM),"");
@ -410,10 +405,6 @@ BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
char rom_name[MAX_PATH];
memset(&info, 0, sizeof(info));
info.metadata = metadata;
info.metadata_size = sizeof(metadata);
info.name_of_rom_used = rom_name;
info.name_of_rom_used_size = sizeof(rom_name);
char filename [512];
sprintf(filename, "%s%s", globBase, wfd.cFileName);
@ -836,7 +827,7 @@ static BOOL CALLBACK RecordDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LP
void FCEUD_MovieRecordTo()
{
struct CreateMovieParameters p;
p.szFilename = FCEUI_MovieGetCurrentName(0);
p.szFilename = FCEU_MakeFName(FCEUMKF_MOVIE,0,0);
if(DialogBoxParam(fceu_hInstance, "IDD_RECORDINP", hAppWnd, RecordDialogProc, (LPARAM)&p))
{

Binary file not shown.

View File

@ -18,6 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
@ -374,7 +375,6 @@ FCEUGI *FCEUI_LoadGame(const char *name, int OverwriteVidMode)
PowerNES();
FCEUSS_CheckStates();
FCEUMOV_CheckMovies();
if(GameInfo->type!=GIT_NSF)
{

View File

@ -615,10 +615,6 @@ void FCEUI_SetDirOverride(int which, char *n)
{
FCEUSS_CheckStates();
}
else if(which == FCEUIOD_MISC)
{
FCEUMOV_CheckMovies();
}
}
}

View File

@ -10,6 +10,8 @@
#define GIV_PAL 1 /* PAL emulation. */
#define GIV_USER 2 /* What was set by FCEUI_SetVidSys(). */
#include "utils/md5.h"
typedef struct {
uint8 *name; /* Game name, UTF8 encoding */
@ -22,7 +24,7 @@ typedef struct {
int cspecial; /* Special cart expansion: DIP switches, barcode
reader, etc.
*/
uint8 MD5[16];
MD5DATA MD5;
int soundrate; /* For Ogg Vorbis expansion sound wacky support. 0 for default. */
int soundchan; /* Number of sound channels. */
} FCEUGI;

View File

@ -18,6 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string>
#include <string.h>
#include "types.h"
@ -749,42 +751,16 @@ static void CommandStateLoad(void)
FCEUI_LoadState(0);
}
void FCEUI_SelectMovieNext(int);
/*
static void CommandMovieSelectSlot(void)
{
if(execcmd <= EMUCMD_MOVIE_SLOT_9)
FCEUI_SelectMovie(execcmd-EMUCMD_MOVIE_SLOT_0, 1);
else if(execcmd == EMUCMD_MOVIE_SLOT_NEXT)
FCEUI_SelectMovieNext(1);
else if(execcmd == EMUCMD_MOVIE_SLOT_PREV)
FCEUI_SelectMovieNext(-1);
}
static void CommandMovieRecord(void)
{
if(execcmd >= EMUCMD_MOVIE_RECORD_SLOT_0 && execcmd <= EMUCMD_MOVIE_RECORD_SLOT_9)
{
int oldslot=FCEUI_SelectMovie(execcmd-EMUCMD_MOVIE_RECORD_SLOT_0, 0);
FCEUI_SaveMovie(0, 0, 0);
FCEUI_SelectMovie(oldslot, 0);
}
else
FCEUI_SaveMovie(0, 0, 0);
}
static void CommandMovieReplay(void)
{
if(execcmd >= EMUCMD_MOVIE_REPLAY_SLOT_0 && execcmd <= EMUCMD_MOVIE_REPLAY_SLOT_9)
{
int oldslot=FCEUI_SelectMovie(execcmd-EMUCMD_MOVIE_REPLAY_SLOT_0, 0);
FCEUI_LoadMovie(0, 0);
FCEUI_SelectMovie(oldslot, 0);
FCEUI_LoadMovie(0, 0, 0);
}
else
FCEUI_LoadMovie(0, 0);
}
*/
static void CommandSoundAdjust(void)
{
int n;

File diff suppressed because it is too large Load Diff

View File

@ -2,12 +2,11 @@
#define __MOVIE_H_
void FCEUMOV_AddJoy(uint8 *, int SkipFlush);
void FCEUMOV_CheckMovies(void);
void FCEUMOV_AddCommand(int cmd);
void FCEU_DrawMovies(uint8 *);
int FCEUMOV_IsPlaying(void);
int FCEUMOV_IsRecording(void);
int FCEUMOV_ShouldPause(void);
bool FCEUMOV_ShouldPause(void);
int FCEUMOV_GetFrame(void);
int FCEUMOV_WriteState(FILE* st);

View File

@ -21,6 +21,7 @@
/* TODO: Add (better) file io error checking */
/* TODO: Change save state file format. */
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -490,11 +491,12 @@ int FCEUSS_Load(char *fname)
FILE *st;
char *fn;
//this fixes read-only toggle problems
if(FCEUMOV_IsRecording()) {
FCEUMOV_AddCommand(0);
MovieFlushHeader();
}
//mbg movie - this needs to be overhauled
////this fixes read-only toggle problems
//if(FCEUMOV_IsRecording()) {
// FCEUMOV_AddCommand(0);
// MovieFlushHeader();
//}
if(geniestage==1)
{
@ -621,7 +623,6 @@ int FCEUI_SelectState(int w, int show)
{
int oldstate=CurrentState;
if(w == -1) { StateShow = 0; return 0; } //mbg merge 7/17/06 had to make return a value
FCEUI_SelectMovie(-1,0);
CurrentState=w;
if(show)

View File

@ -24,7 +24,7 @@
#include <stdlib.h>
#define FCEU_VERSION_NUMERIC 9816
#define FCEU_VERSION_NUMERIC 19901
#define FCEU_NAME "FCE Ultra"
#define FCEU_VERSION_STRING "1.9.9"
#define FCEU_NAME_AND_VERSION FCEU_NAME " " FCEU_VERSION_STRING
@ -54,6 +54,7 @@ typedef signed int int32;
#define mkdir _mkdir
#define alloca _alloca
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#define W_OK 2
#define R_OK 2
#define X_OK 1

View File

@ -228,8 +228,9 @@ void md5_finish( struct md5_context *ctx, uint8 digest[16] )
/* Uses a static buffer, so beware of how it's used. */
char *md5_asciistr(uint8 digest[16])
char *md5_asciistr(MD5DATA& md5)
{
uint8* digest = md5.data;
static char str[33];
static char trans[16]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
int x;

View File

@ -8,11 +8,22 @@ struct md5_context
uint8 buffer[64];
};
template<typename T, int N>
struct ValueArray
{
T data[N];
T &operator[](int index) { return data[index]; }
static const int size = N;
};
typedef ValueArray<uint8,16> MD5DATA;
void md5_starts( struct md5_context *ctx );
void md5_update( struct md5_context *ctx, uint8 *input, uint32 length );
void md5_finish( struct md5_context *ctx, uint8 digest[16] );
/* Uses a static buffer, so beware of how it's used. */
char *md5_asciistr(uint8 digest[16]);
char *md5_asciistr(MD5DATA& md5);
#endif /* md5.h */

View File

@ -22,6 +22,7 @@
/// \brief various string manipulation utilities
#include "xstring.h"
#include <string>
///Upper case routine. Returns number of characters modified
int str_ucase(char *str) {
@ -189,3 +190,122 @@ int str_replace(char *str, char *search, char *replace) {
free(astr);
return j;
}
///Converts the provided data to a string in a standard, user-friendly, round-trippable format
std::string BytesToString(void* data, int len)
{
char temp[16];
if(len==1) {
sprintf(temp,"%d",*(unsigned char*)data);
return temp;
} else if(len==2) {
sprintf(temp,"%d",*(unsigned short*)data);
return temp;
} else if(len==4) {
sprintf(temp,"%d",*(unsigned int*)data);
return temp;
}
std::string ret;
ret.resize(len*2+2);
char* str= (char*)ret.c_str();
str[0] = '0';
str[1] = 'x';
str += 2;
for(int i=0;i<len;i++)
{
int a = (((unsigned char*)data)[i]>>4);
int b = (((unsigned char*)data)[i])&15;
if(a>9) a += 'A'-10;
else a += '0';
if(b>9) b += 'A'-10;
else b += '0';
str[i*2] = a;
str[i*2+1] = b;
}
return ret;
}
///returns -1 if this is not a hex string
int HexStringToBytesLength(std::string& str)
{
if(str.size()>2 && str[0] == '0' && toupper(str[1]) == 'X')
return str.size()/2-1;
else return -1;
}
///parses a string in the same format as BytesToString
///returns true if success.
bool StringToBytes(std::string& str, void* data, int len)
{
if(str.size()>2 && str[0] == '0' && toupper(str[1]) == 'X')
goto hex;
if(len==1) {
int x = atoi(str.c_str());
*(unsigned char*)data = x;
return true;
} else if(len==2) {
int x = atoi(str.c_str());
*(unsigned short*)data = x;
return true;
} else if(len==4) {
int x = atoi(str.c_str());
*(unsigned int*)data = x;
return true;
}
//we can't handle it
return false;
hex:
int amt = len;
int bytesAvailable = str.size()/2;
if(bytesAvailable < amt)
amt = bytesAvailable;
const char* cstr = str.c_str()+2;
for(int i=0;i<amt;i++) {
char a = toupper(cstr[i*2]);
char b = toupper(cstr[i*2+1]);
if(a>='A') a=a-'A'+10;
else a-='0';
if(b>='A') b=b-'A'+10;
else b-='0';
unsigned char val = ((unsigned char)a<<4)|(unsigned char)b;
((unsigned char*)data)[i] = val;
}
return true;
}
#include <string>
#include <vector>
/// \brief convert input string into vector of string tokens
///
/// \note consecutive delimiters will be treated as single delimiter
/// \note delimiters are _not_ included in return data
///
/// \param input string to be parsed
/// \param delims list of delimiters.
std::vector<std::string> tokenize_str(const std::string & str,
const std::string & delims=", \t")
{
using namespace std;
// Skip delims at beginning, find start of first token
string::size_type lastPos = str.find_first_not_of(delims, 0);
// Find next delimiter @ end of token
string::size_type pos = str.find_first_of(delims, lastPos);
// output vector
vector<string> tokens;
while (string::npos != pos || string::npos != lastPos)
{
// Found a token, add it to the vector.
tokens.push_back(str.substr(lastPos, pos - lastPos));
// Skip delims. Note the "not_of". this is beginning of token
lastPos = str.find_first_not_of(delims, pos);
// Find next delimiter at end of token.
pos = str.find_first_of(delims, lastPos);
}
return tokens;
}

View File

@ -17,9 +17,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string>
#include <string.h>
#include <stdlib.h>
#include <vector>
//definitions for str_strip() flags
#define STRIP_SP 0x01 /* space */
@ -35,3 +37,9 @@ int str_rtrim(char *str, int flags);
int str_strip(char *str, int flags);
int chr_replace(char *str, char search, char replace);
int str_replace(char *str, char *search, char *replace);
int HexStringToBytesLength(std::string& str);
std::string BytesToString(void* data, int len);
bool StringToBytes(std::string& str, void* data, int len);
std::vector<std::string> tokenize_str(const std::string & str,const std::string & delims);

View File

@ -342,8 +342,9 @@ void FCEU_DispMessage(char *format, ...)
howlong=180;
extern int movcounter;
movcounter=0;
//mbg movie 5/23/08
//extern int movcounter;
//movcounter=0;
}
void FCEU_ResetMessages(void)

View File

@ -748,6 +748,7 @@
>
<Tool
Name="VCCLCompilerTool"
GeneratePreprocessedFile="0"
ObjectFile="$(IntDir)\$(InputName)2.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
/>
@ -2170,6 +2171,14 @@
<File
RelativePath="..\src\cheat.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
GeneratePreprocessedFile="0"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\src\conddebug.cpp"