dont read every archive file when scanning for replay. scan them, though, and look only for *.fm2

This commit is contained in:
zeromus 2008-08-17 19:02:19 +00:00
parent 8da54eff69
commit 4bd3881f1b
3 changed files with 89 additions and 39 deletions

View File

@ -15,6 +15,8 @@
#include "driver.h" #include "driver.h"
#include "main.h" #include "main.h"
static FCEUARCHIVEFILEINFO *currFileSelectorContext;
DEFINE_GUID(CLSID_CFormat_07,0x23170F69,0x40C1,0x278A,0x10,0x00,0x00,0x01,0x10,0x07,0x00,0x00); DEFINE_GUID(CLSID_CFormat_07,0x23170F69,0x40C1,0x278A,0x10,0x00,0x00,0x01,0x10,0x07,0x00,0x00);
class OutStream : public IArchiveExtractCallback class OutStream : public IArchiveExtractCallback
@ -280,17 +282,6 @@ public:
} }
}; };
struct FileSelectorContext
{
struct Item
{
std::string name;
uint32 size, index;
};
std::vector<Item> items;
} *currFileSelectorContext;
static BOOL CALLBACK ArchiveFileSelectorCallback(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) static BOOL CALLBACK ArchiveFileSelectorCallback(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ {
@ -436,14 +427,53 @@ ArchiveScanRecord FCEUD_ScanArchive(std::string fname)
if (SUCCEEDED(object->Open(&ifs,0,0))) if (SUCCEEDED(object->Open(&ifs,0,0)))
{ {
uint32 numFiles; uint32 numFiles;
if (SUCCEEDED(object->GetNumberOfItems(&numFiles))) if (SUCCEEDED(object->GetNumberOfItems(&numFiles)))
{ {
ArchiveScanRecord asr(matchingFormat,(int)numFiles);
//scan the filename of each item
for(uint32 i=0;i<numFiles;i++)
{
FCEUARCHIVEFILEINFO::Item item;
item.index = i;
PROPVARIANT prop;
prop.vt = VT_EMPTY;
if (FAILED(object->GetProperty( i, kpidSize, &prop )) || prop.vt != VT_UI8 || !prop.uhVal.LowPart || prop.uhVal.HighPart)
goto bomb;
item.size = prop.uhVal.LowPart;
if (FAILED(object->GetProperty( i, kpidPath, &prop )) || prop.vt != VT_BSTR || prop.bstrVal == NULL)
goto bomb;
std::wstring tempfname = prop.bstrVal;
int buflen = tempfname.size()*2;
char* buf = new char[buflen];
int ret = WideCharToMultiByte(CP_ACP,0,tempfname.c_str(),tempfname.size(),buf,buflen,0,0);
if(ret == 0) {
delete[] buf;
::VariantClear( reinterpret_cast<VARIANTARG*>(&prop) );
continue;
}
buf[ret] = 0;
item.name = buf;
delete[] buf;
::VariantClear( reinterpret_cast<VARIANTARG*>(&prop) );
asr.files.items.push_back(item);
}
object->Release(); object->Release();
return ArchiveScanRecord(matchingFormat,(int)numFiles); return asr;
} }
} }
} }
bomb:
object->Release(); object->Release();
return ArchiveScanRecord(); return ArchiveScanRecord();
@ -451,6 +481,8 @@ ArchiveScanRecord FCEUD_ScanArchive(std::string fname)
extern HWND hAppWnd; extern HWND hAppWnd;
//TODO - factor out the filesize and name extraction code from below (it is already done once above)
static FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::string* innerFilename, int innerIndex) static FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::string* innerFilename, int innerIndex)
{ {
FCEUFILE* fp = 0; FCEUFILE* fp = 0;
@ -479,12 +511,12 @@ static FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, s
uint32 numFiles; uint32 numFiles;
if (SUCCEEDED(object->GetNumberOfItems(&numFiles))) if (SUCCEEDED(object->GetNumberOfItems(&numFiles)))
{ {
FileSelectorContext fileSelectorContext; FCEUARCHIVEFILEINFO fileSelectorContext;
currFileSelectorContext = &fileSelectorContext; currFileSelectorContext = &fileSelectorContext;
for(uint32 i=0;i<numFiles;i++) for(uint32 i=0;i<numFiles;i++)
{ {
FileSelectorContext::Item item; FCEUARCHIVEFILEINFO::Item item;
item.index = i; item.index = i;
PROPVARIANT prop; PROPVARIANT prop;
@ -509,19 +541,7 @@ static FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, s
} }
else else
{ {
std::wstring tempfname = prop.bstrVal;
int buflen = tempfname.size()*2;
char* buf = new char[buflen];
int ret = WideCharToMultiByte(CP_ACP,0,tempfname.c_str(),tempfname.size(),buf,buflen,0,0);
if(ret == 0) {
delete[] buf;
::VariantClear( reinterpret_cast<VARIANTARG*>(&prop) );
continue;
}
buf[ret] = 0;
item.name = buf;
delete[] buf;
} }
::VariantClear( reinterpret_cast<VARIANTARG*>(&prop) ); ::VariantClear( reinterpret_cast<VARIANTARG*>(&prop) );
@ -548,7 +568,7 @@ static FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, s
if(ret != LB_ERR) if(ret != LB_ERR)
{ {
FileSelectorContext::Item& item = fileSelectorContext.items[ret]; FCEUARCHIVEFILEINFO::Item& item = fileSelectorContext.items[ret];
memorystream* ms = new memorystream(item.size); memorystream* ms = new memorystream(item.size);
OutStream outStream( item.index, ms->buf(), item.size); OutStream outStream( item.index, ms->buf(), item.size);
const uint32 indices[1] = {item.index}; const uint32 indices[1] = {item.index};

View File

@ -399,6 +399,21 @@ void HandleScan(HWND hwndDlg, FCEUFILE* file, int& i)
SendDlgItemMessage(hwndDlg, IDC_COMBO_FILENAME, CB_INSERTSTRING, i++, (LPARAM)relative); SendDlgItemMessage(hwndDlg, IDC_COMBO_FILENAME, CB_INSERTSTRING, i++, (LPARAM)relative);
} }
//TODO - dont we already have another function that can do this
std::string getExtension(const char* input) {
char buf[1024];
strcpy(buf,input);
char* dot=strrchr(buf,'.');
if(!dot)
return "";
char ext [512];
strcpy(ext, dot+1);
int k, extlen=strlen(ext);
for(k=0;k<extlen;k++)
ext[k]=tolower(ext[k]);
return ext;
}
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)
@ -465,21 +480,16 @@ 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;
//TODO - a big copy/pasted block below. factor out extension extractor or use another one
// filter out everything that's not an extension we like *.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,'.'); std::string ext = getExtension(wfd.cFileName);
if(!dot) if(ext != "fm2")
continue; if(ext != "zip")
char ext [512]; if(ext != "rar")
strcpy(ext, dot+1); if(ext != "7z")
int k, extlen=strlen(ext);
for(k=0;k<extlen;k++)
ext[k]=tolower(ext[k]);
if(stricmp(ext,"fm2"))
if(stricmp(ext,"zip"))
if(stricmp(ext,"rar"))
if(stricmp(ext,"7z"))
continue; continue;
} }
@ -491,6 +501,9 @@ BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
ArchiveScanRecord asr = FCEUD_ScanArchive(filename); ArchiveScanRecord asr = FCEUD_ScanArchive(filename);
if(asr.numFiles>1) { if(asr.numFiles>1) {
for(int i=0;i<asr.numFiles;i++) { for(int i=0;i<asr.numFiles;i++) {
std::string ext = getExtension(asr.files.items[i].name.c_str());
if(ext != "fm2")
continue;
FCEUFILE* fp = FCEU_fopen(filename,0,"rb",0,i); FCEUFILE* fp = FCEU_fopen(filename,0,"rb",0,i);
if(fp) { if(fp) {
HandleScan(hwndDlg,fp, items); HandleScan(hwndDlg,fp, items);
@ -499,6 +512,11 @@ BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
} }
} else } else
{ {
if(asr.numFiles == 1) {
std::string ext = getExtension(asr.files.items[0].name.c_str());
if(ext != "fm2")
continue;
}
FCEUFILE* fp = FCEU_fopen(filename,0,"rb",0); FCEUFILE* fp = FCEU_fopen(filename,0,"rb",0);
if(fp) { if(fp) {
HandleScan(hwndDlg,fp ,items); HandleScan(hwndDlg,fp ,items);

View File

@ -71,6 +71,16 @@ struct FCEUFILE {
} }
}; };
struct FCEUARCHIVEFILEINFO
{
struct Item
{
std::string name;
uint32 size, index;
};
std::vector<Item> items;
};
struct FileBaseInfo { struct FileBaseInfo {
std::string filebase, filebasedirectory, ext; std::string filebase, filebasedirectory, ext;
FileBaseInfo() {} FileBaseInfo() {}
@ -97,6 +107,8 @@ struct ArchiveScanRecord
int type; int type;
int numFiles; int numFiles;
FCEUARCHIVEFILEINFO files;
bool isArchive() { return type != -1; } bool isArchive() { return type != -1; }
}; };