generalized the loading-from-archive code to work with any archive format and to load any kind of file from archives (although nothing but the roms may work yet and i will have to fiddle with things as requested). I probably broke the sdl build; just stub the two new FCEUD_ functions in the most brainless way possible and it should work.

This commit is contained in:
zeromus 2008-07-09 05:47:13 +00:00
parent 5c22d93e11
commit bc54e2abba
21 changed files with 383 additions and 401 deletions

View File

@ -7,6 +7,7 @@
#include "types.h" #include "types.h"
#include "git.h" #include "git.h"
#include "file.h"
FILE *FCEUD_UTF8fopen(const char *fn, const char *mode); FILE *FCEUD_UTF8fopen(const char *fn, const char *mode);
inline FILE *FCEUD_UTF8fopen(const std::string &n, const char *mode) { return FCEUD_UTF8fopen(n.c_str(),mode); } inline FILE *FCEUD_UTF8fopen(const std::string &n, const char *mode) { return FCEUD_UTF8fopen(n.c_str(),mode); }
@ -93,8 +94,8 @@ void FCEUI_GetRenderPlanes(bool& sprites, bool& bg);
FCEUGI *FCEUI_LoadGame(const char *name, int OverwriteVidMode); FCEUGI *FCEUI_LoadGame(const char *name, int OverwriteVidMode);
//same as FCEUI_LoadGame, except that it can load from a tempfile. //same as FCEUI_LoadGame, except that it can load from a tempfile.
//name is the actual path to open; logicalname is what the emulator should think it is //name is the logical path to open; archiveFilename is the archive which contains name
FCEUGI *FCEUI_LoadGameVirtual(const char *name, const char *logicalname, int OverwriteVidMode); FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode);
//general purpose emulator initialization. returns true if successful //general purpose emulator initialization. returns true if successful
bool FCEUI_Initialize(); bool FCEUI_Initialize();
@ -318,6 +319,11 @@ enum EFCEUI
//checks whether an EFCEUI is valid right now //checks whether an EFCEUI is valid right now
bool FCEU_IsValidUI(EFCEUI ui); bool FCEU_IsValidUI(EFCEUI ui);
//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);
//scans a file to see if it is an archive you can handle
ArchiveScanRecord FCEUD_ScanArchive(std::string fname);
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"

BIN
src/drivers/win/7z.dll Normal file

Binary file not shown.

View File

@ -1,2 +0,0 @@
//if you want to autopilot this, pass in an innerfilename to try and automatically load
void do7zip(HWND hParent, std::string fname, std::string* innerFilename=0);

Binary file not shown.

View File

