diff --git a/src/driver.h b/src/driver.h index a88cdd5d..4bdf6541 100644 --- a/src/driver.h +++ b/src/driver.h @@ -7,6 +7,7 @@ #include "types.h" #include "git.h" +#include "file.h" 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); } @@ -93,8 +94,8 @@ void FCEUI_GetRenderPlanes(bool& sprites, bool& bg); FCEUGI *FCEUI_LoadGame(const char *name, int OverwriteVidMode); //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 -FCEUGI *FCEUI_LoadGameVirtual(const char *name, const char *logicalname, int OverwriteVidMode); +//name is the logical path to open; archiveFilename is the archive which contains name +FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode); //general purpose emulator initialization. returns true if successful bool FCEUI_Initialize(); @@ -318,6 +319,11 @@ enum EFCEUI //checks whether an EFCEUI is valid right now 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 extern "C" diff --git a/src/drivers/win/7z.dll b/src/drivers/win/7z.dll new file mode 100644 index 00000000..b56149ab Binary files /dev/null and b/src/drivers/win/7z.dll differ diff --git a/src/drivers/win/7zip.h b/src/drivers/win/7zip.h deleted file mode 100644 index a0a1d6fe..00000000 --- a/src/drivers/win/7zip.h +++ /dev/null @@ -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); \ No newline at end of file diff --git a/src/drivers/win/7zxa.dll b/src/drivers/win/7zxa.dll deleted file mode 100644 index 1ae72528..00000000 Binary files a/src/drivers/win/7zxa.dll and /dev/null differ diff --git a/src/drivers/win/7zip.cpp b/src/drivers/win/archive.cpp similarity index 61% rename from src/drivers/win/7zip.cpp rename to src/drivers/win/archive.cpp index 9ceec129..c7c506ce 100644 --- a/src/drivers/win/7zip.cpp +++ b/src/drivers/win/archive.cpp @@ -8,11 +8,14 @@ #include #include "7zip/IArchive.h" +#include "file.h" +#include "utils/memorystream.h" +#include "utils/guid.h" #include "driver.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 { @@ -269,7 +272,7 @@ class LibRef public: HMODULE hmod; LibRef(const char* fname) { - hmod = LoadLibrary("7zxa.dll"); + hmod = LoadLibrary(fname); } ~LibRef() { if(hmod) @@ -327,24 +330,135 @@ static BOOL CALLBACK ArchiveFileSelectorCallback(HWND hwndDlg, UINT uMsg, WPARAM 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 signature; + GUID guid; +}; + +typedef std::vector 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(&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) { - MessageBox(hParent,"Could not locate 7zxa.dll","Failure launching 7z archive browser",0); - return; + MessageBox(hAppWnd,"Could not locate 7z.dll","Failure launching archive browser",0); + return 0; } typedef UINT32 (WINAPI *CreateObjectFunc)(const GUID*,const GUID*,void**); CreateObjectFunc CreateObject = (CreateObjectFunc)GetProcAddress(libref.hmod,"CreateObject"); if(!CreateObject) { - MessageBox(hParent,"7zxa.dll was invalid","Failure launching 7z archive browser",0); - return; + MessageBox(hAppWnd,"7z.dll was invalid","Failure launching archive browser",0); + return 0; } + 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); if (SUCCEEDED(object->Open(&ifs,0,0))) @@ -402,24 +516,29 @@ void do7zip(HWND hParent, std::string fname, std::string* innerFilename) } else //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) { FileSelectorContext::Item& item = fileSelectorContext.items[ret]; - std::vector data(item.size); - OutStream outStream( item.index, &data[0], item.size); + 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))) { - char* tempname = tmpnam(0); - FILE* outf = fopen(tempname,"wb"); - fwrite(&data[0],1,item.size,outf); - fclose(outf); - void ALoad(char *nameo,char* actualfile,char* archiveFile); - ALoad((char*)item.name.c_str(),tempname,(char*)fname.c_str()); - - } //if we extracted the file correctly + //if we extracted the file correctly + fp = new FCEUFILE(); + fp->archiveFilename = fname; + fp->filename = fileSelectorContext.items[ret].name; + fp->archiveIndex = ret; + fp->mode = FCEUFILE::READ; + fp->size = fileSelectorContext.items[ret].size; + fp->stream = ms; + } + else + { + delete ms; + } } //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 object->Release(); } + + return fp; } \ No newline at end of file diff --git a/src/drivers/win/archive.h b/src/drivers/win/archive.h new file mode 100644 index 00000000..92d07f7b --- /dev/null +++ b/src/drivers/win/archive.h @@ -0,0 +1,6 @@ +#ifndef _ARCHIVE_H_ +#define _ARCHIVE_H_ + +void initArchiveSystem(); + +#endif \ No newline at end of file diff --git a/src/drivers/win/main.cpp b/src/drivers/win/main.cpp index 98af18e4..ae4e7884 100644 --- a/src/drivers/win/main.cpp +++ b/src/drivers/win/main.cpp @@ -39,6 +39,7 @@ #include "../../state.h" #include "../../debug.h" #include "../../movie.h" +#include "archive.h" #include "input.h" #include "netplay.h" #include "memwatch.h" @@ -555,6 +556,8 @@ int main(int argc,char *argv[]) { char *t; + initArchiveSystem(); + if(timeBeginPeriod(1) != TIMERR_NOERROR) { AddLogText("Error setting timer granularity to 1ms.", DO_ADD_NEWLINE); diff --git a/src/drivers/win/res.rc b/src/drivers/win/res.rc index f203cbc4..4d8b3378 100644 --- a/src/drivers/win/res.rc +++ b/src/drivers/win/res.rc @@ -1392,14 +1392,14 @@ BEGIN EDITTEXT IDC_PPUVIEW_SCANLINE,72,176,27,12 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 CAPTION "Choose File From Archive" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "OK",IDOK,146,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 TEXTHOOKER DIALOGEX 0, 0, 456, 327 @@ -1596,7 +1596,7 @@ BEGIN BOTTOMMARGIN, 66 END - "7ZIPARCHIVEDIALOG", DIALOG + "ARCHIVECHOOSERDIALOG", DIALOG BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 258 diff --git a/src/drivers/win/window.cpp b/src/drivers/win/window.cpp index 0390b015..00073982 100644 --- a/src/drivers/win/window.cpp +++ b/src/drivers/win/window.cpp @@ -49,7 +49,6 @@ #include "joystick.h" #include "oldmovie.h" #include "movie.h" -#include "7zip.h" #include "texthook.h" #include "guiconfig.h" #include "timing.h" @@ -149,13 +148,7 @@ int GetCheckedAutoFireOffset() // 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) { @@ -401,12 +394,10 @@ void UpdateRMenu(HMENU menu, char **strs, unsigned int mitem, unsigned int basei continue; std::string tmp = strs[x]; - if(tmp[0] == '|') - { - std::string archiveName, fileName; - SplitRecentArchiveFilename(tmp,archiveName,fileName); + std::string archiveName, fileName, fileToOpen; + FCEU_SplitArchiveFilename(tmp,archiveName,fileName,fileToOpen); + if(archiveName != "") tmp = archiveName + " <" + fileName + ">"; - } //clamp this string to 128 chars if(tmp.size()>128) @@ -567,11 +558,9 @@ void FCEUD_HideMenuToggle(void) ToggleHideMenu(); } -void ALoad(char *nameo,char* actualfile,char* archiveFile) +void ALoad(char *nameo, char* innerFilename) { - bool isvirtual = (actualfile!=0); - if(!isvirtual) actualfile = nameo; - if(FCEUI_LoadGameVirtual(actualfile, nameo, 1)) + if(FCEUI_LoadGameVirtual(nameo, 1)) { pal_emulation = FCEUI_GetCurrentVidSystem(0, 0); @@ -579,10 +568,9 @@ void ALoad(char *nameo,char* actualfile,char* archiveFile) SetMainWindowStuff(); - //todo-add recent files from archives somehow std::string recentFileName = nameo; - if(archiveFile) - recentFileName = (std::string)"|" + archiveFile + "|" + nameo; + if(GameInfo->archiveFilename) + recentFileName = (std::string)GameInfo->archiveFilename + "|" + GameInfo->filename; else recentFileName = nameo; @@ -633,17 +621,7 @@ void LoadNewGamey(HWND hParent, const char *initialdir) // Show the Open File dialog if(GetOpenFileName(&ofn)) { - //if the user selected a 7zip file, then we have some work to do.. - //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); - } + ALoad(nameo); } } @@ -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 { DragQueryFile((HDROP)wParam,0,ftmp,len); //mbg merge 7/17/06 changed (HANDLE) to (HDROP) - ALoad(ftmp,0); + ALoad(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]; if(fname) { - if(fname[0] == '|') - { - std::string fnamestr = fname, archiveName, fileName; - SplitRecentArchiveFilename(fnamestr,archiveName,fileName); - do7zip(hWnd,archiveName,&fileName); - } - else - ALoad(fname,0); + ALoad(fname); } } switch(LOWORD(wParam)) diff --git a/src/drivers/win/window.h b/src/drivers/win/window.h index 83cc8b7e..ff8f4371 100644 --- a/src/drivers/win/window.h +++ b/src/drivers/win/window.h @@ -23,7 +23,7 @@ void ByebyeWindow(); void DoTimingConfigFix(); int CreateMainWindow(); 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); int BrowseForFolder(HWND hParent, const char *htext, char *buf); void UpdateCheckedMenuItems(); diff --git a/src/fceu.cpp b/src/fceu.cpp index e92c274d..09183ed7 100644 --- a/src/fceu.cpp +++ b/src/fceu.cpp @@ -59,9 +59,16 @@ 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 -bool lagCounterDisplay = false; -bool lagFlag = true; +FCEUGI::FCEUGI() + : filename(0) + , archiveFilename(0) +{} + +FCEUGI::~FCEUGI() +{ + if(filename) delete filename; + if(archiveFilename) delete archiveFilename; +} 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 -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 //#ifdef WIN32 @@ -325,10 +332,11 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, const char *logicalname, int Ove char *ipsfn; FCEU_printf("Loading %s...\n\n",name); - GetFileBase(logicalname); ipsfn=strdup(FCEU_MakeFName(FCEUMKF_IPS,0,0).c_str()); fp=FCEU_fopen(name,ipsfn,"rb",0); + GetFileBase(fp->filename.c_str()); + free(ipsfn); if(!fp) { @@ -345,9 +353,12 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, const char *logicalname, int Ove AutosaveStatus[2] = AutosaveStatus[3] = 0; CloseGame(); - GameInfo = new FCEUGI; + GameInfo = new 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->soundrate = 0; GameInfo->name=0; @@ -401,7 +412,7 @@ endlseq: 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 void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int skip) { + extern unsigned int LagCounter; + extern bool lagCounterDisplay; + extern bool lagFlag; lagFlag = true; int r,ssize; diff --git a/src/file.cpp b/src/file.cpp index 51c5fafd..2bab4746 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -26,7 +26,9 @@ #include #include +#ifndef WIN32 #include +#endif #include "types.h" #include "file.h" @@ -211,377 +213,162 @@ doret: #define strcasecmp strcmp #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) { FILE *ipsfile=0; - FCEUFILE *fceufp; - void *t; + FCEUFILE *fceufp=0; - 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"); - fceufp=(FCEUFILE *)malloc(sizeof(FCEUFILE)); - + if(read) { - unzFile tz; - if((tz=unzOpen(path))) // If it's not a zip file, use regular file handlers. - // Assuming file type by extension usually works, - // but I don't like it. :) + ArchiveScanRecord asr = FCEUD_ScanArchive(fileToOpen); + if(asr.numFiles == 0) { - 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(;;) - { - 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)) - break; - } - if(strlen(tempu)>=5) - { - if(!strcasecmp(tempu+strlen(tempu)-5,".unif")) - break; - } - if(unzGoToNextFile(tz)!=UNZ_OK) - { - if(unzGoToFirstFile(tz)!=UNZ_OK) goto zpfail; - break; - } - } - if(unzOpenCurrentFile(tz)!=UNZ_OK) - goto zpfail; - } - else - { -zpfail: - free(fceufp); - unzClose(tz); return 0; } - if(!(fceufp->fp=MakeMemWrap(tz,2))) - { - free(fceufp); - return(0); - } - fceufp->type=2; - if(ipsfile) - ApplyIPS(ipsfile,(MEMWRAP *)fceufp->fp); - return(fceufp); + fceufp = new FCEUFILE(); + fceufp->filename = fileToOpen; + fceufp->archiveIndex = -1; + fceufp->stream = (std::iostream*)fp; + FCEU_fseek(fceufp,0,SEEK_END); + fceufp->size = FCEU_ftell(fceufp); + FCEU_fseek(fceufp,0,SEEK_SET); + 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 */ + else { - 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); + //open an archive file + if(archive == "") + fceufp = FCEUD_OpenArchive(asr, fileToOpen, 0); + else + fceufp = FCEUD_OpenArchive(asr, archive, &fname); + return fceufp; } - } - 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; } int FCEU_fclose(FCEUFILE *fp) { - if(fp->type==1) - { - gzclose(fp->fp); - } - else if(fp->type>=2) - { - free(((MEMWRAP*)(fp->fp))->data); - free(fp->fp); - } - else - { - fclose((FILE *)fp->fp); - } - free(fp); + delete fp; return 1; } uint64 FCEU_fread(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp) { - if(fp->type==1) - { - return gzread(fp->fp,ptr,size*nmemb); - } - 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); - } + fp->stream->read((char*)ptr,size*nmemb); + uint32 read = fp->stream->gcount(); + return read/size; } uint64 FCEU_fwrite(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp) { - if(fp->type==1) - { - return gzwrite(fp->fp,ptr,size*nmemb); - } - else if(fp->type>=2) - { - return 0; - } - else - return fwrite(ptr,size,nmemb,(FILE *)fp->fp); + fp->stream->write((char*)ptr,size*nmemb); + //todo - how do we tell how many bytes we wrote? + return nmemb; } int FCEU_fseek(FCEUFILE *fp, long offset, int whence) { - if(fp->type==1) - { - return( (gzseek(fp->fp,offset,whence)>0)?0:-1); - } - else if(fp->type>=2) - { - MEMWRAP *wz; - wz=(MEMWRAP*)fp->fp; + //if(fp->type==1) + //{ + // return( (gzseek(fp->fp,offset,whence)>0)?0:-1); + //} + //else if(fp->type>=2) + //{ + // MEMWRAP *wz; + // wz=(MEMWRAP*)fp->fp; - switch(whence) - { - case SEEK_SET:if(offset>=(long)wz->size) //mbg merge 7/17/06 - added cast to long - return(-1); - wz->location=offset;break; - case SEEK_CUR:if(offset+wz->location>wz->size) - return (-1); - wz->location+=offset; - break; - } - return 0; - } - else - return fseek((FILE *)fp->fp,offset,whence); + // switch(whence) + // { + // case SEEK_SET:if(offset>=(long)wz->size) //mbg merge 7/17/06 - added cast to long + // return(-1); + // wz->location=offset;break; + // case SEEK_CUR:if(offset+wz->location>wz->size) + // return (-1); + // wz->location+=offset; + // break; + // } + // return 0; + //} + //else + // 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) { - if(fp->type==1) - { - return gztell(fp->fp); - } - else if(fp->type>=2) - { - return (((MEMWRAP *)(fp->fp))->location); - } + if(fp->mode == FCEUFILE::READ) + return fp->stream->tellg(); else - return ftell((FILE *)fp->fp); -} - -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* + return fp->stream->tellp(); } 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 - - 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); + return read16le(val,fp->stream); } int FCEU_read32le(uint32 *Bufo, FCEUFILE *fp) { - if(fp->type>=1) - { - 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); - } + return read32le(Bufo, fp->stream); } int FCEU_fgetc(FCEUFILE *fp) { - if(fp->type==1) - return gzgetc(fp->fp); - else if(fp->type>=2) - { - MEMWRAP *wz; - wz=(MEMWRAP *)fp->fp; - if(wz->locationsize) - return wz->data[wz->location++]; - return EOF; - } - else - return fgetc((FILE *)fp->fp); + return fp->stream->get(); } uint64 FCEU_fgetsize(FCEUFILE *fp) { - if(fp->type==1) - { - 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; - } + return fp->size; } int FCEU_fisarchive(FCEUFILE *fp) { - if(fp->type==2) - return 1; - return 0; + if(fp->archiveIndex==0) return 0; + else return 1; } 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; } - if(GameInfo) /* Rebuild cache of present states/movies. */ + if(GameInfo) //Rebuild cache of present states/movies. { if(which==FCEUIOD_STATES) { diff --git a/src/file.h b/src/file.h index afa33355..a7e43d6c 100644 --- a/src/file.h +++ b/src/file.h @@ -2,11 +2,47 @@ #define _FCEU_FILE_H_ #include +#include +#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); 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*); int FCEU_fseek(FCEUFILE*, long offset, int whence); uint64 FCEU_ftell(FCEUFILE*); -void FCEU_autosave(FCEUFILE*); int FCEU_read32le(uint32 *Bufo, FCEUFILE*); int FCEU_read16le(uint16 *Bufo, FCEUFILE*); int FCEU_fgetc(FCEUFILE*); @@ -27,6 +62,7 @@ void GetFileBase(const char *f); std::string FCEU_GetPath(int type); std::string FCEU_MakePath(int type, const char* filebase); 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_SNAP 2 diff --git a/src/git.h b/src/git.h index 33e879da..0a79e6d3 100644 --- a/src/git.h +++ b/src/git.h @@ -109,8 +109,11 @@ inline const char* ESIFC_Name(ESIFC esifc) #include "utils/md5.h" -typedef struct +struct FCEUGI { + FCEUGI(); + ~FCEUGI(); + uint8 *name; //Game name, UTF8 encoding int mappernum; @@ -125,5 +128,9 @@ typedef struct //mbg 6/8/08 - ??? int soundrate; //For Ogg Vorbis expansion sound wacky support. 0 for default. int soundchan; //Number of sound channels. -} FCEUGI; + + char* filename; + char* archiveFilename; +}; + #endif diff --git a/src/input.cpp b/src/input.cpp index a9f6e68b..99926312 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -75,9 +75,9 @@ extern INPUTCFC *FCEU_InitTopRider(void); extern INPUTCFC *FCEU_InitBarcodeWorld(void); //--------------- -extern unsigned int LagCounter; -extern bool lagCounterDisplay; -extern bool lagFlag; +unsigned int LagCounter; +bool lagCounterDisplay; +bool lagFlag; static uint8 joy_readbit[2]; uint8 joy[4]={0,0,0,0}; //HACK - should be static but movie needs it static uint8 LastStrobe; diff --git a/src/netplay.cpp b/src/netplay.cpp index f47411e1..e39744d7 100644 --- a/src/netplay.cpp +++ b/src/netplay.cpp @@ -25,6 +25,7 @@ #include #include //#include //mbg merge 7/17/06 removed + #include #include "types.h" diff --git a/src/utils/endian.cpp b/src/utils/endian.cpp index 00b91372..e63c9a49 100644 --- a/src/utils/endian.cpp +++ b/src/utils/endian.cpp @@ -108,6 +108,19 @@ int read32le(uint32 *Bufo, FILE *fp) 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 int read64le(uint64 *Bufo, std::istream *is) { diff --git a/src/utils/endian.h b/src/utils/endian.h index a6bf64e7..74537281 100644 --- a/src/utils/endian.h +++ b/src/utils/endian.h @@ -12,6 +12,8 @@ int write64le(uint64 b, std::ostream* os); int read64le(uint64 *Bufo, std::istream *is); int read32le(uint32 *Bufo, std::istream *is); int read32le(uint32 *Bufo, FILE *fp); +int read16le(uint16 *Bufo, std::istream *is); + void FlipByteOrder(uint8 *src, uint32 count); void FCEU_en32lsb(uint8 *, uint32); diff --git a/src/utils/memorystream.h b/src/utils/memorystream.h index f0aa949a..40d5d69c 100644 --- a/src/utils/memorystream.h +++ b/src/utils/memorystream.h @@ -30,6 +30,17 @@ private: public: + memory_streambuf(int _capacity) + : buf(new T[capacity=_capacity]) + , myBuf(true) + , length(_capacity) + , ww(0) + , usevec(0) + { + sync(); + } + + memory_streambuf() : buf(new T[capacity = 128]) , myBuf(true) @@ -243,6 +254,11 @@ public: : std::basic_iostream >(&streambuf) {} + memorystream(int size) + : std::basic_iostream >(&streambuf) + , streambuf(size) + {} + memorystream(char* usebuf, int buflength) : std::basic_iostream >(&streambuf) , streambuf(usebuf, buflength) diff --git a/vc8/archive.bat b/vc8/archive.bat index 70decc27..726862f2 100644 --- a/vc8/archive.bat +++ b/vc8/archive.bat @@ -1,3 +1,4 @@ +del /s fceux.zip 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 \ No newline at end of file diff --git a/vc8/fceux.vcproj b/vc8/fceux.vcproj index 8c9b699f..291f53cf 100644 --- a/vc8/fceux.vcproj +++ b/vc8/fceux.vcproj @@ -97,7 +97,7 @@ />