proper support for single-file archives

This commit is contained in:
zeromus 2008-07-10 05:42:12 +00:00
parent 81241b5d26
commit 0a63a42df2
5 changed files with 67 additions and 24 deletions

View File

@ -340,13 +340,15 @@ struct FormatRecord
typedef std::vector<FormatRecord> TFormatRecords; typedef std::vector<FormatRecord> TFormatRecords;
TFormatRecords formatRecords; TFormatRecords formatRecords;
static bool archiveSystemInitialized=false;
static LibRef libref("7z.dll");
void initArchiveSystem() void initArchiveSystem()
{ {
LibRef libref("7z.dll");
if(!libref.hmod) if(!libref.hmod)
{ {
//couldnt initialize archive system //couldnt initialize archive system
return;
} }
typedef HRESULT (WINAPI *GetNumberOfFormatsFunc)(UINT32 *numFormats); typedef HRESULT (WINAPI *GetNumberOfFormatsFunc)(UINT32 *numFormats);
@ -355,6 +357,14 @@ void initArchiveSystem()
GetNumberOfFormatsFunc GetNumberOfFormats = (GetNumberOfFormatsFunc)GetProcAddress(libref.hmod,"GetNumberOfFormats"); GetNumberOfFormatsFunc GetNumberOfFormats = (GetNumberOfFormatsFunc)GetProcAddress(libref.hmod,"GetNumberOfFormats");
GetHandlerProperty2Func GetHandlerProperty2 = (GetHandlerProperty2Func)GetProcAddress(libref.hmod,"GetHandlerProperty2"); GetHandlerProperty2Func GetHandlerProperty2 = (GetHandlerProperty2Func)GetProcAddress(libref.hmod,"GetHandlerProperty2");
if(!GetNumberOfFormats || !GetHandlerProperty2)
{
//not the right dll.
return;
}
//looks like it is gonna be OK
archiveSystemInitialized = true;
UINT32 numFormats; UINT32 numFormats;
GetNumberOfFormats(&numFormats); GetNumberOfFormats(&numFormats);
@ -384,9 +394,10 @@ void initArchiveSystem()
ArchiveScanRecord FCEUD_ScanArchive(std::string fname) ArchiveScanRecord FCEUD_ScanArchive(std::string fname)
{ {
LibRef libref("7z.dll"); if(!archiveSystemInitialized)
if(!libref.hmod) {
return ArchiveScanRecord(); return ArchiveScanRecord();
}
//check the file against the signatures //check the file against the signatures
std::fstream* inf = FCEUD_UTF8_fstream(fname,"rb"); std::fstream* inf = FCEUD_UTF8_fstream(fname,"rb");
@ -442,8 +453,7 @@ FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::str
{ {
FCEUFILE* fp = 0; FCEUFILE* fp = 0;
LibRef libref("7z.dll"); if(!archiveSystemInitialized) {
if(!libref.hmod) {
MessageBox(hAppWnd,"Could not locate 7z.dll","Failure launching archive browser",0); MessageBox(hAppWnd,"Could not locate 7z.dll","Failure launching archive browser",0);
return 0; return 0;
} }
@ -457,6 +467,7 @@ FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::str
} }
bool unnamedFileFound = false;
IInArchive* object; IInArchive* object;
if (!FAILED(CreateObject( &formatRecords[asr.type].guid, &IID_IInArchive, (void**)&object ))) if (!FAILED(CreateObject( &formatRecords[asr.type].guid, &IID_IInArchive, (void**)&object )))
{ {
@ -478,28 +489,40 @@ FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::str
prop.vt = VT_EMPTY; prop.vt = VT_EMPTY;
if (FAILED(object->GetProperty( i, kpidSize, &prop )) || prop.vt != VT_UI8 || !prop.uhVal.LowPart || prop.uhVal.HighPart) if (FAILED(object->GetProperty( i, kpidSize, &prop )) || prop.vt != VT_UI8 || !prop.uhVal.LowPart || prop.uhVal.HighPart)
continue; {
goto bomb;
}
item.size = prop.uhVal.LowPart; item.size = prop.uhVal.LowPart;
if (FAILED(object->GetProperty( i, kpidPath, &prop )) || prop.vt != VT_BSTR || prop.bstrVal == NULL) if (FAILED(object->GetProperty( i, kpidPath, &prop )) || prop.vt != VT_BSTR || prop.bstrVal == NULL)
continue; {
//mbg 7/10/08 - this was attempting to handle gz files, but it fails later in the extraction
if(!unnamedFileFound)
{
unnamedFileFound = true;
item.name = "<unnamed>";
}
else goto bomb;
}
else
{
std::wstring tempfname = prop.bstrVal; std::wstring tempfname = prop.bstrVal;
int buflen = tempfname.size()*2; int buflen = tempfname.size()*2;
char* buf = new char[buflen]; char* buf = new char[buflen];
int ret = WideCharToMultiByte(CP_ACP,0,tempfname.c_str(),tempfname.size(),buf,buflen,0,0); int ret = WideCharToMultiByte(CP_ACP,0,tempfname.c_str(),tempfname.size(),buf,buflen,0,0);
if(ret == 0) { if(ret == 0) {
delete[] buf; delete[] buf;
::VariantClear( reinterpret_cast<VARIANTARG*>(&prop) );
continue; continue;
} }
buf[ret] = 0; buf[ret] = 0;
item.name = buf; item.name = buf;
delete[] buf; delete[] buf;
}
::VariantClear( reinterpret_cast<VARIANTARG*>(&prop) ); ::VariantClear( reinterpret_cast<VARIANTARG*>(&prop) );
fileSelectorContext.items.push_back(item); fileSelectorContext.items.push_back(item);
} }
@ -514,8 +537,11 @@ FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::str
break; break;
} }
} }
else if(numFiles==1)
//or automatically choose the first file if there was only one file in the archive
ret = 0;
else else
//or use the UI if we're not //otherwise use the UI
ret = DialogBoxParam(fceu_hInstance, "ARCHIVECHOOSERDIALOG", hAppWnd, ArchiveFileSelectorCallback, (LPARAM)0); ret = DialogBoxParam(fceu_hInstance, "ARCHIVECHOOSERDIALOG", hAppWnd, ArchiveFileSelectorCallback, (LPARAM)0);
if(ret != LB_ERR) if(ret != LB_ERR)
@ -524,7 +550,8 @@ FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::str
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};
if (SUCCEEDED(object->Extract(indices,1,0,&outStream))) HRESULT hr = object->Extract(indices,1,0,&outStream);
if (SUCCEEDED(hr))
{ {
//if we extracted the file correctly //if we extracted the file correctly
fp = new FCEUFILE(); fp = new FCEUFILE();
@ -534,6 +561,7 @@ FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::str
fp->mode = FCEUFILE::READ; fp->mode = FCEUFILE::READ;
fp->size = fileSelectorContext.items[ret].size; fp->size = fileSelectorContext.items[ret].size;
fp->stream = ms; fp->stream = ms;
fp->archiveCount = (int)numFiles;
} }
else else
{ {
@ -544,6 +572,7 @@ FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::str
} //if we scanned the 7z correctly } //if we scanned the 7z correctly
} //if we opened the 7z correctly } //if we opened the 7z correctly
bomb:
object->Release(); object->Release();
} }

