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 "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"

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 "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<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) {
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<char> 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;
}

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 "../../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);

View File

@ -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

View File

@ -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))

View File

@ -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();

View File

@ -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;

View File

@ -26,7 +26,9 @@
#include <sys/types.h>
#include <sys/stat.h>
#ifndef WIN32
#include <zlib.h>
#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->location<wz->size)
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)
{

View File

@ -2,11 +2,47 @@
#define _FCEU_FILE_H_
#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);
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

View File

@ -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

View File

@ -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;

View File

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

View File

@ -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)
{

View File

@ -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);

View File

@ -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<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)
: std::basic_iostream<char, std::char_traits<char> >(&streambuf)
, streambuf(usebuf, buflength)

View File

@ -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

View File

@ -97,7 +97,7 @@
/>
<Tool
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
@ -181,7 +181,7 @@
/>
<Tool
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
@ -705,11 +705,11 @@
Name="win"
>
<File
RelativePath="..\src\drivers\win\7zip.cpp"
RelativePath="..\src\drivers\win\archive.cpp"
>
</File>
<File
RelativePath="..\src\drivers\win\7zip.h"
RelativePath="..\src\drivers\win\archive.h"
>
</File>
<File