@ -8,11 +8,14 @@
#include <OleAuto.h> #include <OleAuto.h>
#include "7zip/IArchive.h" #include "7zip/IArchive.h"
#include "file.h"
#include "utils/memorystream.h"
#include "utils/guid.h"
#include "driver.h" #include "driver.h"
#include "main.h" #include "main.h"
DEFINE_GUID(CLSID_CFormat7z,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
{ {
@ -269,7 +272,7 @@ class LibRef
public: public:
HMODULE hmod; HMODULE hmod;
LibRef(const char* fname) { LibRef(const char* fname) {
hmod = LoadLibrary("7zxa.dll"); hmod = LoadLibrary(fname);
} }
~LibRef() { ~LibRef() {
if(hmod) if(hmod)
@ -327,24 +330,135 @@ static BOOL CALLBACK ArchiveFileSelectorCallback(HWND hwndDlg, UINT uMsg, WPARAM
return FALSE; return FALSE;
} }
void do7zip(HWND hParent, std::string fname, std::string* innerFilename) typedef UINT32 (WINAPI *CreateObjectFunc)(const GUID*,const GUID*,void**);
struct FormatRecord
{ {
LibRef libref("7zxa.dll"); std::vector<char> signature;
GUID guid;
};
typedef std::vector<FormatRecord> TFormatRecords;
TFormatRecords formatRecords;
void initArchiveSystem()
{
LibRef libref("7z.dll");
if(!libref.hmod)
{
//couldnt initialize archive system
}
typedef HRESULT (WINAPI *GetNumberOfFormatsFunc)(UINT32 *numFormats);
typedef HRESULT (WINAPI *GetHandlerProperty2Func)(UInt32 formatIndex, PROPID propID, PROPVARIANT *value);
GetNumberOfFormatsFunc GetNumberOfFormats = (GetNumberOfFormatsFunc)GetProcAddress(libref.hmod,"GetNumberOfFormats");
GetHandlerProperty2Func GetHandlerProperty2 = (GetHandlerProperty2Func)GetProcAddress(libref.hmod,"GetHandlerProperty2");
UINT32 numFormats;
GetNumberOfFormats(&numFormats);
for(uint32 i=0;i<numFormats;i++)
{
PROPVARIANT prop;
prop.vt = VT_EMPTY;
GetHandlerProperty2(i,NArchive::kStartSignature,&prop);
FormatRecord fr;
int len = SysStringLen(prop.bstrVal);
fr.signature.reserve(len);
for(int j=0;j<len;j++)
fr.signature.push_back(((char*)prop.bstrVal)[j]);
GetHandlerProperty2(i,NArchive::kClassID,&prop);
memcpy((char*)&fr.guid,(char*)prop.bstrVal,16);
formatRecords.push_back(fr);
::VariantClear( reinterpret_cast<VARIANTARG*>(&prop) );
}
}
ArchiveScanRecord FCEUD_ScanArchive(std::string fname)
{
LibRef libref("7z.dll");
if(!libref.hmod)
return ArchiveScanRecord();
//check the file against the signatures
std::fstream* inf = FCEUD_UTF8_fstream(fname,"rb");
int matchingFormat = -1;
for(uint32 i=0;i<(int)formatRecords.size();i++)
{
inf->seekg(0);
int size = formatRecords[i].signature.size();
if(size==0)
continue; //WHY??
char* temp = new char[size];
inf->read((char*)temp,size);
if(!memcmp(&formatRecords[i].signature[0],temp,size))
{
delete[] temp;
matchingFormat = i;
break;
}
delete[] temp;
}
delete inf;
if(matchingFormat == -1)
return ArchiveScanRecord();
CreateObjectFunc CreateObject = (CreateObjectFunc)GetProcAddress(libref.hmod,"CreateObject");
if(!CreateObject)
return ArchiveScanRecord();
IInArchive* object;
if (!FAILED(CreateObject( &formatRecords[matchingFormat].guid, &IID_IInArchive, (void**)&object )))
{
//fetch the start signature
InFileStream ifs(fname);
if (SUCCEEDED(object->Open(&ifs,0,0)))
{
uint32 numFiles;
if (SUCCEEDED(object->GetNumberOfItems(&numFiles)))
{
object->Release();
return ArchiveScanRecord(matchingFormat,(int)numFiles);
}
}
}
object->Release();
return ArchiveScanRecord();
}
extern HWND hAppWnd;
FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::string* innerFilename)
{
FCEUFILE* fp = 0;
LibRef libref("7z.dll");
if(!libref.hmod) { if(!libref.hmod) {
MessageBox(hParent,"Could not locate 7zxa.dll","Failure launching 7z archive browser",0); MessageBox(hAppWnd,"Could not locate 7z.dll","Failure launching archive browser",0);
return; return 0;
} }
typedef UINT32 (WINAPI *CreateObjectFunc)(const GUID*,const GUID*,void**); typedef UINT32 (WINAPI *CreateObjectFunc)(const GUID*,const GUID*,void**);
CreateObjectFunc CreateObject = (CreateObjectFunc)GetProcAddress(libref.hmod,"CreateObject"); CreateObjectFunc CreateObject = (CreateObjectFunc)GetProcAddress(libref.hmod,"CreateObject");
if(!CreateObject) if(!CreateObject)
{ {
MessageBox(hParent,"7zxa.dll was invalid","Failure launching 7z archive browser",0); MessageBox(hAppWnd,"7z.dll was invalid","Failure launching archive browser",0);
return; return 0;
} }
IInArchive* object; IInArchive* object;
if (!FAILED(CreateObject( &CLSID_CFormat7z, &IID_IInArchive, (void**)&object ))) if (!FAILED(CreateObject( &formatRecords[asr.type].guid, &IID_IInArchive, (void**)&object )))
{ {
InFileStream ifs(fname); InFileStream ifs(fname);
if (SUCCEEDED(object->Open(&ifs,0,0))) if (SUCCEEDED(object->Open(&ifs,0,0)))
@ -402,24 +516,29 @@ void do7zip(HWND hParent, std::string fname, std::string* innerFilename)
} }
else else
//or use the UI if we're not //or use the UI if we're not
ret = DialogBoxParam(fceu_hInstance, "7ZIPARCHIVEDIALOG", hParent, ArchiveFileSelectorCallback, (LPARAM)0); ret = DialogBoxParam(fceu_hInstance, "ARCHIVECHOOSERDIALOG", hAppWnd, ArchiveFileSelectorCallback, (LPARAM)0);
if(ret != LB_ERR) if(ret != LB_ERR)
{ {
FileSelectorContext::Item& item = fileSelectorContext.items[ret]; FileSelectorContext::Item& item = fileSelectorContext.items[ret];
std::vector<char> data(item.size); memorystream* ms = new memorystream(item.size);
OutStream outStream( item.index, &data[0], 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))) if (SUCCEEDED(object->Extract(indices,1,0,&outStream)))
{ {
char* tempname = tmpnam(0); //if we extracted the file correctly
FILE* outf = fopen(tempname,"wb"); fp = new FCEUFILE();
fwrite(&data[0],1,item.size,outf); fp->archiveFilename = fname;
fclose(outf); fp->filename = fileSelectorContext.items[ret].name;
void ALoad(char *nameo,char* actualfile,char* archiveFile); fp->archiveIndex = ret;
ALoad((char*)item.name.c_str(),tempname,(char*)fname.c_str()); fp->mode = FCEUFILE::READ;
fp->size = fileSelectorContext.items[ret].size;
} //if we extracted the file correctly fp->stream = ms;
}
else
{
delete ms;
}
} //if returned a file from the fileselector } //if returned a file from the fileselector
@ -427,4 +546,6 @@ void do7zip(HWND hParent, std::string fname, std::string* innerFilename)
} //if we opened the 7z correctly } //if we opened the 7z correctly
object->Release(); object->Release();
} }
return fp;
} }

View File

@ -0,0 +1,6 @@
#ifndef _ARCHIVE_H_
#define _ARCHIVE_H_
void initArchiveSystem();
#endif

View File

