first attempt - support loading movies from archives.
This commit is contained in:
parent
9d0e6ecb9e
commit
3a0b893662
|
@ -451,7 +451,7 @@ ArchiveScanRecord FCEUD_ScanArchive(std::string fname)
|
||||||
|
|
||||||
extern HWND hAppWnd;
|
extern HWND hAppWnd;
|
||||||
|
|
||||||
FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::string* innerFilename)
|
FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::string* innerFilename, int innerIndex)
|
||||||
{
|
{
|
||||||
FCEUFILE* fp = 0;
|
FCEUFILE* fp = 0;
|
||||||
|
|
||||||
|
@ -530,10 +530,10 @@ FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::str
|
||||||
|
|
||||||
//try to load the file directly if we're in autopilot
|
//try to load the file directly if we're in autopilot
|
||||||
int ret = LB_ERR;
|
int ret = LB_ERR;
|
||||||
if(innerFilename)
|
if(innerFilename || innerIndex != -1)
|
||||||
{
|
{
|
||||||
for(uint32 i=0;i<fileSelectorContext.items.size();i++)
|
for(uint32 i=0;i<fileSelectorContext.items.size();i++)
|
||||||
if(fileSelectorContext.items[i].name == *innerFilename)
|
if(i == (uint32)innerIndex || (innerFilename && fileSelectorContext.items[i].name == *innerFilename))
|
||||||
{
|
{
|
||||||
ret = i;
|
ret = i;
|
||||||
break;
|
break;
|
||||||
|
@ -559,6 +559,7 @@ FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::str
|
||||||
fp = new FCEUFILE();
|
fp = new FCEUFILE();
|
||||||
fp->archiveFilename = fname;
|
fp->archiveFilename = fname;
|
||||||
fp->filename = fileSelectorContext.items[ret].name;
|
fp->filename = fileSelectorContext.items[ret].name;
|
||||||
|
fp->fullFilename = fp->archiveFilename + "|" + fp->filename;
|
||||||
fp->archiveIndex = ret;
|
fp->archiveIndex = ret;
|
||||||
fp->mode = FCEUFILE::READ;
|
fp->mode = FCEUFILE::READ;
|
||||||
fp->size = fileSelectorContext.items[ret].size;
|
fp->size = fileSelectorContext.items[ret].size;
|
||||||
|
@ -580,3 +581,13 @@ FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::str
|
||||||
|
|
||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FCEUFILE* FCEUD_OpenArchiveIndex(ArchiveScanRecord& asr, std::string& fname, int innerIndex)
|
||||||
|
{
|
||||||
|
return FCEUD_OpenArchive(asr, fname, 0, innerIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::string* innerFilename)
|
||||||
|
{
|
||||||
|
return FCEUD_OpenArchive(asr, fname, innerFilename, -1);
|
||||||
|
}
|
|
@ -12,6 +12,8 @@ void initArchiveSystem();
|
||||||
//if you want to autopilot this, pass in an innerfilename to try and automatically load
|
//if you want to autopilot this, pass in an innerfilename to try and automatically load
|
||||||
FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::string* innerFilename);
|
FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::string* innerFilename);
|
||||||
|
|
||||||
|
FCEUFILE* FCEUD_OpenArchiveIndex(ArchiveScanRecord& asr, std::string& fname, int innerIndex);
|
||||||
|
|
||||||
//scans a file to see if it is an archive you can handle
|
//scans a file to see if it is an archive you can handle
|
||||||
ArchiveScanRecord FCEUD_ScanArchive(std::string fname);
|
ArchiveScanRecord FCEUD_ScanArchive(std::string fname);
|
||||||
|
|
||||||
|
|
|
@ -644,7 +644,11 @@ int main(int argc,char *argv[])
|
||||||
|
|
||||||
if(GameInfo && MovieToLoad)
|
if(GameInfo && MovieToLoad)
|
||||||
{
|
{
|
||||||
FCEUI_LoadMovie(MovieToLoad, replayReadOnlySetting!=0, false, replayStopFrameSetting!=0);
|
//switch to readonly mode if the file is an archive
|
||||||
|
if(FCEU_isFileInArchive(MovieToLoad))
|
||||||
|
replayReadOnlySetting = true;
|
||||||
|
|
||||||
|
FCEUI_LoadMovie(MovieToLoad, replayReadOnlySetting, false, replayStopFrameSetting!=0);
|
||||||
free(MovieToLoad);
|
free(MovieToLoad);
|
||||||
MovieToLoad = NULL;
|
MovieToLoad = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "movie.h"
|
#include "movie.h"
|
||||||
|
#include "archive.h"
|
||||||
|
|
||||||
// Used when deciding to automatically make the stop movie checkbox checked
|
// Used when deciding to automatically make the stop movie checkbox checked
|
||||||
static bool stopframeWasEditedByUser = false;
|
static bool stopframeWasEditedByUser = false;
|
||||||
|
@ -115,7 +116,11 @@ void UpdateReplayDialog(HWND hwndDlg)
|
||||||
{
|
{
|
||||||
MOVIE_INFO info;
|
MOVIE_INFO info;
|
||||||
|
|
||||||
if(FCEUI_MovieGetInfo(fn, &info, false))
|
FCEUFILE* fp = FCEU_fopen(fn,0,"rb",0);
|
||||||
|
bool isarchive = FCEU_isFileInArchive(fn);
|
||||||
|
bool ismovie = FCEUI_MovieGetInfo(fp, &info, false);
|
||||||
|
delete fp;
|
||||||
|
if(ismovie)
|
||||||
{
|
{
|
||||||
char tmp[256];
|
char tmp[256];
|
||||||
uint32 div;
|
uint32 div;
|
||||||
|
@ -139,6 +144,12 @@ void UpdateReplayDialog(HWND hwndDlg)
|
||||||
|
|
||||||
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_RECORDEDFROM),info.poweron ? "Power-On" : (info.reset?"Soft-Reset":"Savestate"));
|
SetWindowText(GetDlgItem(hwndDlg,IDC_LABEL_RECORDEDFROM),info.poweron ? "Power-On" : (info.reset?"Soft-Reset":"Savestate"));
|
||||||
|
|
||||||
|
if(isarchive) {
|
||||||
|
EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK_READONLY),FALSE);
|
||||||
|
Button_SetCheck(GetDlgItem(hwndDlg,IDC_CHECK_READONLY),BST_CHECKED);
|
||||||
|
} else
|
||||||
|
EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK_READONLY),TRUE);
|
||||||
|
|
||||||
//-----------
|
//-----------
|
||||||
//mbg 5/26/08 - getting rid of old movie formats
|
//mbg 5/26/08 - getting rid of old movie formats
|
||||||
|
|
||||||
|
@ -321,6 +332,54 @@ BOOL CALLBACK ReplayMetadataDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, L
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern char FileBase[];
|
||||||
|
|
||||||
|
void HandleScan(HWND hwndDlg, FCEUFILE* file, int& i)
|
||||||
|
{
|
||||||
|
MOVIE_INFO info;
|
||||||
|
|
||||||
|
bool scanok = FCEUI_MovieGetInfo(file, &info, true);
|
||||||
|
if(!scanok)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//------------
|
||||||
|
//attempt to match the movie with the rom
|
||||||
|
//first, try matching md5
|
||||||
|
//then try matching base name
|
||||||
|
char md51 [256];
|
||||||
|
char md52 [256];
|
||||||
|
strcpy(md51, md5_asciistr(GameInfo->MD5));
|
||||||
|
strcpy(md52, md5_asciistr(info.md5_of_rom_used));
|
||||||
|
if(strcmp(md51, md52))
|
||||||
|
{
|
||||||
|
unsigned int k, count1=0, count2=0; //mbg merge 7/17/06 changed to uint
|
||||||
|
for(k=0;k<strlen(md51);k++) count1 += md51[k]-'0';
|
||||||
|
for(k=0;k<strlen(md52);k++) count2 += md52[k]-'0';
|
||||||
|
if(count1 && count2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char* tlen1=strstr(file->filename.c_str(), " (");
|
||||||
|
const char* tlen2=strstr(FileBase, " (");
|
||||||
|
int tlen3=tlen1?(int)(tlen1-file->filename.c_str()):file->filename.size();
|
||||||
|
int tlen4=tlen2?(int)(tlen2-FileBase):strlen(FileBase);
|
||||||
|
int len=MAX(0,MIN(tlen3,tlen4));
|
||||||
|
if(strnicmp(file->filename.c_str(), FileBase, len))
|
||||||
|
{
|
||||||
|
char temp[512];
|
||||||
|
strcpy(temp,FileBase);
|
||||||
|
temp[len]='\0';
|
||||||
|
if(!strstr(file->filename.c_str(), temp))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//-------------
|
||||||
|
//if we get here, then we had a match
|
||||||
|
|
||||||
|
char relative[MAX_PATH];
|
||||||
|
AbsoluteToRelative(relative, file->fullFilename.c_str(), BaseDirectory.c_str());
|
||||||
|
SendDlgItemMessage(hwndDlg, IDC_COMBO_FILENAME, CB_INSERTSTRING, i++, (LPARAM)relative);
|
||||||
|
}
|
||||||
|
|
||||||
BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
switch(uMsg)
|
switch(uMsg)
|
||||||
|
@ -345,9 +404,9 @@ BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
||||||
char* findGlob[2] = {strdup(FCEU_MakeFName(FCEUMKF_MOVIEGLOB, 0, 0).c_str()),
|
char* findGlob[2] = {strdup(FCEU_MakeFName(FCEUMKF_MOVIEGLOB, 0, 0).c_str()),
|
||||||
strdup(FCEU_MakeFName(FCEUMKF_MOVIEGLOB2, 0, 0).c_str())};
|
strdup(FCEU_MakeFName(FCEUMKF_MOVIEGLOB2, 0, 0).c_str())};
|
||||||
|
|
||||||
int i=0, j=0;
|
int items=0;
|
||||||
|
|
||||||
for(j=0;j<2;j++)
|
for(int j=0;j<2;j++)
|
||||||
{
|
{
|
||||||
char* temp=0;
|
char* temp=0;
|
||||||
do {
|
do {
|
||||||
|
@ -364,7 +423,7 @@ BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
||||||
// FCEU_PrintError(findGlob[0]);
|
// FCEU_PrintError(findGlob[0]);
|
||||||
// FCEU_PrintError(findGlob[1]);
|
// FCEU_PrintError(findGlob[1]);
|
||||||
|
|
||||||
for(j=0;j<2;j++)
|
for(int j=0;j<2;j++)
|
||||||
{
|
{
|
||||||
// if the two directories are the same, only look through one of them to avoid adding everything twice
|
// if the two directories are the same, only look through one of them to avoid adding everything twice
|
||||||
if(j==1 && !strnicmp(findGlob[0],findGlob[1],MAX(strlen(findGlob[0]),strlen(findGlob[1]))-6))
|
if(j==1 && !strnicmp(findGlob[0],findGlob[1],MAX(strlen(findGlob[0]),strlen(findGlob[1]))-6))
|
||||||
|
@ -374,7 +433,6 @@ BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
||||||
strcpy(globBase,findGlob[j]);
|
strcpy(globBase,findGlob[j]);
|
||||||
globBase[strlen(globBase)-5]='\0';
|
globBase[strlen(globBase)-5]='\0';
|
||||||
|
|
||||||
extern char FileBase[];
|
|
||||||
//char szFindPath[512]; //mbg merge 7/17/06 removed
|
//char szFindPath[512]; //mbg merge 7/17/06 removed
|
||||||
WIN32_FIND_DATA wfd;
|
WIN32_FIND_DATA wfd;
|
||||||
HANDLE hFind;
|
HANDLE hFind;
|
||||||
|
@ -388,7 +446,7 @@ BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
||||||
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// filter out everything that's not *.fm2
|
// filter out everything that's not an extension we like *.fm2
|
||||||
// (because FindFirstFile is too dumb to do that)
|
// (because FindFirstFile is too dumb to do that)
|
||||||
{
|
{
|
||||||
char* dot=strrchr(wfd.cFileName,'.');
|
char* dot=strrchr(wfd.cFileName,'.');
|
||||||
|
@ -399,56 +457,36 @@ BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
||||||
int k, extlen=strlen(ext);
|
int k, extlen=strlen(ext);
|
||||||
for(k=0;k<extlen;k++)
|
for(k=0;k<extlen;k++)
|
||||||
ext[k]=tolower(ext[k]);
|
ext[k]=tolower(ext[k]);
|
||||||
if(strcmp(ext,"fm2"))
|
if(stricmp(ext,"fm2"))
|
||||||
continue;
|
if(stricmp(ext,"zip"))
|
||||||
|
if(stricmp(ext,"rar"))
|
||||||
|
if(stricmp(ext,"7z"))
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOVIE_INFO info;
|
|
||||||
|
|
||||||
char filename [512];
|
char filename [512];
|
||||||
sprintf(filename, "%s%s", globBase, wfd.cFileName);
|
sprintf(filename, "%s%s", globBase, wfd.cFileName);
|
||||||
|
|
||||||
char* dot = strrchr(filename, '.');
|
char* dot = strrchr(filename, '.');
|
||||||
|
|
||||||
if(!FCEUI_MovieGetInfo(filename, &info, true))
|
ArchiveScanRecord asr = FCEUD_ScanArchive(filename);
|
||||||
continue;
|
if(asr.numFiles>1) {
|
||||||
|
for(int i=0;i<asr.numFiles;i++) {
|
||||||
//------------
|
FCEUFILE* fp = FCEU_fopen(filename,0,"rb",0,i);
|
||||||
//attempt to match the movie with the rom
|
if(fp) {
|
||||||
//first, try matching md5
|
HandleScan(hwndDlg,fp, items);
|
||||||
//then try matching base name
|
delete fp;
|
||||||
char md51 [256];
|
}
|
||||||
char md52 [256];
|
}
|
||||||
strcpy(md51, md5_asciistr(GameInfo->MD5));
|
} else
|
||||||
strcpy(md52, md5_asciistr(info.md5_of_rom_used));
|
|
||||||
if(strcmp(md51, md52))
|
|
||||||
{
|
{
|
||||||
unsigned int k, count1=0, count2=0; //mbg merge 7/17/06 changed to uint
|
FCEUFILE* fp = FCEU_fopen(filename,0,"rb",0);
|
||||||
for(k=0;k<strlen(md51);k++) count1 += md51[k]-'0';
|
if(fp) {
|
||||||
for(k=0;k<strlen(md52);k++) count2 += md52[k]-'0';
|
HandleScan(hwndDlg,fp ,items);
|
||||||
if(count1 && count2)
|
delete fp;
|
||||||
continue;
|
|
||||||
|
|
||||||
char* tlen1=strstr(wfd.cFileName, " (");
|
|
||||||
char* tlen2=strstr(FileBase, " (");
|
|
||||||
int tlen3=tlen1?(int)(tlen1-wfd.cFileName):strlen(wfd.cFileName);
|
|
||||||
int tlen4=tlen2?(int)(tlen2-FileBase):strlen(FileBase);
|
|
||||||
int len=MAX(0,MIN(tlen3,tlen4));
|
|
||||||
if(strnicmp(wfd.cFileName, FileBase, len))
|
|
||||||
{
|
|
||||||
char temp[512];
|
|
||||||
strcpy(temp,FileBase);
|
|
||||||
temp[len]='\0';
|
|
||||||
if(!strstr(wfd.cFileName, temp))
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//-------------
|
|
||||||
//if we get here, then we had a match
|
|
||||||
|
|
||||||
char relative[MAX_PATH];
|
|
||||||
AbsoluteToRelative(relative, filename, BaseDirectory.c_str());
|
|
||||||
SendDlgItemMessage(hwndDlg, IDC_COMBO_FILENAME, CB_INSERTSTRING, i++, (LPARAM)relative);
|
|
||||||
} while(FindNextFile(hFind, &wfd));
|
} while(FindNextFile(hFind, &wfd));
|
||||||
FindClose(hFind);
|
FindClose(hFind);
|
||||||
}
|
}
|
||||||
|
@ -457,9 +495,9 @@ BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
||||||
free(findGlob[0]);
|
free(findGlob[0]);
|
||||||
free(findGlob[1]);
|
free(findGlob[1]);
|
||||||
|
|
||||||
if(i>0)
|
if(items>0)
|
||||||
SendDlgItemMessage(hwndDlg, IDC_COMBO_FILENAME, CB_SETCURSEL, i-1, 0);
|
SendDlgItemMessage(hwndDlg, IDC_COMBO_FILENAME, CB_SETCURSEL, items-1, 0);
|
||||||
SendDlgItemMessage(hwndDlg, IDC_COMBO_FILENAME, CB_INSERTSTRING, i++, (LPARAM)"Browse...");
|
SendDlgItemMessage(hwndDlg, IDC_COMBO_FILENAME, CB_INSERTSTRING, items++, (LPARAM)"Browse...");
|
||||||
|
|
||||||
UpdateReplayDialog(hwndDlg);
|
UpdateReplayDialog(hwndDlg);
|
||||||
}
|
}
|
||||||
|
@ -520,7 +558,7 @@ BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
||||||
memset(&ofn, 0, sizeof(ofn));
|
memset(&ofn, 0, sizeof(ofn));
|
||||||
ofn.lStructSize = sizeof(ofn);
|
ofn.lStructSize = sizeof(ofn);
|
||||||
ofn.hwndOwner = hwndDlg;
|
ofn.hwndOwner = hwndDlg;
|
||||||
ofn.lpstrFilter = "FCEUX Movie Files (*.fm2)\0*.fm2\0All files(*.*)\0*.*\0\0";
|
ofn.lpstrFilter = "FCEUX Movie Files (*.fm2)\0*.fm2\0Archive files(*.zip,*.rar,*.7z)\0*.zip;*.rar;*.7z\0All files(*.*)\0*.*\0\0";
|
||||||
ofn.lpstrFile = szFile;
|
ofn.lpstrFile = szFile;
|
||||||
ofn.nMaxFile = sizeof(szFile);
|
ofn.nMaxFile = sizeof(szFile);
|
||||||
ofn.lpstrInitialDir = pn;
|
ofn.lpstrInitialDir = pn;
|
||||||
|
@ -530,9 +568,17 @@ BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
||||||
|
|
||||||
if(GetOpenFileName(&ofn))
|
if(GetOpenFileName(&ofn))
|
||||||
{
|
{
|
||||||
char relative[MAX_PATH];
|
char relative[MAX_PATH*2];
|
||||||
AbsoluteToRelative(relative, szFile, BaseDirectory.c_str());
|
AbsoluteToRelative(relative, szFile, BaseDirectory.c_str());
|
||||||
|
|
||||||
|
ArchiveScanRecord asr = FCEUD_ScanArchive(relative);
|
||||||
|
FCEUFILE* fp = FCEU_fopen(relative,0,"rb",0);
|
||||||
|
if(!fp) {
|
||||||
|
delete fp;
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
|
strcpy(relative,fp->fullFilename.c_str());
|
||||||
|
|
||||||
LONG lOtherIndex = SendDlgItemMessage(hwndDlg, IDC_COMBO_FILENAME, CB_FINDSTRING, (WPARAM)-1, (LPARAM)relative);
|
LONG lOtherIndex = SendDlgItemMessage(hwndDlg, IDC_COMBO_FILENAME, CB_FINDSTRING, (WPARAM)-1, (LPARAM)relative);
|
||||||
if(lOtherIndex != CB_ERR)
|
if(lOtherIndex != CB_ERR)
|
||||||
{
|
{
|
||||||
|
@ -547,6 +593,7 @@ BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
||||||
SetFocus(GetDlgItem(hwndDlg, IDC_COMBO_FILENAME));
|
SetFocus(GetDlgItem(hwndDlg, IDC_COMBO_FILENAME));
|
||||||
UpdateReplayDialog(hwndDlg);
|
UpdateReplayDialog(hwndDlg);
|
||||||
}
|
}
|
||||||
|
abort:
|
||||||
|
|
||||||
free(pn);
|
free(pn);
|
||||||
}
|
}
|
||||||
|
|
23
src/file.cpp
23
src/file.cpp
|
@ -230,7 +230,7 @@ void FCEU_SplitArchiveFilename(std::string src, std::string& archive, std::strin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext)
|
FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext, int index)
|
||||||
{
|
{
|
||||||
FILE *ipsfile=0;
|
FILE *ipsfile=0;
|
||||||
FCEUFILE *fceufp=0;
|
FCEUFILE *fceufp=0;
|
||||||
|
@ -264,6 +264,7 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext
|
||||||
}
|
}
|
||||||
fceufp = new FCEUFILE();
|
fceufp = new FCEUFILE();
|
||||||
fceufp->filename = fileToOpen;
|
fceufp->filename = fileToOpen;
|
||||||
|
fceufp->fullFilename = fileToOpen;
|
||||||
fceufp->archiveIndex = -1;
|
fceufp->archiveIndex = -1;
|
||||||
fceufp->stream = (std::iostream*)fp;
|
fceufp->stream = (std::iostream*)fp;
|
||||||
FCEU_fseek(fceufp,0,SEEK_END);
|
FCEU_fseek(fceufp,0,SEEK_END);
|
||||||
|
@ -275,7 +276,10 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext
|
||||||
{
|
{
|
||||||
//open an archive file
|
//open an archive file
|
||||||
if(archive == "")
|
if(archive == "")
|
||||||
fceufp = FCEUD_OpenArchive(asr, fileToOpen, 0);
|
if(index != -1)
|
||||||
|
fceufp = FCEUD_OpenArchiveIndex(asr, fileToOpen, index);
|
||||||
|
else
|
||||||
|
fceufp = FCEUD_OpenArchive(asr, fileToOpen, 0);
|
||||||
else
|
else
|
||||||
fceufp = FCEUD_OpenArchive(asr, archive, &fname);
|
fceufp = FCEUD_OpenArchive(asr, archive, &fname);
|
||||||
return fceufp;
|
return fceufp;
|
||||||
|
@ -289,6 +293,7 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext
|
||||||
}
|
}
|
||||||
fceufp = new FCEUFILE();
|
fceufp = new FCEUFILE();
|
||||||
fceufp->filename = fileToOpen;
|
fceufp->filename = fileToOpen;
|
||||||
|
fceufp->filename = fileToOpen;
|
||||||
fceufp->archiveIndex = -1;
|
fceufp->archiveIndex = -1;
|
||||||
fceufp->stream = (std::iostream*)fp;
|
fceufp->stream = (std::iostream*)fp;
|
||||||
FCEU_fseek(fceufp,0,SEEK_END);
|
FCEU_fseek(fceufp,0,SEEK_END);
|
||||||
|
@ -642,7 +647,8 @@ std::string FCEU_MakeFName(int type, int id1, char *cd1)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
//convert | to . for archive filenames.
|
||||||
|
return mass_replace(ret,"|",".");
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetFileBase(const char *f)
|
void GetFileBase(const char *f)
|
||||||
|
@ -684,3 +690,14 @@ void GetFileBase(const char *f)
|
||||||
FileExt[0]=0;
|
FileExt[0]=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FCEU_isFileInArchive(const char *path)
|
||||||
|
{
|
||||||
|
bool isarchive = false;
|
||||||
|
FCEUFILE* fp = FCEU_fopen(path,0,"rb",0,0);
|
||||||
|
if(fp) {
|
||||||
|
isarchive = fp->isArchive();
|
||||||
|
delete fp;
|
||||||
|
}
|
||||||
|
return isarchive;
|
||||||
|
}
|
14
src/file.h
14
src/file.h
|
@ -6,8 +6,7 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
struct FCEUFILE {
|
struct FCEUFILE {
|
||||||
//void *fp; // FILE* or ptr to ZIPWRAP
|
//the stream you can use to access the data
|
||||||
//uint32 type; // 0=normal file, 1=gzip, 2=zip
|
|
||||||
std::iostream *stream;
|
std::iostream *stream;
|
||||||
|
|
||||||
//the name of the file, or the logical name of the file within the archive
|
//the name of the file, or the logical name of the file within the archive
|
||||||
|
@ -16,6 +15,9 @@ struct FCEUFILE {
|
||||||
//the filename of the archive (maybe "" if it is not in an archive)
|
//the filename of the archive (maybe "" if it is not in an archive)
|
||||||
std::string archiveFilename;
|
std::string archiveFilename;
|
||||||
|
|
||||||
|
//a the path to the filename, possibly using | to get into the archive
|
||||||
|
std::string fullFilename;
|
||||||
|
|
||||||
//the number of files that were in the archive
|
//the number of files that were in the archive
|
||||||
int archiveCount;
|
int archiveCount;
|
||||||
|
|
||||||
|
@ -25,6 +27,9 @@ struct FCEUFILE {
|
||||||
//the size of the file
|
//the size of the file
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
|
//whether the file is contained in an archive
|
||||||
|
bool isArchive() { return archiveCount > 0; }
|
||||||
|
|
||||||
FCEUFILE()
|
FCEUFILE()
|
||||||
: stream(0)
|
: stream(0)
|
||||||
, archiveCount(-1)
|
, archiveCount(-1)
|
||||||
|
@ -53,10 +58,13 @@ struct ArchiveScanRecord
|
||||||
}
|
}
|
||||||
int type;
|
int type;
|
||||||
int numFiles;
|
int numFiles;
|
||||||
|
|
||||||
|
bool isArchive() { return type != -1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
FCEUFILE *FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext);
|
FCEUFILE *FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext, int index=-1);
|
||||||
|
bool FCEU_isFileInArchive(const char *path);
|
||||||
int FCEU_fclose(FCEUFILE*);
|
int FCEU_fclose(FCEUFILE*);
|
||||||
uint64 FCEU_fread(void *ptr, size_t size, size_t nmemb, FCEUFILE*);
|
uint64 FCEU_fread(void *ptr, size_t size, size_t nmemb, FCEUFILE*);
|
||||||
uint64 FCEU_fwrite(void *ptr, size_t size, size_t nmemb, FCEUFILE*);
|
uint64 FCEU_fwrite(void *ptr, size_t size, size_t nmemb, FCEUFILE*);
|
||||||
|
|
|
@ -456,13 +456,20 @@ static void LoadFM2_binarychunk(MovieData& movieData, std::istream* fp, int size
|
||||||
{
|
{
|
||||||
movieData.records[i].parseBinary(&movieData,fp);
|
movieData.records[i].parseBinary(&movieData,fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//yuck... another custom text parser.
|
//yuck... another custom text parser.
|
||||||
static void LoadFM2(MovieData& movieData, std::istream* fp, int size, bool stopAfterHeader)
|
static bool LoadFM2(MovieData& movieData, std::istream* fp, int size, bool stopAfterHeader)
|
||||||
{
|
{
|
||||||
|
//movie must start with "version 3"
|
||||||
|
char buf[9];
|
||||||
|
std::ios::pos_type curr = fp->tellg();
|
||||||
|
fp->read(buf,9);
|
||||||
|
if(fp->fail()) return false;
|
||||||
|
if(memcmp(buf,"version 3",9))
|
||||||
|
return false;
|
||||||
|
fp->seekg(curr);
|
||||||
|
|
||||||
std::string key,value;
|
std::string key,value;
|
||||||
enum {
|
enum {
|
||||||
NEWLINE, KEY, SEPARATOR, VALUE, RECORD, COMMENT
|
NEWLINE, KEY, SEPARATOR, VALUE, RECORD, COMMENT
|
||||||
|
@ -482,7 +489,7 @@ static void LoadFM2(MovieData& movieData, std::istream* fp, int size, bool stopA
|
||||||
if(isrecchar && movieData.binaryFlag && !stopAfterHeader)
|
if(isrecchar && movieData.binaryFlag && !stopAfterHeader)
|
||||||
{
|
{
|
||||||
LoadFM2_binarychunk(movieData, fp, size);
|
LoadFM2_binarychunk(movieData, fp, size);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
switch(state)
|
switch(state)
|
||||||
{
|
{
|
||||||
|
@ -499,7 +506,7 @@ static void LoadFM2(MovieData& movieData, std::istream* fp, int size, bool stopA
|
||||||
case RECORD:
|
case RECORD:
|
||||||
{
|
{
|
||||||
dorecord:
|
dorecord:
|
||||||
if (stopAfterHeader) return;
|
if (stopAfterHeader) return true;
|
||||||
int currcount = movieData.records.size();
|
int currcount = movieData.records.size();
|
||||||
movieData.records.resize(currcount+1);
|
movieData.records.resize(currcount+1);
|
||||||
int preparse = fp->tellg();
|
int preparse = fp->tellg();
|
||||||
|
@ -541,6 +548,8 @@ static void LoadFM2(MovieData& movieData, std::istream* fp, int size, bool stopA
|
||||||
done: ;
|
done: ;
|
||||||
if(bail) break;
|
if(bail) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void closeRecordingMovie()
|
static void closeRecordingMovie()
|
||||||
|
@ -691,10 +700,14 @@ void FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _paus
|
||||||
currMovieData = MovieData();
|
currMovieData = MovieData();
|
||||||
|
|
||||||
strcpy(curMovieFilename, fname);
|
strcpy(curMovieFilename, fname);
|
||||||
std::fstream* fp = FCEUD_UTF8_fstream(fname, "rb");
|
FCEUFILE *fp = FCEU_fopen(fname,0,"rb",0);
|
||||||
if (!fp) return;
|
if (!fp) return;
|
||||||
LoadFM2(currMovieData, fp, INT_MAX, false);
|
if(fp->isArchive() && !_read_only) {
|
||||||
fp->close();
|
FCEU_PrintError("Cannot open a movie in read+write from an archive.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadFM2(currMovieData, fp->stream, INT_MAX, false);
|
||||||
delete fp;
|
delete fp;
|
||||||
|
|
||||||
//fully reload the game to reinitialize everything before playing any movie
|
//fully reload the game to reinitialize everything before playing any movie
|
||||||
|
@ -937,6 +950,14 @@ bool FCEUMOV_ReadState(std::istream* is, uint32 size)
|
||||||
{
|
{
|
||||||
load_successful = false;
|
load_successful = false;
|
||||||
|
|
||||||
|
//a little rule: cant load states in read+write mode with a movie from an archive.
|
||||||
|
//so we are going to switch it to readonly mode in that case
|
||||||
|
if(!movie_readonly && FCEU_isFileInArchive(curMovieFilename)) {
|
||||||
|
FCEU_PrintError("Cannot loadstate in Read+Write with movie from archive. Movie is now Read-Only.");
|
||||||
|
movie_readonly = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////write the state to disk so we can reload
|
////write the state to disk so we can reload
|
||||||
//std::vector<char> buf(size);
|
//std::vector<char> buf(size);
|
||||||
//fread(&buf[0],1,size,st);
|
//fread(&buf[0],1,size,st);
|
||||||
|
@ -1081,13 +1102,11 @@ void FCEUI_MoviePlayFromBeginning(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool FCEUI_MovieGetInfo(const std::string& fname, MOVIE_INFO* info, bool skipFrameCount)
|
bool FCEUI_MovieGetInfo(FCEUFILE* fp, MOVIE_INFO* /* [in, out] */ info, bool skipFrameCount)
|
||||||
{
|
{
|
||||||
MovieData md;
|
MovieData md;
|
||||||
std::fstream* fp = FCEUD_UTF8_fstream(fname, "rb");
|
if(!LoadFM2(md, fp->stream, INT_MAX, skipFrameCount))
|
||||||
if(!fp) return false;
|
return false;
|
||||||
LoadFM2(md, fp, INT_MAX, skipFrameCount);
|
|
||||||
delete fp;
|
|
||||||
|
|
||||||
info->movie_version = md.version;
|
info->movie_version = md.version;
|
||||||
info->poweron = md.savestate.size()==0;
|
info->poweron = md.savestate.size()==0;
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#include "input/zapper.h"
|
#include "input/zapper.h"
|
||||||
#include "utils/guid.h"
|
#include "utils/guid.h"
|
||||||
|
|
||||||
|
struct FCEUFILE;
|
||||||
|
|
||||||
enum EMOVIE_FLAG
|
enum EMOVIE_FLAG
|
||||||
{
|
{
|
||||||
MOVIE_FLAG_NONE = 0,
|
MOVIE_FLAG_NONE = 0,
|
||||||
|
@ -232,7 +234,7 @@ void FCEUI_SaveMovie(const char *fname, EMOVIE_FLAG flags);
|
||||||
void FCEUI_LoadMovie(const char *fname, bool read_only, bool tasedit, int _stopframe);
|
void FCEUI_LoadMovie(const char *fname, bool read_only, bool tasedit, int _stopframe);
|
||||||
void FCEUI_MoviePlayFromBeginning(void);
|
void FCEUI_MoviePlayFromBeginning(void);
|
||||||
void FCEUI_StopMovie(void);
|
void FCEUI_StopMovie(void);
|
||||||
bool FCEUI_MovieGetInfo(const std::string& fname, MOVIE_INFO* /* [in, out] */ info, bool skipFrameCount = false);
|
bool FCEUI_MovieGetInfo(FCEUFILE* fp, MOVIE_INFO* /* [in, out] */ info, bool skipFrameCount = false);
|
||||||
char* FCEUI_MovieGetCurrentName(int addSlotNumber);
|
char* FCEUI_MovieGetCurrentName(int addSlotNumber);
|
||||||
void FCEUI_MovieToggleReadOnly(void);
|
void FCEUI_MovieToggleReadOnly(void);
|
||||||
bool FCEUI_GetMovieToggleReadOnly();
|
bool FCEUI_GetMovieToggleReadOnly();
|
||||||
|
|
|
@ -565,3 +565,13 @@ std::string readNullTerminatedAscii(std::istream* is)
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// replace all instances of victim with replacement
|
||||||
|
std::string mass_replace(const std::string &source, const std::string &victim, const std::string &replacement)
|
||||||
|
{
|
||||||
|
std::string answer = source;
|
||||||
|
std::string::size_type j = 0;
|
||||||
|
while ((j = answer.find(victim, j)) != std::string::npos )
|
||||||
|
answer.replace(j, victim.length(), replacement);
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
|
@ -113,3 +113,6 @@ template<typename T, int DIGITS, bool PAD> void putdec(std::ostream* os, T dec)
|
||||||
else
|
else
|
||||||
os->write(temp,DIGITS);
|
os->write(temp,DIGITS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string mass_replace(const std::string &source, const std::string &victim, const std::string &replacement);
|
Loading…
Reference in New Issue