View File

@ -569,7 +569,7 @@ void ALoad(char *nameo, char* innerFilename)
SetMainWindowStuff(); SetMainWindowStuff();
std::string recentFileName = nameo; std::string recentFileName = nameo;
if(GameInfo->archiveFilename) if(GameInfo->archiveFilename && GameInfo->archiveCount>1)
recentFileName = (std::string)GameInfo->archiveFilename + "|" + GameInfo->filename; recentFileName = (std::string)GameInfo->archiveFilename + "|" + GameInfo->filename;
else else
recentFileName = nameo; recentFileName = nameo;

View File

@ -358,6 +358,7 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode)
GameInfo->filename = strdup(fp->filename.c_str()); GameInfo->filename = strdup(fp->filename.c_str());
if(fp->archiveFilename != "") GameInfo->archiveFilename = strdup(fp->archiveFilename.c_str()); if(fp->archiveFilename != "") GameInfo->archiveFilename = strdup(fp->archiveFilename.c_str());
GameInfo->archiveCount = fp->archiveCount;
GameInfo->soundchan = 0; GameInfo->soundchan = 0;
GameInfo->soundrate = 0; GameInfo->soundrate = 0;

View File

@ -9,13 +9,25 @@ struct FCEUFILE {
//void *fp; // FILE* or ptr to ZIPWRAP //void *fp; // FILE* or ptr to ZIPWRAP
//uint32 type; // 0=normal file, 1=gzip, 2=zip //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
std::string filename; std::string filename;
//the filename of the archive (maybe "" if it is not in an archive)
std::string archiveFilename; std::string archiveFilename;
//the number of files that were in the archive
int archiveCount;
//the index of the file within the archive
int archiveIndex; int archiveIndex;
//the size of the file
int size; int size;
FCEUFILE() FCEUFILE()
: stream(0) : stream(0)
, archiveCount(-1)
{} {}
~FCEUFILE() ~FCEUFILE()

View File

@ -131,6 +131,7 @@ struct FCEUGI
char* filename; char* filename;
char* archiveFilename; char* archiveFilename;
int archiveCount;
}; };
#endif #endif