@ -39,6 +39,7 @@
#include "../../state.h" #include "../../state.h"
#include "../../debug.h" #include "../../debug.h"
#include "../../movie.h" #include "../../movie.h"
#include "archive.h"
#include "input.h" #include "input.h"
#include "netplay.h" #include "netplay.h"
#include "memwatch.h" #include "memwatch.h"
@ -555,6 +556,8 @@ int main(int argc,char *argv[])
{ {
char *t; char *t;
initArchiveSystem();
if(timeBeginPeriod(1) != TIMERR_NOERROR) if(timeBeginPeriod(1) != TIMERR_NOERROR)
{ {
AddLogText("Error setting timer granularity to 1ms.", DO_ADD_NEWLINE); AddLogText("Error setting timer granularity to 1ms.", DO_ADD_NEWLINE);

View File

@ -1392,14 +1392,14 @@ BEGIN
EDITTEXT IDC_PPUVIEW_SCANLINE,72,176,27,12 EDITTEXT IDC_PPUVIEW_SCANLINE,72,176,27,12
END END
7ZIPARCHIVEDIALOG DIALOGEX 0, 0, 265, 159 ARCHIVECHOOSERDIALOG DIALOGEX 0, 0, 265, 159
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Choose File From Archive" CAPTION "Choose File From Archive"
FONT 8, "MS Shell Dlg", 400, 0, 0x1 FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN BEGIN
DEFPUSHBUTTON "OK",IDOK,146,138,50,14 DEFPUSHBUTTON "OK",IDOK,146,138,50,14
PUSHBUTTON "Cancel",IDCANCEL,208,138,50,14 PUSHBUTTON "Cancel",IDCANCEL,208,138,50,14
LISTBOX IDC_LIST1,7,7,251,120,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP LISTBOX IDC_LIST1,7,7,251,120,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP
END END
TEXTHOOKER DIALOGEX 0, 0, 456, 327 TEXTHOOKER DIALOGEX 0, 0, 456, 327
@ -1596,7 +1596,7 @@ BEGIN
BOTTOMMARGIN, 66 BOTTOMMARGIN, 66
END END
"7ZIPARCHIVEDIALOG", DIALOG "ARCHIVECHOOSERDIALOG", DIALOG
BEGIN BEGIN
LEFTMARGIN, 7 LEFTMARGIN, 7
RIGHTMARGIN, 258 RIGHTMARGIN, 258

View File

@ -49,7 +49,6 @@
#include "joystick.h" #include "joystick.h"
#include "oldmovie.h" #include "oldmovie.h"
#include "movie.h" #include "movie.h"
#include "7zip.h"
#include "texthook.h" #include "texthook.h"
#include "guiconfig.h" #include "guiconfig.h"
#include "timing.h" #include "timing.h"
@ -149,13 +148,7 @@ int GetCheckedAutoFireOffset()
// Internal functions // Internal functions
void SplitRecentArchiveFilename(std::string src, std::string& archive, std::string& file)
{
src = src.substr(1);
size_t pipe = src.find_first_of('|');
archive = src.substr(0,pipe);
file = src.substr(pipe+1);
}
static void ConvertFCM(HWND hwndOwner) static void ConvertFCM(HWND hwndOwner)
{ {
@ -401,12 +394,10 @@ void UpdateRMenu(HMENU menu, char **strs, unsigned int mitem, unsigned int basei
continue; continue;
std::string tmp = strs[x]; std::string tmp = strs[x];
if(tmp[0] == '|') std::string archiveName, fileName, fileToOpen;
{ FCEU_SplitArchiveFilename(tmp,archiveName,fileName,fileToOpen);
std::string archiveName, fileName; if(archiveName != "")
SplitRecentArchiveFilename(tmp,archiveName,fileName);
tmp = archiveName + " <" + fileName + ">"; tmp = archiveName + " <" + fileName + ">";
}
//clamp this string to 128 chars //clamp this string to 128 chars
if(tmp.size()>128) if(tmp.size()>128)
@ -567,11 +558,9 @@ void FCEUD_HideMenuToggle(void)
ToggleHideMenu(); ToggleHideMenu();
} }
void ALoad(char *nameo,char* actualfile,char* archiveFile) void ALoad(char *nameo, char* innerFilename)
{ {
bool isvirtual = (actualfile!=0); if(FCEUI_LoadGameVirtual(nameo, 1))
if(!isvirtual) actualfile = nameo;
if(FCEUI_LoadGameVirtual(actualfile, nameo, 1))
{ {
pal_emulation = FCEUI_GetCurrentVidSystem(0, 0); pal_emulation = FCEUI_GetCurrentVidSystem(0, 0);
@ -579,10 +568,9 @@ void ALoad(char *nameo,char* actualfile,char* archiveFile)
SetMainWindowStuff(); SetMainWindowStuff();
//todo-add recent files from archives somehow
std::string recentFileName = nameo; std::string recentFileName = nameo;
if(archiveFile) if(GameInfo->archiveFilename)
recentFileName = (std::string)"|" + archiveFile + "|" + nameo; recentFileName = (std::string)GameInfo->archiveFilename + "|" + GameInfo->filename;
else else
recentFileName = nameo; recentFileName = nameo;
@ -633,17 +621,7 @@ void LoadNewGamey(HWND hParent, const char *initialdir)
// Show the Open File dialog // Show the Open File dialog
if(GetOpenFileName(&ofn)) if(GetOpenFileName(&ofn))
{ {
//if the user selected a 7zip file, then we have some work to do.. ALoad(nameo);
//todo - scan file instead of checking extension
std::string fname = nameo;
if(fname.substr(fname.size()-3,3) == ".7z")
{
do7zip(hParent, fname);
}
else
{
ALoad(nameo,0);
}
} }
} }
@ -775,7 +753,7 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
if((ftmp=(char*)malloc(len))) //mbg merge 7/17/06 added cast if((ftmp=(char*)malloc(len))) //mbg merge 7/17/06 added cast
{ {
DragQueryFile((HDROP)wParam,0,ftmp,len); //mbg merge 7/17/06 changed (HANDLE) to (HDROP) DragQueryFile((HDROP)wParam,0,ftmp,len); //mbg merge 7/17/06 changed (HANDLE) to (HDROP)
ALoad(ftmp,0); ALoad(ftmp);
free(ftmp); free(ftmp);
} }
} }
@ -793,14 +771,7 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
char*& fname = recent_files[wParam - MENU_FIRST_RECENT_FILE]; char*& fname = recent_files[wParam - MENU_FIRST_RECENT_FILE];
if(fname) if(fname)
{ {
if(fname[0] == '|') ALoad(fname);
{
std::string fnamestr = fname, archiveName, fileName;
SplitRecentArchiveFilename(fnamestr,archiveName,fileName);
do7zip(hWnd,archiveName,&fileName);
}
else
ALoad(fname,0);
} }
} }
switch(LOWORD(wParam)) switch(LOWORD(wParam))

View File

@ -23,7 +23,7 @@ void ByebyeWindow();
void DoTimingConfigFix(); void DoTimingConfigFix();
int CreateMainWindow(); int CreateMainWindow();
void UpdateCheckedMenuItems(); void UpdateCheckedMenuItems();
void ALoad(char *nameo,char* actualfile=0, char* archiveFile=0); void ALoad(char* nameo, char* innerFilename=0);
void LoadNewGamey(HWND hParent, const char *initialdir); void LoadNewGamey(HWND hParent, const char *initialdir);
int BrowseForFolder(HWND hParent, const char *htext, char *buf); int BrowseForFolder(HWND hParent, const char *htext, char *buf);
void UpdateCheckedMenuItems(); void UpdateCheckedMenuItems();

View File

@ -59,9 +59,16 @@
int AFon, AFoff, AutoFireOffset = 0; //For keeping track of autofire settings int AFon, AFoff, AutoFireOffset = 0; //For keeping track of autofire settings
unsigned int LagCounter = 0; //This will increment everytime input is not polled by the game FCEUGI::FCEUGI()
bool lagCounterDisplay = false; : filename(0)
bool lagFlag = true; , archiveFilename(0)
{}
FCEUGI::~FCEUGI()
{
if(filename) delete filename;
if(archiveFilename) delete archiveFilename;
}
static void CloseGame(void) static void CloseGame(void)
{ {
@ -312,7 +319,7 @@ int NSFLoad(FCEUFILE *fp);
//char lastLoadedGameName [2048] = {0,}; // hack for movie WRAM clearing on record from poweron //char lastLoadedGameName [2048] = {0,}; // hack for movie WRAM clearing on record from poweron
FCEUGI *FCEUI_LoadGameVirtual(const char *name, const char *logicalname, int OverwriteVidMode) FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode)
{ {
//mbg merge 7/17/07 - why is this here //mbg merge 7/17/07 - why is this here
//#ifdef WIN32 //#ifdef WIN32
@ -325,10 +332,11 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, const char *logicalname, int Ove
char *ipsfn; char *ipsfn;
FCEU_printf("Loading %s...\n\n",name); FCEU_printf("Loading %s...\n\n",name);
GetFileBase(logicalname);
ipsfn=strdup(FCEU_MakeFName(FCEUMKF_IPS,0,0).c_str()); ipsfn=strdup(FCEU_MakeFName(FCEUMKF_IPS,0,0).c_str());
fp=FCEU_fopen(name,ipsfn,"rb",0); fp=FCEU_fopen(name,ipsfn,"rb",0);
GetFileBase(fp->filename.c_str());
free(ipsfn); free(ipsfn);
if(!fp) { if(!fp) {
@ -345,9 +353,12 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, const char *logicalname, int Ove
AutosaveStatus[2] = AutosaveStatus[3] = 0; AutosaveStatus[2] = AutosaveStatus[3] = 0;
CloseGame(); CloseGame();
GameInfo = new FCEUGI; GameInfo = new FCEUGI();
memset(GameInfo, 0, sizeof(FCEUGI)); memset(GameInfo, 0, sizeof(FCEUGI));
GameInfo->filename = strdup(fp->filename.c_str());
if(fp->archiveFilename != "") GameInfo->archiveFilename = strdup(fp->archiveFilename.c_str());
GameInfo->soundchan = 0; GameInfo->soundchan = 0;
GameInfo->soundrate = 0; GameInfo->soundrate = 0;
GameInfo->name=0; GameInfo->name=0;
@ -401,7 +412,7 @@ endlseq:
FCEUGI *FCEUI_LoadGame(const char *name, int OverwriteVidMode) FCEUGI *FCEUI_LoadGame(const char *name, int OverwriteVidMode)
{ {
return FCEUI_LoadGameVirtual(name,name,OverwriteVidMode); return FCEUI_LoadGameVirtual(name,OverwriteVidMode);
} }
@ -502,6 +513,9 @@ void UpdateAutosave(void);
///Skip may be passed in, if FRAMESKIP is #defined, to cause this to emulate more than one frame ///Skip may be passed in, if FRAMESKIP is #defined, to cause this to emulate more than one frame
void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int skip) void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int skip)
{ {
extern unsigned int LagCounter;
extern bool lagCounterDisplay;
extern bool lagFlag;
lagFlag = true; lagFlag = true;
int r,ssize; int r,ssize;

View File

@ -26,7 +26,9 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#ifndef WIN32
#include <zlib.h> #include <zlib.h>
#endif
#include "types.h" #include "types.h"
#include "file.h" #include "file.h"
@ -211,377 +213,162 @@ doret:
#define strcasecmp strcmp #define strcasecmp strcmp
#endif #endif
void FCEU_SplitArchiveFilename(std::string src, std::string& archive, std::string& file, std::string& fileToOpen)
{
size_t pipe = src.find_first_of('|');
if(pipe == std::string::npos)
{
archive = "";
file = src;
fileToOpen = src;
}
else
{
archive = src.substr(0,pipe);
file = src.substr(pipe+1);
fileToOpen = archive;
}
}
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)
{ {
FILE *ipsfile=0; FILE *ipsfile=0;
FCEUFILE *fceufp; FCEUFILE *fceufp=0;
void *t;
if(ipsfn && strchr(mode,'r')) bool read = (std::string)mode == "rb";
bool write = (std::string)mode == "wb";
if(read&&write || (!read&&!write))
{
FCEU_PrintError("invalid file open mode specified (only wb and rb are supported)");
return 0;
}
std::string archive,fname,fileToOpen;
FCEU_SplitArchiveFilename(path,archive,fname,fileToOpen);
//try to setup the ips file
if(ipsfn && read)
ipsfile=FCEUD_UTF8fopen(ipsfn,"rb"); ipsfile=FCEUD_UTF8fopen(ipsfn,"rb");
fceufp=(FCEUFILE *)malloc(sizeof(FCEUFILE)); if(read)
{ {
unzFile tz; ArchiveScanRecord asr = FCEUD_ScanArchive(fileToOpen);
if((tz=unzOpen(path))) // If it's not a zip file, use regular file handlers. if(asr.numFiles == 0)
// Assuming file type by extension usually works,
// but I don't like it. :)
{ {
if(unzGoToFirstFile(tz)==UNZ_OK) //if the archive contained no files, try to open it the old fashioned way
std::fstream* fp = FCEUD_UTF8_fstream(fileToOpen,mode);
if(!fp)
{ {
for(;;) return 0;
{
char tempu[512]; // Longer filenames might be possible, but I don't
// think people would name files that long in zip files...
unzGetCurrentFileInfo(tz,0,tempu,512,0,0,0,0);
tempu[511]=0;
if(strlen(tempu)>=4)
{
char *za=tempu+strlen(tempu)-4;
if(!ext)
{
if(!strcasecmp(za,".nes") || !strcasecmp(za,".fds") ||
!strcasecmp(za,".nsf") || !strcasecmp(za,".unf") ||
!strcasecmp(za,".nez"))
break;
} }
else if(!strcasecmp(za,ext)) fceufp = new FCEUFILE();
break; fceufp->filename = fileToOpen;
} fceufp->archiveIndex = -1;
if(strlen(tempu)>=5) fceufp->stream = (std::iostream*)fp;
{ FCEU_fseek(fceufp,0,SEEK_END);
if(!strcasecmp(tempu+strlen(tempu)-5,".unif")) fceufp->size = FCEU_ftell(fceufp);
break; FCEU_fseek(fceufp,0,SEEK_SET);
} return fceufp;
if(unzGoToNextFile(tz)!=UNZ_OK)
{
if(unzGoToFirstFile(tz)!=UNZ_OK) goto zpfail;
break;
}
}
if(unzOpenCurrentFile(tz)!=UNZ_OK)
goto zpfail;
} }
else else
{ {
zpfail: //open an archive file
free(fceufp); if(archive == "")
unzClose(tz); fceufp = FCEUD_OpenArchive(asr, fileToOpen, 0);
return 0; else
} fceufp = FCEUD_OpenArchive(asr, archive, &fname);
if(!(fceufp->fp=MakeMemWrap(tz,2))) return fceufp;
{
free(fceufp);
return(0);
}
fceufp->type=2;
if(ipsfile)
ApplyIPS(ipsfile,(MEMWRAP *)fceufp->fp);
return(fceufp);
} }
} }
if((t=FCEUD_UTF8fopen(path,"rb")))
{
uint32 magic;
magic=fgetc((FILE *)t);
magic|=fgetc((FILE *)t)<<8;
magic|=fgetc((FILE *)t)<<16;
if(magic!=0x088b1f) /* Not gzip... */
fclose((FILE *)t);
else /* Probably gzip */
{
int fd;
fd = dup(fileno( (FILE *)t));
fclose((FILE*)t); //mbg merge 7/17/06 - cast to FILE*
lseek(fd, 0, SEEK_SET);
if((t=gzdopen(fd,mode)))
{
fceufp->type=1;
fceufp->fp=t;
if(ipsfile)
{
fceufp->fp=MakeMemWrap(t,1);
gzclose(t);
if(fceufp->fp)
{
free(fceufp);
return(0);
}
fceufp->type=3;
ApplyIPS(ipsfile,(MEMWRAP *)fceufp->fp);
}
return(fceufp);
}
close(fd);
}
}
if((t=FCEUD_UTF8fopen(path,mode)))
{
fseek((FILE *)t,0,SEEK_SET);
fceufp->type=0;
fceufp->fp=t;
if(ipsfile)
{
if(!(fceufp->fp=MakeMemWrap(t,0)))
{
free(fceufp);
return(0);
}
fceufp->type=3;
ApplyIPS(ipsfile,(MEMWRAP *)fceufp->fp);
}
return(fceufp);
}
free(fceufp);
return 0; return 0;
} }
int FCEU_fclose(FCEUFILE *fp) int FCEU_fclose(FCEUFILE *fp)
{ {
if(fp->type==1) delete fp;
{
gzclose(fp->fp);
}
else if(fp->type>=2)
{
free(((MEMWRAP*)(fp->fp))->data);
free(fp->fp);
}
else
{
fclose((FILE *)fp->fp);
}
free(fp);
return 1; return 1;
} }
uint64 FCEU_fread(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp) uint64 FCEU_fread(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp)
{ {
if(fp->type==1) fp->stream->read((char*)ptr,size*nmemb);
{ uint32 read = fp->stream->gcount();
return gzread(fp->fp,ptr,size*nmemb); return read/size;
}
else if(fp->type>=2)
{
MEMWRAP *wz;
uint32 total=size*nmemb;
wz=(MEMWRAP*)fp->fp;
if(wz->location>=wz->size) return 0;
if((wz->location+total)>wz->size)
{
int ak=wz->size-wz->location;
memcpy((uint8*)ptr,wz->data+wz->location,ak);
wz->location=wz->size;
return(ak/size);
}
else
{
memcpy((uint8*)ptr,wz->data+wz->location,total);
wz->location+=total;
return nmemb;
}
}
else
{
return fread(ptr,size,nmemb,(FILE *)fp->fp);
}
} }
uint64 FCEU_fwrite(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp) uint64 FCEU_fwrite(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp)
{ {
if(fp->type==1) fp->stream->write((char*)ptr,size*nmemb);
{ //todo - how do we tell how many bytes we wrote?
return gzwrite(fp->fp,ptr,size*nmemb); return nmemb;
}
else if(fp->type>=2)
{
return 0;
}
else
return fwrite(ptr,size,nmemb,(FILE *)fp->fp);
} }
int FCEU_fseek(FCEUFILE *fp, long offset, int whence) int FCEU_fseek(FCEUFILE *fp, long offset, int whence)
{ {
if(fp->type==1) //if(fp->type==1)
{ //{
return( (gzseek(fp->fp,offset,whence)>0)?0:-1); // return( (gzseek(fp->fp,offset,whence)>0)?0:-1);
} //}
else if(fp->type>=2) //else if(fp->type>=2)
{ //{
MEMWRAP *wz; // MEMWRAP *wz;
wz=(MEMWRAP*)fp->fp; // wz=(MEMWRAP*)fp->fp;
switch(whence) // switch(whence)
{ // {
case SEEK_SET:if(offset>=(long)wz->size) //mbg merge 7/17/06 - added cast to long // case SEEK_SET:if(offset>=(long)wz->size) //mbg merge 7/17/06 - added cast to long
return(-1); // return(-1);
wz->location=offset;break; // wz->location=offset;break;
case SEEK_CUR:if(offset+wz->location>wz->size) // case SEEK_CUR:if(offset+wz->location>wz->size)
return (-1); // return (-1);
wz->location+=offset; // wz->location+=offset;
break; // break;
} // }
return 0; // return 0;
} //}
else //else
return fseek((FILE *)fp->fp,offset,whence); // return fseek((FILE *)fp->fp,offset,whence);
fp->stream->seekg(offset,(std::ios_base::seekdir)whence);
fp->stream->seekp(offset,(std::ios_base::seekdir)whence);
return FCEU_ftell(fp);
} }
uint64 FCEU_ftell(FCEUFILE *fp) uint64 FCEU_ftell(FCEUFILE *fp)
{ {
if(fp->type==1) if(fp->mode == FCEUFILE::READ)
{ return fp->stream->tellg();
return gztell(fp->fp);
}
else if(fp->type>=2)
{
return (((MEMWRAP *)(fp->fp))->location);
}
else else
return ftell((FILE *)fp->fp); return fp->stream->tellp();
}
void FCEU_autosave(FCEUFILE *fp)
{
if(fp->type==1)
{
gzrewind(fp->fp);
}
else if(fp->type>=2)
{
((MEMWRAP *)(fp->fp))->location=0;
}
else
//Autosave load
fseek((FILE*)fp->fp,0,SEEK_SET); //mbg merge 7/17/06 - added cast to FILE*
} }
int FCEU_read16le(uint16 *val, FCEUFILE *fp) int FCEU_read16le(uint16 *val, FCEUFILE *fp)
{ {
uint8 t[4]; //mbg merge 7/17/06 - changed size from 2 to 4 to avoid dangerous problem with uint32* poking return read16le(val,fp->stream);
if(fp->type>=1)
{
if(fp->type>=2)
{
MEMWRAP *wz;
wz=(MEMWRAP *)fp->fp;
if(wz->location+2>wz->size)
{return 0;}
*(uint32 *)t=*(uint32 *)(wz->data+wz->location);
wz->location+=2;
}
else if(fp->type==1)
if(gzread(fp->fp,&t,2)!=2) return(0);
return(1);
}
else
{
if(fread(t,1,2,(FILE *)fp->fp)!=2) return(0);
}
*val=t[0]|(t[1]<<8);
return(1);
} }
int FCEU_read32le(uint32 *Bufo, FCEUFILE *fp) int FCEU_read32le(uint32 *Bufo, FCEUFILE *fp)
{ {
if(fp->type>=1) return read32le(Bufo, fp->stream);
{
uint8 t[4];
#ifndef LSB_FIRST
uint8 x[4];
#endif
if(fp->type>=2)
{
MEMWRAP *wz;
wz=(MEMWRAP *)fp->fp;
if(wz->location+4>wz->size)
{return 0;}
*(uint32 *)t=*(uint32 *)(wz->data+wz->location);
wz->location+=4;
}
else if(fp->type==1)
gzread(fp->fp,&t,4);
#ifndef LSB_FIRST
x[0]=t[3];
x[1]=t[2];
x[2]=t[1];
x[3]=t[0];
*(uint32*)Bufo=*(uint32*)x;
#else
*(uint32*)Bufo=*(uint32*)t;
#endif
return 1;
}
else
{
return read32le(Bufo,(FILE *)fp->fp);
}
} }
int FCEU_fgetc(FCEUFILE *fp) int FCEU_fgetc(FCEUFILE *fp)
{ {
if(fp->type==1) return fp->stream->get();
return gzgetc(fp->fp);
else if(fp->type>=2)
{
MEMWRAP *wz;
wz=(MEMWRAP *)fp->fp;
if(wz->location<wz->size)
return wz->data[wz->location++];
return EOF;
}
else
return fgetc((FILE *)fp->fp);
} }
uint64 FCEU_fgetsize(FCEUFILE *fp) uint64 FCEU_fgetsize(FCEUFILE *fp)
{ {
if(fp->type==1) return fp->size;
{
int x,t;
t=gztell(fp->fp);
gzrewind(fp->fp);
for(x=0; gzgetc(fp->fp) != EOF; x++);
gzseek(fp->fp,t,SEEK_SET);
return(x);
}
else if(fp->type>=2)
return ((MEMWRAP*)(fp->fp))->size;
else
{
long t,r;
t=ftell((FILE *)fp->fp);
fseek((FILE *)fp->fp,0,SEEK_END);
r=ftell((FILE *)fp->fp);
fseek((FILE *)fp->fp,t,SEEK_SET);
return r;
}
} }
int FCEU_fisarchive(FCEUFILE *fp) int FCEU_fisarchive(FCEUFILE *fp)
{ {
if(fp->type==2) if(fp->archiveIndex==0) return 0;
return 1; else return 1;
return 0;
} }
std::string GetMfn() //Retrieves the movie filename from curMovieFilename (for adding to savestate and auto-save files) std::string GetMfn() //Retrieves the movie filename from curMovieFilename (for adding to savestate and auto-save files)
@ -619,7 +406,7 @@ void FCEUI_SetDirOverride(int which, char *n)
odirs[which] = n; odirs[which] = n;
} }
if(GameInfo) /* Rebuild cache of present states/movies. */ if(GameInfo) //Rebuild cache of present states/movies.
{ {
if(which==FCEUIOD_STATES) if(which==FCEUIOD_STATES)
{ {

View File

@ -2,11 +2,47 @@
#define _FCEU_FILE_H_ #define _FCEU_FILE_H_
#include <string> #include <string>
#include <iostream>
#include "types.h"
struct FCEUFILE {
//void *fp; // FILE* or ptr to ZIPWRAP
//uint32 type; // 0=normal file, 1=gzip, 2=zip
std::iostream *stream;
std::string filename;
std::string archiveFilename;
int archiveIndex;
int size;
FCEUFILE()
: stream(0)
{}
~FCEUFILE()
{
if(stream) delete stream;
}
enum {
READ, WRITE, READWRITE
} mode;
};
struct ArchiveScanRecord
{
ArchiveScanRecord()
: type(-1)
, numFiles(0)
{}
ArchiveScanRecord(int _type, int _numFiles)
{
type = _type;
numFiles = _numFiles;
}
int type;
int numFiles;
};
typedef struct {
void *fp; // FILE* or ptr to ZIPWRAP
uint32 type; // 0=normal file, 1=gzip, 2=zip
} FCEUFILE;
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 FCEU_fclose(FCEUFILE*); int FCEU_fclose(FCEUFILE*);
@ -14,7 +50,6 @@ 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*);
int FCEU_fseek(FCEUFILE*, long offset, int whence); int FCEU_fseek(FCEUFILE*, long offset, int whence);
uint64 FCEU_ftell(FCEUFILE*); uint64 FCEU_ftell(FCEUFILE*);
void FCEU_autosave(FCEUFILE*);
int FCEU_read32le(uint32 *Bufo, FCEUFILE*); int FCEU_read32le(uint32 *Bufo, FCEUFILE*);
int FCEU_read16le(uint16 *Bufo, FCEUFILE*); int FCEU_read16le(uint16 *Bufo, FCEUFILE*);
int FCEU_fgetc(FCEUFILE*); int FCEU_fgetc(FCEUFILE*);
@ -27,6 +62,7 @@ void GetFileBase(const char *f);
std::string FCEU_GetPath(int type); std::string FCEU_GetPath(int type);
std::string FCEU_MakePath(int type, const char* filebase); std::string FCEU_MakePath(int type, const char* filebase);
std::string FCEU_MakeFName(int type, int id1, char *cd1); std::string FCEU_MakeFName(int type, int id1, char *cd1);
void FCEU_SplitArchiveFilename(std::string src, std::string& archive, std::string& file, std::string& fileToOpen);
#define FCEUMKF_STATE 1 #define FCEUMKF_STATE 1
#define FCEUMKF_SNAP 2 #define FCEUMKF_SNAP 2

View File

@ -109,8 +109,11 @@ inline const char* ESIFC_Name(ESIFC esifc)
#include "utils/md5.h" #include "utils/md5.h"
typedef struct struct FCEUGI
{ {
FCEUGI();
~FCEUGI();
uint8 *name; //Game name, UTF8 encoding uint8 *name; //Game name, UTF8 encoding
int mappernum; int mappernum;
@ -125,5 +128,9 @@ typedef struct
//mbg 6/8/08 - ??? //mbg 6/8/08 - ???
int soundrate; //For Ogg Vorbis expansion sound wacky support. 0 for default. int soundrate; //For Ogg Vorbis expansion sound wacky support. 0 for default.
int soundchan; //Number of sound channels. int soundchan; //Number of sound channels.
} FCEUGI;
char* filename;
char* archiveFilename;
};
#endif #endif

View File

@ -75,9 +75,9 @@ extern INPUTCFC *FCEU_InitTopRider(void);
extern INPUTCFC *FCEU_InitBarcodeWorld(void); extern INPUTCFC *FCEU_InitBarcodeWorld(void);
//--------------- //---------------
extern unsigned int LagCounter; unsigned int LagCounter;
extern bool lagCounterDisplay; bool lagCounterDisplay;
extern bool lagFlag; bool lagFlag;
static uint8 joy_readbit[2]; static uint8 joy_readbit[2];
uint8 joy[4]={0,0,0,0}; //HACK - should be static but movie needs it uint8 joy[4]={0,0,0,0}; //HACK - should be static but movie needs it
static uint8 LastStrobe; static uint8 LastStrobe;

View File

@ -25,6 +25,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
//#include <unistd.h> //mbg merge 7/17/06 removed //#include <unistd.h> //mbg merge 7/17/06 removed
#include <zlib.h> #include <zlib.h>
#include "types.h" #include "types.h"

View File

@ -108,6 +108,19 @@ int read32le(uint32 *Bufo, FILE *fp)
return 1; return 1;
} }
int read16le(uint16 *Bufo, std::istream *is)
{
uint16 buf;
if(is->read((char*)&buf,2).gcount() != 2)
return 0;
#ifdef LSB_FIRST
*Bufo=buf;
#else
*Bufo = FCEU_de16lsb(&buf)
#endif
return 1;
}
///reads a little endian 64bit value from the specified file ///reads a little endian 64bit value from the specified file
int read64le(uint64 *Bufo, std::istream *is) int read64le(uint64 *Bufo, std::istream *is)
{ {

View File

@ -12,6 +12,8 @@ int write64le(uint64 b, std::ostream* os);
int read64le(uint64 *Bufo, std::istream *is); int read64le(uint64 *Bufo, std::istream *is);
int read32le(uint32 *Bufo, std::istream *is); int read32le(uint32 *Bufo, std::istream *is);
int read32le(uint32 *Bufo, FILE *fp); int read32le(uint32 *Bufo, FILE *fp);
int read16le(uint16 *Bufo, std::istream *is);
void FlipByteOrder(uint8 *src, uint32 count); void FlipByteOrder(uint8 *src, uint32 count);
void FCEU_en32lsb(uint8 *, uint32); void FCEU_en32lsb(uint8 *, uint32);

View File

@ -30,6 +30,17 @@ private:
public: public:
memory_streambuf(int _capacity)
: buf(new T[capacity=_capacity])
, myBuf(true)
, length(_capacity)
, ww(0)
, usevec(0)
{
sync();
}
memory_streambuf() memory_streambuf()
: buf(new T[capacity = 128]) : buf(new T[capacity = 128])
, myBuf(true) , myBuf(true)
@ -243,6 +254,11 @@ public:
: std::basic_iostream<char, std::char_traits<char> >(&streambuf) : std::basic_iostream<char, std::char_traits<char> >(&streambuf)
{} {}
memorystream(int size)
: std::basic_iostream<char, std::char_traits<char> >(&streambuf)
, streambuf(size)
{}
memorystream(char* usebuf, int buflength) memorystream(char* usebuf, int buflength)
: std::basic_iostream<char, std::char_traits<char> >(&streambuf) : std::basic_iostream<char, std::char_traits<char> >(&streambuf)
, streambuf(usebuf, buflength) , streambuf(usebuf, buflength)

View File

@ -1,3 +1,4 @@
del /s fceux.zip
cd ..\output cd ..\output
..\vc8\zip -X -9 -r ..\vc8\fceux.zip fceux.exe fceux.chm 7zxa.dll palettes ..\vc8\zip -X -9 -r ..\vc8\fceux.zip fceux.exe fceux.chm 7z.dll palettes
cd ..\vc8 cd ..\vc8

View File

@ -97,7 +97,7 @@
/> />
<Tool <Tool
Name="VCPostBuildEventTool" Name="VCPostBuildEventTool"
CommandLine="xcopy /y /d $(ProjectDir)\..\src\drivers\win\7zxa.dll $(OutDir)" CommandLine="xcopy /y /d $(ProjectDir)\..\src\drivers\win\7z.dll $(OutDir)"
/> />
</Configuration> </Configuration>
<Configuration <Configuration
@ -181,7 +181,7 @@
/> />
<Tool <Tool
Name="VCPostBuildEventTool" Name="VCPostBuildEventTool"
CommandLine="xcopy /d $(ProjectDir)\..\src\drivers\win\7zxa.dll $(OutDir)&#x0D;&#x0A;upx ..\output\fceux.exe" CommandLine="xcopy /d $(ProjectDir)\..\src\drivers\win\7z.dll $(OutDir)&#x0D;&#x0A;upx ..\output\fceux.exe&#x0D;&#x0A;"
/> />
</Configuration> </Configuration>
<Configuration <Configuration
@ -705,11 +705,11 @@
Name="win" Name="win"
> >
<File <File
RelativePath="..\src\drivers\win\7zip.cpp" RelativePath="..\src\drivers\win\archive.cpp"
> >
</File> </File>
<File <File
RelativePath="..\src\drivers\win\7zip.h" RelativePath="..\src\drivers\win\archive.h"
> >
</File> </File>
<File <File