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;
TFormatRecords formatRecords;
static bool archiveSystemInitialized=false;
static LibRef libref("7z.dll");
void initArchiveSystem()
{
LibRef libref("7z.dll");
if(!libref.hmod)
{
//couldnt initialize archive system
return;
}
typedef HRESULT (WINAPI *GetNumberOfFormatsFunc)(UINT32 *numFormats);
@ -355,6 +357,14 @@ void initArchiveSystem()
GetNumberOfFormatsFunc GetNumberOfFormats = (GetNumberOfFormatsFunc)GetProcAddress(libref.hmod,"GetNumberOfFormats");
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;
GetNumberOfFormats(&numFormats);
@ -384,9 +394,10 @@ void initArchiveSystem()
ArchiveScanRecord FCEUD_ScanArchive(std::string fname)
{
LibRef libref("7z.dll");
if(!libref.hmod)
if(!archiveSystemInitialized)
{
return ArchiveScanRecord();
}
//check the file against the signatures
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;
LibRef libref("7z.dll");
if(!libref.hmod) {
if(!archiveSystemInitialized) {
MessageBox(hAppWnd,"Could not locate 7z.dll","Failure launching archive browser",0);
return 0;
}
@ -457,6 +467,7 @@ FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::str
}
bool unnamedFileFound = false;
IInArchive* 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;
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;
if (FAILED(object->GetProperty( i, kpidPath, &prop )) || prop.vt != VT_BSTR || prop.bstrVal == NULL)
continue;
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;
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;
}
buf[ret] = 0;
item.name = buf;
delete[] buf;
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) );
fileSelectorContext.items.push_back(item);
}
@ -514,8 +537,11 @@ FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::str
break;
}
}
else if(numFiles==1)
//or automatically choose the first file if there was only one file in the archive
ret = 0;
else
//or use the UI if we're not
//otherwise use the UI
ret = DialogBoxParam(fceu_hInstance, "ARCHIVECHOOSERDIALOG", hAppWnd, ArchiveFileSelectorCallback, (LPARAM)0);
if(ret != LB_ERR)
@ -524,7 +550,8 @@ FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::str
memorystream* ms = new memorystream(item.size);
OutStream outStream( item.index, ms->buf(), item.size);
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
fp = new FCEUFILE();
@ -534,6 +561,7 @@ FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::str
fp->mode = FCEUFILE::READ;
fp->size = fileSelectorContext.items[ret].size;
fp->stream = ms;
fp->archiveCount = (int)numFiles;
}
else
{
@ -544,6 +572,7 @@ FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::str
} //if we scanned the 7z correctly
} //if we opened the 7z correctly
bomb:
object->Release();
}

View File

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

View File

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

View File

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

View File

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