From 4e66aaef9c4e252e9a9ad57ed10df8b673a55a74 Mon Sep 17 00:00:00 2001 From: zeromus Date: Mon, 17 May 2010 21:02:38 +0000 Subject: [PATCH] replace most of the crappy iostream stuff with EMUFILE --- src/driver.h | 4 +- src/drivers/win/archive.cpp | 31 +- src/drivers/win/main.cpp | 18 +- src/drivers/win/tasedit.cpp | 3 +- src/drivers/win/taseditlib/taseditproj.cpp | 22 +- src/drivers/win/window.cpp | 4 +- src/emufile.cpp | 2 +- src/emufile.h | 35 +- src/file.cpp | 60 +-- src/file.h | 21 +- src/lua-engine.cpp | 10 +- src/movie.cpp | 207 ++++---- src/movie.h | 30 +- src/state.cpp | 89 ++-- src/state.h | 4 +- src/utils/endian.cpp | 117 +++++ src/utils/endian.h | 85 +++- src/utils/memorystream.h | 302 ------------ src/utils/xstring.h | 51 ++ vc/vc10_fceux.vcxproj | 1 - vc/vc8_fceux.sln | 6 + vc/vc8_fceux.vcproj | 528 +++++++++++++++++++++ vc/vc9_fceux.vcproj | 204 ++++---- 23 files changed, 1141 insertions(+), 693 deletions(-) delete mode 100644 src/utils/memorystream.h diff --git a/src/driver.h b/src/driver.h index 4fe6af38..a5b6f881 100644 --- a/src/driver.h +++ b/src/driver.h @@ -11,8 +11,8 @@ 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); } -std::fstream* FCEUD_UTF8_fstream(const char *n, const char *m); -inline std::fstream* FCEUD_UTF8_fstream(const std::string &n, const char *m) { return FCEUD_UTF8_fstream(n.c_str(),m); } +EMUFILE_FILE* FCEUD_UTF8_fstream(const char *n, const char *m); +inline EMUFILE_FILE* FCEUD_UTF8_fstream(const std::string &n, const char *m) { return FCEUD_UTF8_fstream(n.c_str(),m); } FCEUFILE* FCEUD_OpenArchiveIndex(ArchiveScanRecord& asr, std::string& fname, int innerIndex); FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::string* innerFilename); ArchiveScanRecord FCEUD_ScanArchive(std::string fname); diff --git a/src/drivers/win/archive.cpp b/src/drivers/win/archive.cpp index 108d252d..873e655c 100644 --- a/src/drivers/win/archive.cpp +++ b/src/drivers/win/archive.cpp @@ -9,7 +9,6 @@ #include "7zip/IArchive.h" #include "file.h" -#include "utils/memorystream.h" #include "utils/guid.h" #include "driver.h" @@ -203,7 +202,7 @@ public: if(inf) delete inf; } - std::fstream* inf; + EMUFILE_FILE* inf; InFileStream(std::string fname) : inf(0) @@ -211,9 +210,8 @@ public: inf = FCEUD_UTF8_fstream(fname,"rb"); if(inf) { - inf->seekg(0,std::ios::end); - size = inf->tellg(); - inf->seekg(0,std::ios::beg); + size = inf->size(); + inf->fseek(0,SEEK_SET); } } @@ -223,8 +221,7 @@ public: if (data != NULL || length == 0) { - inf->read((char*)data,length); - length = inf->gcount(); + length = inf->fread((char*)data,length); //do we need to do //return E_FAIL; @@ -246,17 +243,17 @@ public: if (origin < 3) { - std::ios::seekdir offtype; + UInt32 offtype; switch(origin) { - case 0: offtype = std::ios::beg; break; - case 1: offtype = std::ios::cur; break; - case 2: offtype = std::ios::end; break; + case 0: offtype = SEEK_SET; break; + case 1: offtype = SEEK_CUR; break; + case 2: offtype = SEEK_END; break; default: return E_INVALIDARG; } - inf->seekg(offset,offtype); - origin = inf->tellg(); + inf->fseek(offset,offtype); + origin = inf->ftell(); if (pos) *pos = origin; @@ -409,18 +406,18 @@ ArchiveScanRecord FCEUD_ScanArchive(std::string fname) } //check the file against the signatures - std::fstream* inf = FCEUD_UTF8_fstream(fname,"rb"); + EMUFILE* inf = FCEUD_UTF8_fstream(fname,"rb"); if(!inf) return ArchiveScanRecord(); int matchingFormat = -1; for(uint32 i=0;i<(int)formatRecords.size();i++) { - inf->seekg(0); + inf->fseek(0,SEEK_SET); int size = formatRecords[i].signature.size(); if(size==0) continue; //WHY?? char* temp = new char[size]; - inf->read((char*)temp,size); + inf->fread((char*)temp,size); if(!memcmp(&formatRecords[i].signature[0],temp,size)) { delete[] temp; @@ -542,7 +539,7 @@ static FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, s if(ret != LB_ERR) { FCEUARCHIVEFILEINFO_ITEM& item = (*currFileSelectorContext)[ret]; - memorystream* ms = new memorystream(item.size); + EMUFILE_MEMORY* ms = new EMUFILE_MEMORY(item.size); OutStream outStream( item.index, ms->buf(), item.size); const uint32 indices[1] = {item.index}; HRESULT hr = object->Extract(indices,1,0,&outStream); diff --git a/src/drivers/win/main.cpp b/src/drivers/win/main.cpp index e934583f..11472449 100644 --- a/src/drivers/win/main.cpp +++ b/src/drivers/win/main.cpp @@ -920,28 +920,14 @@ static void FCEUD_MakePathDirs(const char *fname) } while(1); } -std::fstream* FCEUD_UTF8_fstream(const char *n, const char *m) +EMUFILE_FILE* FCEUD_UTF8_fstream(const char *n, const char *m) { if(strchr(m, 'w') || strchr(m, '+')) { FCEUD_MakePathDirs(n); } - std::ios_base::openmode mode = std::ios_base::binary; - if(!strcmp(m,"r") || !strcmp(m,"rb")) - mode |= std::ios_base::in; - else if(!strcmp(m,"w") || !strcmp(m,"wb")) - mode |= std::ios_base::out | std::ios_base::trunc; - else if(!strcmp(m,"a") || !strcmp(m,"ab")) - mode |= std::ios_base::out | std::ios_base::app; - else if(!strcmp(m,"r+") || !strcmp(m,"r+b")) - mode |= std::ios_base::in | std::ios_base::out; - else if(!strcmp(m,"w+") || !strcmp(m,"w+b")) - mode |= std::ios_base::in | std::ios_base::out | std::ios_base::trunc; - else if(!strcmp(m,"a+") || !strcmp(m,"a+b")) - mode |= std::ios_base::in | std::ios_base::out | std::ios_base::app; - - std::fstream *fs = new std::fstream(n,mode); + EMUFILE_FILE *fs = new EMUFILE_FILE(n,m); if(!fs->is_open()) { delete fs; return 0; diff --git a/src/drivers/win/tasedit.cpp b/src/drivers/win/tasedit.cpp index 3dc1bfe3..0d1972e1 100644 --- a/src/drivers/win/tasedit.cpp +++ b/src/drivers/win/tasedit.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "common.h" #include "tasedit.h" @@ -951,7 +952,7 @@ static void Export() ofn.lpstrInitialDir=initdir.c_str(); if(GetSaveFileName(&ofn)) { - fstream* osRecordingMovie = FCEUD_UTF8_fstream(fname, "wb"); + EMUFILE* osRecordingMovie = FCEUD_UTF8_fstream(fname, "wb"); currMovieData.dump(osRecordingMovie,false); delete osRecordingMovie; osRecordingMovie = 0; diff --git a/src/drivers/win/taseditlib/taseditproj.cpp b/src/drivers/win/taseditlib/taseditproj.cpp index b52eecf4..a0e43275 100644 --- a/src/drivers/win/taseditlib/taseditproj.cpp +++ b/src/drivers/win/taseditlib/taseditproj.cpp @@ -17,7 +17,7 @@ #include #include #include - +#include "../main.h" #include "taseditproj.h" #include "movie.h" @@ -60,22 +60,21 @@ bool TASEDIT_PROJECT::SaveProject() { std::string PFN = GetProjectFile(); const char* filename = PFN.c_str(); - std::ofstream ofs; + EMUFILE_FILE* ofs = FCEUD_UTF8_fstream(filename,"wb"); //ofs << GetProjectName() << std::endl; //ofs << GetFM2Name() << std::endl; - ofs.open(filename, std::ios_base::binary); - currMovieData.dump(&ofs, true); - ofs.put('\0'); // TODO: Add main branch name. - currMovieData.dumpGreenzone(&ofs, true); + currMovieData.dump(ofs, true); + ofs->fputc('\0'); // TODO: Add main branch name. + currMovieData.dumpGreenzone(ofs, true); - ofs.close(); + delete ofs; changed=false; return true; } -extern bool LoadFM2(MovieData& movieData, std::istream* fp, int size, bool stopAfterHeader); +extern bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader); bool TASEDIT_PROJECT::LoadProject(std::string PFN) @@ -83,22 +82,19 @@ bool TASEDIT_PROJECT::LoadProject(std::string PFN) const char* filename = PFN.c_str(); SetProjectName(PFN); - std::ifstream ifs; - ifs.open(filename, std::ios_base::binary); + EMUFILE_FILE ifs(filename, "rb"); LoadFM2(currMovieData, &ifs, INT_MAX, false); LoadSubtitles(currMovieData); char branchname; - ifs.get(branchname); // TODO: Add main branch name. + branchname = ifs.fgetc(); // TODO: Add main branch name. currMovieData.loadGreenzone(&ifs, true); poweron(true); currFrameCounter = currMovieData.greenZoneCount; currMovieData.TryDumpIncremental(); - ifs.close(); - changed=false; return true; } diff --git a/src/drivers/win/window.cpp b/src/drivers/win/window.cpp index 90e7243b..b5a9b8dd 100644 --- a/src/drivers/win/window.cpp +++ b/src/drivers/win/window.cpp @@ -287,7 +287,7 @@ static void ConvertFCM(HWND hwndOwner) if(result==FCM_CONVERTRESULT_SUCCESS) { okcount++; - std::fstream* outf = FCEUD_UTF8_fstream(outname, "wb"); + EMUFILE_FILE* outf = FCEUD_UTF8_fstream(outname, "wb"); md.dump(outf,false); delete outf; } else { @@ -1406,7 +1406,7 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) EFCM_CONVERTRESULT result = convert_fcm(md, fileDropped.c_str()); if(result==FCM_CONVERTRESULT_SUCCESS) { - std::fstream* outf = FCEUD_UTF8_fstream(outname, "wb"); + EMUFILE* outf = FCEUD_UTF8_fstream(outname, "wb"); md.dump(outf,false); delete outf; if (!GameInfo) //If no game is loaded, load the Open Game dialog diff --git a/src/emufile.cpp b/src/emufile.cpp index d50674d8..7068220a 100644 --- a/src/emufile.cpp +++ b/src/emufile.cpp @@ -1,4 +1,4 @@ -#include "types-des.h" +#include "types.h" #include "emufile.h" #include diff --git a/src/emufile.h b/src/emufile.h index c059d0b8..41a55294 100644 --- a/src/emufile.h +++ b/src/emufile.h @@ -23,12 +23,21 @@ #include #include #include -#include "types-des.h" #include #include #include #include +//should be changed to #ifdef FCEUX but too much work +#ifndef DESMUME +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef char s8; +typedef short s16; +typedef int s32; +#endif + #ifdef _XBOX #undef min; #undef max; @@ -97,6 +106,11 @@ public: EMUFILE_MEMORY(std::vector *underlying) : vec(underlying), ownvec(false), pos(0), len(underlying->size()) { } EMUFILE_MEMORY(u32 preallocate) : vec(new std::vector()), ownvec(true), pos(0), len(0) { vec->reserve(preallocate); } EMUFILE_MEMORY() : vec(new std::vector()), ownvec(true), pos(0), len(0) { vec->reserve(1024); } + EMUFILE_MEMORY(void* buf, s32 size) : vec(new std::vector()), ownvec(true), pos(0), len(size) { + vec->reserve(size); + if(size != 0) + memcpy(&vec[0],buf,size); + } ~EMUFILE_MEMORY() { if(ownvec) delete vec; @@ -180,6 +194,11 @@ public: return pos; } + void trim() + { + vec->resize(len); + } + virtual int size() { return (int)len; } }; @@ -187,14 +206,18 @@ class EMUFILE_FILE : public EMUFILE { protected: FILE* fp; -public: - - EMUFILE_FILE(const char* fname, const char* mode) +private: + void open(const char* fname, const char* mode) { fp = fopen(fname,mode); if(!fp) failbit = true; - }; + } + +public: + + EMUFILE_FILE(const std::string& fname, const char* mode) { open(fname.c_str(),mode); } + EMUFILE_FILE(const char* fname, const char* mode) { open(fname,mode); } virtual ~EMUFILE_FILE() { if(NULL != fp) @@ -205,6 +228,8 @@ public: return fp; } + bool is_open() { return fp != NULL; } + virtual int fprintf(const char *format, ...) { va_list argptr; va_start(argptr, format); diff --git a/src/file.cpp b/src/file.cpp index 0a3357c1..e3a7bb8f 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -44,7 +44,6 @@ #include "movie.h" #include "driver.h" #include "utils/xstring.h" -#include "utils/memorystream.h" using namespace std; @@ -139,8 +138,7 @@ void ApplyIPS(FILE *ips, FCEUFILE* fp) FCEU_printf(" Hard IPS end!\n"); end: fclose(ips); - memorystream* ms = new memorystream(buf,fp->size); - ms->giveBuf(); + EMUFILE_MEMORY* ms = new EMUFILE_MEMORY(buf,fp->size); fp->SetStream(ms); } @@ -237,7 +235,7 @@ zpfail: unzGetCurrentFileInfo(tz,&ufo,0,0,0,0,0,0); int size = ufo.uncompressed_size; - memorystream* ms = new memorystream(size); + EMUFILE_MEMORY* ms = new EMUFILE_MEMORY(size); unzReadCurrentFile(tz,ms->buf(),ufo.uncompressed_size); unzCloseCurrentFile(tz); unzClose(tz); @@ -279,7 +277,7 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext if(!asr.isArchive()) { //if the archive contained no files, try to open it the old fashioned way - std::fstream* fp = FCEUD_UTF8_fstream(fileToOpen,mode); + EMUFILE_FILE* fp = FCEUD_UTF8_fstream(fileToOpen,mode); if(!fp) { return 0; @@ -302,10 +300,10 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext { uint32 magic; - magic = fp->get(); - magic|=fp->get()<<8; - magic|=fp->get()<<16; - fp->seekg(0,std::ios::beg); + magic = fp->fgetc(); + magic|=fp->fgetc()<<8; + magic|=fp->fgetc()<<16; + fp->fseek(0,SEEK_SET); if(magic==0x088b1f) { // maybe gzip... @@ -316,7 +314,7 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext int size; for(size=0; gzgetc(gzfile) != EOF; size++) {} - memorystream* ms = new memorystream(size); + EMUFILE_MEMORY* ms = new EMUFILE_MEMORY(size); gzseek(gzfile,0,SEEK_SET); gzread(gzfile,ms->buf(),size); gzclose(gzfile); @@ -340,7 +338,7 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext fceufp->logicalPath = fileToOpen; fceufp->fullFilename = fileToOpen; fceufp->archiveIndex = -1; - fceufp->stream = (std::iostream*)fp; + fceufp->stream = fp; FCEU_fseek(fceufp,0,SEEK_END); fceufp->size = FCEU_ftell(fceufp); FCEU_fseek(fceufp,0,SEEK_SET); @@ -382,56 +380,26 @@ int FCEU_fclose(FCEUFILE *fp) uint64 FCEU_fread(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp) { - fp->stream->read((char*)ptr,size*nmemb); - uint32 read = fp->stream->gcount(); - return read/size; + return fp->stream->fread((char*)ptr,size*nmemb); } uint64 FCEU_fwrite(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp) { - fp->stream->write((char*)ptr,size*nmemb); + fp->stream->fwrite((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; - - // 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); + fp->stream->fseek(offset,whence); return FCEU_ftell(fp); } uint64 FCEU_ftell(FCEUFILE *fp) { - if(fp->mode == FCEUFILE::READ) - return fp->stream->tellg(); - else - return fp->stream->tellp(); + return fp->stream->ftell(); } int FCEU_read16le(uint16 *val, FCEUFILE *fp) @@ -446,7 +414,7 @@ int FCEU_read32le(uint32 *Bufo, FCEUFILE *fp) int FCEU_fgetc(FCEUFILE *fp) { - return fp->stream->get(); + return fp->stream->fgetc(); } uint64 FCEU_fgetsize(FCEUFILE *fp) diff --git a/src/file.h b/src/file.h index 2e021742..2d3ff9cd 100644 --- a/src/file.h +++ b/src/file.h @@ -4,13 +4,14 @@ #include #include #include "types.h" -#include "utils/memorystream.h" +#include "emufile.h" extern bool bindSavestate; struct FCEUFILE { //the stream you can use to access the data - std::iostream *stream; + //std::iostream *stream; + EMUFILE *stream; //the name of the file, or the logical name of the file within the archive std::string filename; @@ -51,25 +52,25 @@ struct FCEUFILE { } mode; //guarantees that the file contains a memorystream, and returns it for your convenience - memorystream* EnsureMemorystream() { - memorystream* ret = dynamic_cast(stream); + EMUFILE_MEMORY* EnsureMemorystream() { + + EMUFILE_MEMORY* ret = dynamic_cast(stream); if(ret) return ret; //nope, we need to create it: copy the contents - ret = new memorystream(size); - stream->read(ret->buf(),size); + ret = new EMUFILE_MEMORY(size); + stream->fread(ret->buf(),size); delete stream; stream = ret; return ret; } - void SetStream(std::iostream *newstream) { + void SetStream(EMUFILE *newstream) { if(stream) delete stream; stream = newstream; //get the size of the stream - stream->seekg(0,std::ios::end); - size = stream->tellg(); - stream->seekg(0,std::ios::beg); + stream->fseek(0,SEEK_SET); + size = stream->size(); } }; diff --git a/src/lua-engine.cpp b/src/lua-engine.cpp index e04f86c6..81fd0189 100644 --- a/src/lua-engine.cpp +++ b/src/lua-engine.cpp @@ -74,7 +74,7 @@ extern void AddRecentLuaFile(const char *filename); struct LuaSaveState { std::string filename; - memorystream *data; + EMUFILE_MEMORY *data; bool anonymous, persisted; LuaSaveState() : data(0) @@ -97,7 +97,7 @@ struct LuaSaveState { fseek(inf,0,SEEK_END); int len = ftell(inf); fseek(inf,0,SEEK_SET); - data = new memorystream(len); + data = new EMUFILE_MEMORY(len); fread(data->buf(),1,len,inf); fclose(inf); } @@ -2449,7 +2449,7 @@ static int savestate_save(lua_State *L) { } if(ss->data) delete ss->data; - ss->data = new memorystream(); + ss->data = new EMUFILE_MEMORY(); // printf("saving %s\n", filename); @@ -2457,7 +2457,7 @@ static int savestate_save(lua_State *L) { numTries--; FCEUSS_SaveMS(ss->data,Z_NO_COMPRESSION); - ss->data->sync(); + ss->data->fseek(0,SEEK_SET); return 0; } @@ -2489,7 +2489,7 @@ static int savestate_load(lua_State *L) { return 0; } */ if (FCEUSS_LoadFP(ss->data,SSLOADPARAM_NOBACKUP)) - ss->data->seekg(0); + ss->data->fseek(0,SEEK_SET); return 0; diff --git a/src/movie.cpp b/src/movie.cpp index c72f7276..bbcf8a48 100644 --- a/src/movie.cpp +++ b/src/movie.cpp @@ -8,7 +8,7 @@ #include #include - +#include "emufile.h" #include "version.h" #include "types.h" #include "utils/endian.h" @@ -27,7 +27,6 @@ #endif #include "utils/guid.h" #include "utils/memory.h" -#include "utils/memorystream.h" #include "utils/xstring.h" #include @@ -79,7 +78,7 @@ EMOVIEMODE movieMode = MOVIEMODE_INACTIVE; //this should not be set unless we are in MOVIEMODE_RECORD! //FILE* fpRecordingMovie = 0; -std::ostream* osRecordingMovie = 0; +EMUFILE* osRecordingMovie = NULL; int currFrameCounter; uint32 cur_input_display = 0; @@ -213,7 +212,7 @@ bool MovieRecord::Compare(MovieRecord& compareRec) } const char MovieRecord::mnemonics[8] = {'A','B','S','T','U','D','L','R'}; -void MovieRecord::dumpJoy(std::ostream* os, uint8 joystate) +void MovieRecord::dumpJoy(EMUFILE* os, uint8 joystate) { //these are mnemonics for each joystick bit. //since we usually use the regular joypad, these will be more helpful. @@ -225,16 +224,16 @@ void MovieRecord::dumpJoy(std::ostream* os, uint8 joystate) char mnemonic = mnemonics[bit]; //if the bit is set write the mnemonic if(joystate & bitmask) - os->put(mnemonic); + os->fwrite(&mnemonic,1); else //otherwise write an unset bit - os->put('.'); + write8le('.',os); } } -void MovieRecord::parseJoy(std::istream* is, uint8& joystate) +void MovieRecord::parseJoy(EMUFILE* is, uint8& joystate) { char buf[8]; - is->read(buf,8); + is->fread(buf,8); joystate = 0; for(int i=0;i<8;i++) { @@ -243,22 +242,22 @@ void MovieRecord::parseJoy(std::istream* is, uint8& joystate) } } -void MovieRecord::parse(MovieData* md, std::istream* is) +void MovieRecord::parse(MovieData* md, EMUFILE* is) { //by the time we get in here, the initial pipe has already been extracted //extract the commands commands = uint32DecFromIstream(is); //*is >> commands; - is->get(); //eat the pipe + is->fgetc(); //eat the pipe //a special case: if fourscore is enabled, parse four gamepads if(md->fourscore) { - parseJoy(is,joysticks[0]); is->get(); //eat the pipe - parseJoy(is,joysticks[1]); is->get(); //eat the pipe - parseJoy(is,joysticks[2]); is->get(); //eat the pipe - parseJoy(is,joysticks[3]); is->get(); //eat the pipe + parseJoy(is,joysticks[0]); is->fgetc(); //eat the pipe + parseJoy(is,joysticks[1]); is->fgetc(); //eat the pipe + parseJoy(is,joysticks[2]); is->fgetc(); //eat the pipe + parseJoy(is,joysticks[3]); is->fgetc(); //eat the pipe } else { @@ -275,40 +274,40 @@ void MovieRecord::parse(MovieData* md, std::istream* is) zappers[port].zaphit = uint64DecFromIstream(is); } - is->get(); //eat the pipe + is->fgetc(); //eat the pipe } } //(no fcexp data is logged right now) - is->get(); //eat the pipe + is->fgetc(); //eat the pipe //should be left at a newline } -bool MovieRecord::parseBinary(MovieData* md, std::istream* is) +bool MovieRecord::parseBinary(MovieData* md, EMUFILE* is) { - commands = (uint8)is->get(); + commands = (uint8)is->fgetc(); //check for eof - if(is->gcount() != 1) return false; + if(is->eof()) return false; if(md->fourscore) { - is->read((char*)&joysticks,4); + is->fread((char*)&joysticks,4); } else { for(int port=0;port<2;port++) { if(md->ports[port] == SI_GAMEPAD) - joysticks[port] = (uint8)is->get(); + joysticks[port] = (uint8)is->fgetc(); else if(md->ports[port] == SI_ZAPPER) { - zappers[port].x = (uint8)is->get(); - zappers[port].y = (uint8)is->get(); - zappers[port].b = (uint8)is->get(); - zappers[port].bogo = (uint8)is->get(); + zappers[port].x = (uint8)is->fgetc(); + zappers[port].y = (uint8)is->fgetc(); + zappers[port].b = (uint8)is->fgetc(); + zappers[port].bogo = (uint8)is->fgetc(); read64le(&zappers[port].zaphit,is); } } @@ -318,35 +317,33 @@ bool MovieRecord::parseBinary(MovieData* md, std::istream* is) } -void MovieRecord::dumpBinary(MovieData* md, std::ostream* os, int index) +void MovieRecord::dumpBinary(MovieData* md, EMUFILE* os, int index) { - os->put(commands); + write8le(commands,os); if(md->fourscore) { - os->put(joysticks[0]); - os->put(joysticks[1]); - os->put(joysticks[2]); - os->put(joysticks[3]); + for(int i=0;i<4;i++) + os->fwrite(&joysticks[i],sizeof(joysticks[i])); } else { for(int port=0;port<2;port++) { if(md->ports[port] == SI_GAMEPAD) - os->put(joysticks[port]); + os->fwrite(&joysticks[port],sizeof(joysticks[port])); else if(md->ports[port] == SI_ZAPPER) { - os->put(zappers[port].x); - os->put(zappers[port].y); - os->put(zappers[port].b); - os->put(zappers[port].bogo); + write8le(zappers[port].x,os); + write8le(zappers[port].y,os); + write8le(zappers[port].b,os); + write8le(zappers[port].bogo,os); write64le(zappers[port].zaphit, os); } } } } -void MovieRecord::dump(MovieData* md, std::ostream* os, int index) +void MovieRecord::dump(MovieData* md, EMUFILE* os, int index) { if (false/*currMovieData.binaryFlag*/) { @@ -355,42 +352,42 @@ void MovieRecord::dump(MovieData* md, std::ostream* os, int index) } //dump the misc commands //*os << '|' << setw(1) << (int)commands; - os->put('|'); + os->fputc('|'); putdec(os,commands); //a special case: if fourscore is enabled, dump four gamepads if(md->fourscore) { - os->put('|'); - dumpJoy(os,joysticks[0]); os->put('|'); - dumpJoy(os,joysticks[1]); os->put('|'); - dumpJoy(os,joysticks[2]); os->put('|'); - dumpJoy(os,joysticks[3]); os->put('|'); + os->fputc('|'); + dumpJoy(os,joysticks[0]); os->fputc('|'); + dumpJoy(os,joysticks[1]); os->fputc('|'); + dumpJoy(os,joysticks[2]); os->fputc('|'); + dumpJoy(os,joysticks[3]); os->fputc('|'); } else { for(int port=0;port<2;port++) { - os->put('|'); + os->fputc('|'); if(md->ports[port] == SI_GAMEPAD) dumpJoy(os, joysticks[port]); else if(md->ports[port] == SI_ZAPPER) { - putdec(os,zappers[port].x); os->put(' '); - putdec(os,zappers[port].y); os->put(' '); - putdec(os,zappers[port].b); os->put(' '); - putdec(os,zappers[port].bogo); os->put(' '); + putdec(os,zappers[port].x); os->fputc(' '); + putdec(os,zappers[port].y); os->fputc(' '); + putdec(os,zappers[port].b); os->fputc(' '); + putdec(os,zappers[port].bogo); os->fputc(' '); putdec(os,zappers[port].zaphit); } } - os->put('|'); + os->fputc('|'); } //(no fcexp data is logged right now) - os->put('|'); + os->fputc('|'); //each frame is on a new line - os->put('\n'); + os->fputc('\n'); } MovieData::MovieData() @@ -464,43 +461,43 @@ void MovieData::installValue(std::string& key, std::string& val) } } -int MovieData::dump(std::ostream *os, bool binary) +int MovieData::dump(EMUFILE *os, bool binary) { - int start = os->tellp(); - *os << "version " << version << endl; - *os << "emuVersion " << emuVersion << endl; - *os << "rerecordCount " << rerecordCount << endl; - *os << "palFlag " << (palFlag?1:0) << endl; - *os << "romFilename " << romFilename << endl; - *os << "romChecksum " << BytesToString(romChecksum.data,MD5DATA::size) << endl; - *os << "guid " << guid.toString() << endl; - *os << "fourscore " << (fourscore?1:0) << endl; - *os << "microphone " << (microphone?1:0) << endl; - *os << "port0 " << ports[0] << endl; - *os << "port1 " << ports[1] << endl; - *os << "port2 " << ports[2] << endl; - *os << "FDS " << isFDS << endl; - *os << "NewPPU " << newppu << endl; + int start = os->ftell(); + os->fprintf("version %d\n", version); + os->fprintf("emuVersion %d\n", emuVersion); + os->fprintf("rerecordCount %d\n", rerecordCount); + os->fprintf("palFlag %d\n" , (palFlag?1:0) ); + os->fprintf("romFilename %s\n" , romFilename.c_str() ); + os->fprintf("romChecksum %s\n" , BytesToString(romChecksum.data,MD5DATA::size).c_str() ); + os->fprintf("guid %s\n" , guid.toString().c_str() ); + os->fprintf("fourscore %d\n" , (fourscore?1:0) ); + os->fprintf("microphone %d\n" , (microphone?1:0) ); + os->fprintf("port0 %d\n" , ports[0] ); + os->fprintf("port1 %d\n" , ports[1] ); + os->fprintf("port2 %d\n" , ports[2] ); + os->fprintf("FDS %d\n" , isFDS?1:0 ); + os->fprintf("NewPPU %d\n" , newppu?1:0 ); for(uint32 i=0;ifprintf("comment %s\n" , wcstombs(comments[i]).c_str() ); for(uint32 i=0;ifprintf("subtitle %s\n" , subtitles[i].c_str() ); if(binary) - *os << "binary 1" << endl; + os->fprintf("binary 1\n" ); if(savestate.size() != 0) - *os << "savestate " << BytesToString(&savestate[0],savestate.size()) << endl; + os->fprintf("savestate %s\n" , BytesToString(&savestate[0],savestate.size()).c_str() ); if(FCEUMOV_Mode(MOVIEMODE_TASEDIT)) - *os << "length " << this->records.size() << endl; + os->fprintf("length %d\n" , this->records.size() ); if(binary) { //put one | to start the binary dump - os->put('|'); + os->fputc('|'); for(int i=0;i<(int)records.size();i++) records[i].dumpBinary(this,os,i); } @@ -508,13 +505,13 @@ int MovieData::dump(std::ostream *os, bool binary) for(int i=0;i<(int)records.size();i++) records[i].dump(this,os,i); - int end = os->tellp(); + int end = os->ftell(); return end-start; } -int MovieData::dumpGreenzone(std::ostream *os, bool binary) +int MovieData::dumpGreenzone(EMUFILE *os, bool binary) { - int start = os->tellp(); + int start = os->ftell(); int frame, size; for (int i=0; i<(int)records.size(); ++i) { @@ -525,19 +522,19 @@ int MovieData::dumpGreenzone(std::ostream *os, bool binary) write32le(frame, os); write32le(size, os); - os->write(&records[i].savestate[0], size); + os->fwrite(&records[i].savestate[0], size); } frame=-1; size=currMovieData.greenZoneCount; write32le(frame, os); write32le(size, os); - int end= os->tellp(); + int end= os->ftell(); return end-start; } -int MovieData::loadGreenzone(std::istream *is, bool binary) +int MovieData::loadGreenzone(EMUFILE *is, bool binary) { int frame, size; while(1) @@ -545,9 +542,9 @@ int MovieData::loadGreenzone(std::istream *is, bool binary) if (!read32le((uint32 *)&frame, is)) {size=0; break;} if (!read32le((uint32 *)&size, is)) {size=0; break;} if (frame==-1) break; - int pos = is->tellg(); + int pos = is->ftell(); FCEUSS_LoadFP(is, SSLOADPARAM_NOBACKUP); - is->seekg(pos+size); + is->fseek(pos+size,SEEK_SET); } greenZoneCount=size; @@ -599,7 +596,7 @@ bool FCEUMOV_Mode(int modemask) return FCEUMOV_Mode((EMOVIEMODE)modemask); } -static void LoadFM2_binarychunk(MovieData& movieData, std::istream* fp, int size) +static void LoadFM2_binarychunk(MovieData& movieData, EMUFILE* fp, int size) { int recordsize = 1; //1 for the command if(movieData.fourscore) @@ -617,11 +614,11 @@ static void LoadFM2_binarychunk(MovieData& movieData, std::istream* fp, int size } //find out how much remains in the file - int curr = fp->tellg(); - fp->seekg(0,std::ios::end); - int end = fp->tellg(); + int curr = fp->ftell(); + fp->fseek(0,SEEK_END); + int end = fp->ftell(); int flen = end-curr; - fp->seekg(curr,std::ios::beg); + fp->fseek(curr,SEEK_SET); //the amount todo is the min of the limiting size we received and the remaining contents of the file int todo = std::min(size, flen); @@ -638,7 +635,7 @@ static void LoadFM2_binarychunk(MovieData& movieData, std::istream* fp, int size } //yuck... another custom text parser. -bool LoadFM2(MovieData& movieData, std::istream* fp, int size, bool stopAfterHeader) +bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader) { std::string a("length"), b("-1"); // Non-TAS projects consume until EOF @@ -646,9 +643,9 @@ bool LoadFM2(MovieData& movieData, std::istream* fp, int size, bool stopAfterHea //first, look for an fcm signature char fcmbuf[3]; - std::ios::pos_type curr = fp->tellg(); - fp->read(fcmbuf,3); - fp->seekg(curr); + std::ios::pos_type curr = fp->ftell(); + fp->fread(fcmbuf,3); + fp->fseek(curr,SEEK_SET); if(!strncmp(fcmbuf,"FCM",3)) { FCEU_PrintError("FCM File format is no longer supported. Please use Tools > Convert FCM"); return false; @@ -656,9 +653,9 @@ bool LoadFM2(MovieData& movieData, std::istream* fp, int size, bool stopAfterHea //movie must start with "version 3" char buf[9]; - curr = fp->tellg(); - fp->read(buf,9); - fp->seekg(curr); + curr = fp->ftell(); + fp->fread(buf,9); + fp->fseek(curr,SEEK_SET); if(fp->fail()) return false; if(memcmp(buf,"version 3",9)) return false; @@ -673,7 +670,7 @@ bool LoadFM2(MovieData& movieData, std::istream* fp, int size, bool stopAfterHea bool iswhitespace, isrecchar, isnewline; int c; if(size--<=0) goto bail; - c = fp->get(); + c = fp->fgetc(); if(c == -1) goto bail; iswhitespace = (c==' '||c=='\t'); @@ -702,9 +699,9 @@ bool LoadFM2(MovieData& movieData, std::istream* fp, int size, bool stopAfterHea if (stopAfterHeader) return true; int currcount = movieData.records.size(); movieData.records.resize(currcount+1); - int preparse = fp->tellg(); + int preparse = fp->ftell(); movieData.records[currcount].parse(&movieData, fp); - int postparse = fp->tellg(); + int postparse = fp->ftell(); size -= (postparse-preparse); state = NEWLINE; break; @@ -868,15 +865,15 @@ bool FCEUMOV_FromPoweron() { return movieFromPoweron; } -bool MovieData::loadSavestateFrom(std::vector* buf) +bool MovieData::loadSavestateFrom(std::vector* buf) { - memorystream ms(buf); + EMUFILE_MEMORY ms(buf); return FCEUSS_LoadFP(&ms,SSLOADPARAM_BACKUP); } -void MovieData::dumpSavestateTo(std::vector* buf, int compressionLevel) +void MovieData::dumpSavestateTo(std::vector* buf, int compressionLevel) { - memorystream ms(buf); + EMUFILE_MEMORY ms(buf); FCEUSS_SaveMS(&ms,compressionLevel); ms.trim(); } @@ -1201,7 +1198,7 @@ void FCEU_DrawLagCounter(uint8 *XBuf) } } -int FCEUMOV_WriteState(std::ostream* os) +int FCEUMOV_WriteState(EMUFILE* os) { //we are supposed to dump the movie data into the savestate if(movieMode == MOVIEMODE_RECORD || movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_FINISHED) @@ -1241,7 +1238,7 @@ bool CheckTimelines(MovieData& stateMovie, MovieData& currMovie, int& error) static bool load_successful; -bool FCEUMOV_ReadState(std::istream* is, uint32 size) +bool FCEUMOV_ReadState(EMUFILE* is, uint32 size) { load_successful = false; @@ -1253,9 +1250,9 @@ bool FCEUMOV_ReadState(std::istream* is, uint32 size) } MovieData tempMovieData = MovieData(); - std::ios::pos_type curr = is->tellg(); + std::ios::pos_type curr = is->ftell(); if(!LoadFM2(tempMovieData, is, size, false)) { - is->seekg((uint32)curr+size); + is->fseek((uint32)curr+size,SEEK_SET); extern bool FCEU_state_loading_old_format; if(FCEU_state_loading_old_format) { if(movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_RECORD || movieMode == MOVIEMODE_FINISHED) { @@ -1574,7 +1571,7 @@ void FCEU_DisplaySubtitles(char *format, ...) void FCEUI_CreateMovieFile(std::string fn) { MovieData md = currMovieData; //Get current movie data - std::fstream* outf = FCEUD_UTF8_fstream(fn, "wb"); //open/create file + EMUFILE* outf = FCEUD_UTF8_fstream(fn, "wb"); //open/create file md.dump(outf,false); //dump movie data delete outf; //clean up, delete file object } diff --git a/src/movie.h b/src/movie.h index 4097133f..c4d6c099 100644 --- a/src/movie.h +++ b/src/movie.h @@ -82,8 +82,8 @@ int FCEUMOV_GetFrame(void); int FCEUI_GetLagCount(void); bool FCEUI_GetLagged(void); -int FCEUMOV_WriteState(std::ostream* os); -bool FCEUMOV_ReadState(std::istream* is, uint32 size); +int FCEUMOV_WriteState(EMUFILE* os); +bool FCEUMOV_ReadState(EMUFILE* is, uint32 size); void FCEUMOV_PreLoad(); bool FCEUMOV_PostLoad(); @@ -143,14 +143,14 @@ public: void clear(); //a waste of memory in lots of cases.. maybe make it a pointer later? - std::vector savestate; + std::vector savestate; - void parse(MovieData* md, std::istream* is); - bool parseBinary(MovieData* md, std::istream* is); - void dump(MovieData* md, std::ostream* os, int index); - void dumpBinary(MovieData* md, std::ostream* os, int index); - void parseJoy(std::istream* is, uint8& joystate); - void dumpJoy(std::ostream* os, uint8 joystate); + void parse(MovieData* md, EMUFILE* is); + bool parseBinary(MovieData* md, EMUFILE* is); + void dump(MovieData* md, EMUFILE* os, int index); + void dumpBinary(MovieData* md, EMUFILE* os, int index); + void parseJoy(EMUFILE* is, uint8& joystate); + void dumpJoy(EMUFILE* os, uint8 joystate); static const char mnemonics[8]; @@ -172,7 +172,7 @@ public: bool PPUflag; MD5DATA romChecksum; std::string romFilename; - std::vector savestate; + std::vector savestate; std::vector records; std::vector comments; std::vector subtitles; @@ -227,15 +227,15 @@ public: void truncateAt(int frame); void installValue(std::string& key, std::string& val); - int dump(std::ostream* os, bool binary); - int dumpGreenzone(std::ostream *os, bool binary); - int loadGreenzone(std::istream *is, bool binary); + int dump(EMUFILE* os, bool binary); + int dumpGreenzone(EMUFILE *os, bool binary); + int loadGreenzone(EMUFILE *is, bool binary); void clearRecordRange(int start, int len); void insertEmpty(int at, int frames); - static bool loadSavestateFrom(std::vector* buf); - static void dumpSavestateTo(std::vector* buf, int compressionLevel); + static bool loadSavestateFrom(std::vector* buf); + static void dumpSavestateTo(std::vector* buf, int compressionLevel); void TryDumpIncremental(); private: diff --git a/src/state.cpp b/src/state.cpp index 81f10a93..d6fb2af0 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -36,7 +36,6 @@ #include "sound.h" #include "utils/endian.h" #include "utils/memory.h" -#include "utils/memorystream.h" #include "utils/xstring.h" #include "file.h" #include "fds.h" @@ -120,7 +119,7 @@ SFORMAT SFCPUC[]={ void foo(uint8* test) { (void)test; } -static int SubWrite(std::ostream* os, SFORMAT *sf) +static int SubWrite(EMUFILE* os, SFORMAT *sf) { uint32 acc=0; @@ -142,7 +141,7 @@ static int SubWrite(std::ostream* os, SFORMAT *sf) if(os) //Are we writing or calculating the size of this block? { - os->write(sf->desc,4); + os->fwrite(sf->desc,4); write32le(sf->s&(~FCEUSTATE_FLAGS),os); #ifndef LSB_FIRST @@ -151,9 +150,9 @@ static int SubWrite(std::ostream* os, SFORMAT *sf) #endif if(sf->s&FCEUSTATE_INDIRECT) - os->write(*(char **)sf->v,sf->s&(~FCEUSTATE_FLAGS)); + os->fwrite(*(char **)sf->v,sf->s&(~FCEUSTATE_FLAGS)); else - os->write((char*)sf->v,sf->s&(~FCEUSTATE_FLAGS)); + os->fwrite((char*)sf->v,sf->s&(~FCEUSTATE_FLAGS)); //Now restore the original byte order. #ifndef LSB_FIRST @@ -167,10 +166,10 @@ static int SubWrite(std::ostream* os, SFORMAT *sf) return(acc); } -static int WriteStateChunk(std::ostream* os, int type, SFORMAT *sf) +static int WriteStateChunk(EMUFILE* os, int type, SFORMAT *sf) { - os->put(type); - int bsize = SubWrite((std::ostream*)0,sf); + os->fputc(type); + int bsize = SubWrite((EMUFILE*)0,sf); write32le(bsize,os); if(!SubWrite(os,sf)) @@ -203,16 +202,16 @@ static SFORMAT *CheckS(SFORMAT *sf, uint32 tsize, char *desc) return(0); } -static bool ReadStateChunk(std::istream* is, SFORMAT *sf, int size) +static bool ReadStateChunk(EMUFILE* is, SFORMAT *sf, int size) { SFORMAT *tmp; - int temp = is->tellg(); + int temp = is->ftell(); - while(is->tellg()ftell()read(toa,4).gcount()<4) + if(is->fread(toa,4)<4) return false; read32le(&tsize,is); @@ -220,9 +219,9 @@ static bool ReadStateChunk(std::istream* is, SFORMAT *sf, int size) if((tmp=CheckS(sf,tsize,toa))) { if(tmp->s&FCEUSTATE_INDIRECT) - is->read(*(char **)tmp->v,tmp->s&(~FCEUSTATE_FLAGS)); + is->fread(*(char **)tmp->v,tmp->s&(~FCEUSTATE_FLAGS)); else - is->read((char *)tmp->v,tmp->s&(~FCEUSTATE_FLAGS)); + is->fread((char *)tmp->v,tmp->s&(~FCEUSTATE_FLAGS)); #ifndef LSB_FIRST if(tmp->s&RLSB) @@ -230,7 +229,7 @@ static bool ReadStateChunk(std::istream* is, SFORMAT *sf, int size) #endif } else - is->seekg(tsize,std::ios::cur); + is->fseek(tsize,SEEK_CUR); } // while(...) return true; } @@ -239,7 +238,7 @@ static int read_sfcpuc=0, read_snd=0; void FCEUD_BlitScreen(uint8 *XBuf); //mbg merge 7/17/06 YUCKY had to add void UpdateFCEUWindow(void); //mbg merge 7/17/06 YUCKY had to add -static bool ReadStateChunks(std::istream* is, int32 totalsize) +static bool ReadStateChunks(EMUFILE* is, int32 totalsize) { int t; uint32 size; @@ -256,7 +255,7 @@ static bool ReadStateChunks(std::istream* is, int32 totalsize) while(totalsize > 0) { - t=is->get(); + t=is->fgetc(); if(t==EOF) break; if(!read32le(&size,is)) break; totalsize -= size + 5; @@ -290,14 +289,14 @@ static bool ReadStateChunks(std::istream* is, int32 totalsize) } else { - is->seekg(size,std::ios::cur); + is->fseek(size,SEEK_CUR); } break; case 8: // load back buffer { extern uint8 *XBackBuf; - if(is->read((char*)XBackBuf,size).gcount() != size) + if(is->fread((char*)XBackBuf,size) != size) ret = false; //MBG TODO - can this be moved to a better place? @@ -329,7 +328,7 @@ static bool ReadStateChunks(std::istream* is, int32 totalsize) warned=true; } //if(fseek(st,size,SEEK_CUR)<0) goto endo;break; - is->seekg(size,std::ios::cur); + is->fseek(size,SEEK_CUR); } } //endo: @@ -354,13 +353,13 @@ int CurrentState=0; extern int geniestage; -bool FCEUSS_SaveMS(std::ostream* outstream, int compressionLevel) +bool FCEUSS_SaveMS(EMUFILE* outstream, int compressionLevel) { //a temp memory stream. we'll dump some data here and then compress //TODO - support dumping directly without compressing to save a buffer copy - memorystream ms; - std::ostream* os = (std::ostream*)&ms; + EMUFILE_MEMORY ms; + EMUFILE* os = &ms; uint32 totalsize = 0; @@ -380,12 +379,12 @@ bool FCEUSS_SaveMS(std::ostream* outstream, int compressionLevel) //do not save the movie state if we are in tasedit! that is a huge waste of time and space! if(!FCEUMOV_Mode(MOVIEMODE_TASEDIT)) { - os->seekp(5,std::ios::cur); + os->fseek(5,SEEK_CUR); int size = FCEUMOV_WriteState(os); - os->seekp(-(size+5),std::ios::cur); - os->put(7); + os->fseek(-(size+5),SEEK_CUR); + os->fputc(7); write32le(size, os); - os->seekp(size,std::ios::cur); + os->fseek(size,SEEK_CUR); totalsize += 5 + size; } @@ -394,9 +393,9 @@ bool FCEUSS_SaveMS(std::ostream* outstream, int compressionLevel) { extern uint8 *XBackBuf; uint32 size = 256 * 256 + 8; - os->put(8); + os->fputc(8); write32le(size, os); - os->write((char*)XBackBuf,size); + os->fwrite((char*)XBackBuf,size); totalsize += 5 + size; } @@ -433,8 +432,8 @@ bool FCEUSS_SaveMS(std::ostream* outstream, int compressionLevel) FCEU_en32lsb(header+12, comprlen); //dump it to the destination file - outstream->write((char*)header,16); - outstream->write((char*)cbuf,comprlen==-1?totalsize:comprlen); + outstream->fwrite((char*)header,16); + outstream->fwrite((char*)cbuf,comprlen==-1?totalsize:comprlen); if(cbuf != (uint8*)ms.buf()) delete[] cbuf; return error == Z_OK; @@ -443,7 +442,7 @@ bool FCEUSS_SaveMS(std::ostream* outstream, int compressionLevel) void FCEUSS_Save(const char *fname) { - std::fstream* st = 0; + EMUFILE* st = 0; char fn[2048]; if(geniestage==1) @@ -454,7 +453,7 @@ void FCEUSS_Save(const char *fname) if(fname) //If filename is given use it. { - st =FCEUD_UTF8_fstream(fname, "wb"); + st = FCEUD_UTF8_fstream(fname, "wb"); strcpy(fn, fname); } else //Else, generate one @@ -522,7 +521,7 @@ void FCEUSS_Save(const char *fname) redoSS = false; //we have a new savestate so redo is not possible } -int FCEUSS_LoadFP_old(std::istream* is, ENUM_SSLOADPARAMS params) +int FCEUSS_LoadFP_old(EMUFILE* is, ENUM_SSLOADPARAMS params) { //if(params==SSLOADPARAM_DUMMY && suppress_scan_chunks) // return 1; @@ -558,7 +557,7 @@ int FCEUSS_LoadFP_old(std::istream* is, ENUM_SSLOADPARAMS params) { FCEUMOV_PreLoad(); } - is->read((char*)&header,16); + is->fread((char*)&header,16); if(memcmp(header,"FCS",3)) { return(0); @@ -616,10 +615,10 @@ int FCEUSS_LoadFP_old(std::istream* is, ENUM_SSLOADPARAMS params) } -bool FCEUSS_LoadFP(std::istream* is, ENUM_SSLOADPARAMS params) +bool FCEUSS_LoadFP(EMUFILE* is, ENUM_SSLOADPARAMS params) { //maybe make a backup savestate - memorystream msBackupSavestate; + EMUFILE_MEMORY msBackupSavestate; bool backup = (params == SSLOADPARAM_BACKUP); if(!is) @@ -631,10 +630,10 @@ bool FCEUSS_LoadFP(std::istream* is, ENUM_SSLOADPARAMS params) uint8 header[16]; //read and analyze the header - is->read((char*)&header,16); + is->fread((char*)&header,16); if(memcmp(header,"FCSX",4)) { //its not an fceux save file.. perhaps it is an fceu savefile - is->seekg(0); + is->fseek(0,SEEK_SET); FCEU_state_loading_old_format = true; bool ret = FCEUSS_LoadFP_old(is,params)!=0; FCEU_state_loading_old_format = false; @@ -646,14 +645,14 @@ bool FCEUSS_LoadFP(std::istream* is, ENUM_SSLOADPARAMS params) int stateversion = FCEU_de32lsb(header + 8); int comprlen = FCEU_de32lsb(header + 12); - std::vector buf(totalsize); + std::vector buf(totalsize); //not compressed: if(comprlen != -1) { //load the compressed chunk and decompress std::vector cbuf(comprlen); - is->read((char*)&cbuf[0],comprlen); + is->fread((char*)&cbuf[0],comprlen); uLongf uncomprlen = totalsize; int error = uncompress((uint8*)&buf[0],&uncomprlen,(uint8*)&cbuf[0],comprlen); @@ -663,12 +662,12 @@ bool FCEUSS_LoadFP(std::istream* is, ENUM_SSLOADPARAMS params) } else { - is->read((char*)&buf[0],totalsize); + is->fread((char*)&buf[0],totalsize); } FCEUMOV_PreLoad(); - memorystream mstemp(&buf); + EMUFILE_MEMORY mstemp(&buf); bool x = ReadStateChunks(&mstemp,totalsize)!=0; //mbg 5/24/08 - we don't support old states, so this shouldnt matter. @@ -687,7 +686,7 @@ bool FCEUSS_LoadFP(std::istream* is, ENUM_SSLOADPARAMS params) } if(!x && backup) { - msBackupSavestate.sync(); + msBackupSavestate.fseek(0,SEEK_SET); FCEUSS_LoadFP(&msBackupSavestate,SSLOADPARAM_NOBACKUP); } @@ -697,7 +696,7 @@ bool FCEUSS_LoadFP(std::istream* is, ENUM_SSLOADPARAMS params) bool FCEUSS_Load(const char *fname) { - std::fstream* st; + EMUFILE* st; char fn[2048]; //mbg movie - this needs to be overhauled diff --git a/src/state.h b/src/state.h index 8a5065c3..70335288 100644 --- a/src/state.h +++ b/src/state.h @@ -28,9 +28,9 @@ void FCEUSS_Save(const char *); bool FCEUSS_Load(const char *); //zlib values: 0 (none) through 9 (max) or -1 (default) -bool FCEUSS_SaveMS(std::ostream* outstream, int compressionLevel); +bool FCEUSS_SaveMS(EMUFILE* outstream, int compressionLevel); -bool FCEUSS_LoadFP(std::istream* is, ENUM_SSLOADPARAMS params); +bool FCEUSS_LoadFP(EMUFILE* is, ENUM_SSLOADPARAMS params); extern int CurrentState; void FCEUSS_CheckStates(void); diff --git a/src/utils/endian.cpp b/src/utils/endian.cpp index 0524272d..88ab2078 100644 --- a/src/utils/endian.cpp +++ b/src/utils/endian.cpp @@ -26,6 +26,27 @@ #include #include "../types.h" #include "endian.h" +#include "emufile.h" + +//OMG ! configure this correctly +#define LOCAL_LE + +/* little endian to local endianess convert macros */ +#ifdef LOCAL_BE /* local arch is big endian */ +# define LE_TO_LOCAL_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff)) +# define LE_TO_LOCAL_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff)) +# define LE_TO_LOCAL_64(x) ((((x)&0xff)<<56)|(((x)&0xff00)<<40)|(((x)&0xff0000)<<24)|(((x)&0xff000000)<<8)|(((x)>>8)&0xff000000)|(((x)>>24)&0xff00)|(((x)>>40)&0xff00)|(((x)>>56)&0xff)) +# define LOCAL_TO_LE_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff)) +# define LOCAL_TO_LE_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff)) +# define LOCAL_TO_LE_64(x) ((((x)&0xff)<<56)|(((x)&0xff00)<<40)|(((x)&0xff0000)<<24)|(((x)&0xff000000)<<8)|(((x)>>8)&0xff000000)|(((x)>>24)&0xff00)|(((x)>>40)&0xff00)|(((x)>>56)&0xff)) +#else /* local arch is little endian */ +# define LE_TO_LOCAL_16(x) (x) +# define LE_TO_LOCAL_32(x) (x) +# define LE_TO_LOCAL_64(x) (x) +# define LOCAL_TO_LE_16(x) (x) +# define LOCAL_TO_LE_32(x) (x) +# define LOCAL_TO_LE_64(x) (x) +#endif ///endian-flips count bytes. count should be even and nonzero. void FlipByteOrder(uint8 *src, uint32 count) @@ -194,3 +215,99 @@ uint16 FCEU_de16lsb(uint8 *morp) { return morp[0]|(morp[1]<<8); } + + +//well. just for the sake of consistency +int write8le(u8 b, EMUFILE*os) +{ + os->fwrite((char*)&b,1); + return 1; +} + +//well. just for the sake of consistency +int read8le(u8 *Bufo, EMUFILE*is) +{ + if(is->_fread((char*)Bufo,1) != 1) + return 0; + return 1; +} + +///writes a little endian 16bit value to the specified file +int write16le(u16 b, EMUFILE *fp) +{ + u8 s[2]; + s[0]=(u8)b; + s[1]=(u8)(b>>8); + fp->fwrite(s,2); + return 2; +} + + +///writes a little endian 32bit value to the specified file +int write32le(u32 b, EMUFILE *fp) +{ + uint8 s[4]; + s[0]=(u8)b; + s[1]=(u8)(b>>8); + s[2]=(u8)(b>>16); + s[3]=(u8)(b>>24); + fp->fwrite(s,4); + return 4; +} + +void writebool(bool b, EMUFILE* os) { write32le(b?1:0,os); } + +int write64le(uint64 b, EMUFILE* os) +{ + uint8 s[8]; + s[0]=(u8)b; + s[1]=(u8)(b>>8); + s[2]=(u8)(b>>16); + s[3]=(u8)(b>>24); + s[4]=(u8)(b>>32); + s[5]=(u8)(b>>40); + s[6]=(u8)(b>>48); + s[7]=(u8)(b>>56); + os->fwrite((char*)&s,8); + return 8; +} + + +int read32le(uint32 *Bufo, EMUFILE *fp) +{ + uint32 buf; + if(fp->_fread(&buf,4)<4) + return 0; +#ifdef LOCAL_LE + *(u32*)Bufo=buf; +#else + *(u32*)Bufo=((buf&0xFF)<<24)|((buf&0xFF00)<<8)|((buf&0xFF0000)>>8)|((buf&0xFF000000)>>24); +#endif + return 1; +} + +int read16le(u16 *Bufo, EMUFILE *is) +{ + u16 buf; + if(is->_fread((char*)&buf,2) != 2) + return 0; +#ifdef LOCAL_LE + *Bufo=buf; +#else + *Bufo = LE_TO_LOCAL_16(buf); +#endif + return 1; +} + +int read64le(uint64 *Bufo, EMUFILE *is) +{ + uint64 buf; + if(is->_fread((char*)&buf,8) != 8) + return 0; +#ifdef LOCAL_LE + *Bufo=buf; +#else + *Bufo = LE_TO_LOCAL_64(buf); +#endif + return 1; +} diff --git a/src/utils/endian.h b/src/utils/endian.h index d6e12335..1ad58649 100644 --- a/src/utils/endian.h +++ b/src/utils/endian.h @@ -3,6 +3,44 @@ #include #include +#include "../emufile.h" +#include "../types.h" + +inline uint64 double_to_u64(double d) { + union { + uint64 a; + double b; + } fuxor; + fuxor.b = d; + return fuxor.a; +} + +inline double u64_to_double(uint64 u) { + union { + uint64 a; + double b; + } fuxor; + fuxor.a = u; + return fuxor.b; +} + +inline uint32 float_to_u32(float f) { + union { + uint32 a; + float b; + } fuxor; + fuxor.b = f; + return fuxor.a; +} + +inline float u32_to_float(uint32 u) { + union { + uint32 a; + float b; + } fuxor; + fuxor.a = u; + return fuxor.b; +} int write16le(uint16 b, FILE *fp); @@ -22,5 +60,50 @@ uint64 FCEU_de64lsb(uint8 *morp); uint32 FCEU_de32lsb(uint8 *morp); uint16 FCEU_de16lsb(uint8 *morp); -#endif +//well. just for the sake of consistency +int write8le(uint8 b, EMUFILE *fp); +inline int write8le(uint8* b, EMUFILE *fp) { return write8le(*b,fp); } +int write16le(uint16 b, EMUFILE* os); +int write32le(uint32 b, EMUFILE* os); +int write64le(uint64 b, EMUFILE* os); +inline int write_double_le(double b, EMUFILE*is) { uint64 temp = double_to_u64(b); int ret = write64le(temp,is); return ret; } + +int read8le(uint8 *Bufo, EMUFILE*is); +int read16le(uint16 *Bufo, EMUFILE*is); +inline int read16le(int16 *Bufo, EMUFILE*is) { return read16le((u16*)Bufo,is); } +int read32le(uint32 *Bufo, EMUFILE*is); +inline int read32le(int32 *Bufo, EMUFILE*is) { return read32le((u32*)Bufo,is); } +int read64le(uint64 *Bufo, EMUFILE*is); +inline int read_double_le(double *Bufo, EMUFILE*is) { uint64 temp; int ret = read64le(&temp,is); *Bufo = u64_to_double(temp); return ret; } + + +template +int readle(T *Bufo, EMUFILE*is) +{ + CTASSERT(sizeof(T)==1||sizeof(T)==2||sizeof(T)==4||sizeof(T)==8); + switch(sizeof(T)) { + case 1: return read8le((u8*)Bufo,is); + case 2: return read16le((u16*)Bufo,is); + case 4: return read32le((u32*)Bufo,is); + case 8: return read64le((u64*)Bufo,is); + default: + return 0; + } +} + +template +int writele(T *Bufo, EMUFILE*os) +{ + CTASSERT(sizeof(T)==1||sizeof(T)==2||sizeof(T)==4||sizeof(T)==8); + switch(sizeof(T)) { + case 1: return write8le((u8*)Bufo,os); + case 2: return write16le((u16*)Bufo,os); + case 4: return write32le((u32*)Bufo,os); + case 8: return write64le((u64*)Bufo,os); + default: + return 0; + } +} + +#endif //__FCEU_ENDIAN diff --git a/src/utils/memorystream.h b/src/utils/memorystream.h deleted file mode 100644 index 7c6a3430..00000000 --- a/src/utils/memorystream.h +++ /dev/null @@ -1,302 +0,0 @@ -#ifndef _memorystream_h_ -#define _memorystream_h_ - -#include -#include -#include -#include -#include - -template -class memory_streambuf: public std::streambuf { -private: - - friend class memorystream; - - //the current buffer - T* buf; - - //the current allocated capacity of the buffer - size_t capacity; - - //whether the sequence is owned by the stringbuf - bool myBuf; - - //the logical length of the buffer - size_t length; - - //the current 'write window' starting position within the buffer for writing. - size_t ww; - - //a vector that we have been told to use - std::vector* usevec; - - -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) - , length(0) - , ww(0) - , usevec(0) - { - sync(); - } - - //constructs a non-expandable streambuf around the provided buffer - memory_streambuf(T* usebuf, int buflength) - : buf(usebuf) - , myBuf(false) - , length(buflength) - , ww(0) - , usevec(0) - { - sync(); - } - - //constructs an expandable streambuf around the provided buffer - memory_streambuf(std::vector* _usevec) - : capacity(_usevec->size()) - , myBuf(false) - , length(_usevec->size()) - , ww(0) - , usevec(_usevec) - { - if(length>0) - buf = &(*_usevec)[0]; - else buf = 0; - - sync(); - } - - ~memory_streambuf() - { - //only cleanup if we own the seq - if(myBuf) delete[] buf; - } - - //the logical length of the buffer - size_t size() - { - sync(); - return length; - } - - //to avoid copying, rebuilds the provided vector and copies the streambuf contents into it - void toVector(std::vector& out) - { - out.resize(length); - memcpy(&out[0],buf,length); - } - - //maybe the compiler can avoid copying, but maybe not: returns a vector representing the current streambuf - std::vector toVector() - { - return std::vector(buf,buf+length); - } - - //if the memorystream wraps a vector, the vector will be trimmed to the correct size,. - //you probably need to use this if you are using the vector wrapper - void trim() - { - if(!usevec) return; - usevec->resize(size()); - } - - //tells the current read or write position - std::streampos tell(std::ios::openmode which) - { - if(which == std::ios::in) - return tellRead(); - else if(which == std::ios::out) - return tellWrite(); - else return -1; - } - - //tells the current read position - std::streampos tellRead() - { - return gptr()-eback(); - } - - //tells the current write position - std::streampos tellWrite() - { - return pptr()-pbase() + ww; - } - - int sync() - { - dosync(-1); - return 0; - } - - T* getbuf() - { - sync(); - return buf; - } - - //if we were provided a buffer, then calling this gives us ownership of it - void giveBuf() { - myBuf = true; - } - -private: - - void dosync(int c) - { - size_t wp = tellWrite(); - size_t rp = tellRead(); - - //if we are supposed to insert a character.. - if(c != -1) - { - buf[wp] = c; - wp++; - } - - //the length is determined by the highest character that was ever inserted - length = std::max(length,wp); - - //the write window advances to begin at the current write insertion point - ww = wp; - - //set the new write and read windows - setp(buf+ww, buf + capacity); - setg(buf, buf+rp, buf + length); - } - - void expand(size_t upto) - { - if(!myBuf && !usevec) - throw new std::runtime_error("memory_streambuf is not expandable"); - - size_t newcapacity; - if(upto == -1) - newcapacity = capacity + capacity/2 + 2; - else - newcapacity = std::max(upto,capacity); - - if(newcapacity == capacity) return; - - //if we are supposed to use the vector, then do it now - if(usevec) - { - usevec->resize(newcapacity); - capacity = usevec->size(); - buf = &(*usevec)[0]; - } - else - { - //otherwise, manage our own buffer - T* newbuf = new T[newcapacity]; - memcpy(newbuf,buf,capacity); - delete[] buf; - capacity = newcapacity; - buf = newbuf; - } - } - -protected: - - int overflow(int c) - { - expand(-1); - dosync(c); - return 1; - } - - std::streambuf::pos_type seekpos(pos_type pos, std::ios::openmode which) - { - //extend if we are seeking the write cursor - if(which & std::ios_base::out) - expand(pos); - - sync(); - - if(which & std::ios_base::in) - setg(buf, buf+pos, buf + length); - if(which & std::ios_base::out) - { - ww = pos; - setp(buf+pos, buf + capacity); - } - - return pos; - } - - pos_type seekoff(off_type off, std::ios::seekdir way, std::ios::openmode which) - { - switch(way) { - case std::ios::beg: - return seekpos(off, which); - case std::ios::cur: - return seekpos(tell(which)+off, which); - case std::ios::end: - return seekpos(length+off, which); - default: - return -1; - } - } - -}; - -//an iostream that uses the memory_streambuf to effectively act much like a c# memorystream -//please call sync() after writing data if you want to read it back -class memorystream : public std::basic_iostream > -{ -public: - memorystream() - : 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) - {} - - memorystream(std::vector* usevec) - : std::basic_iostream >(&streambuf) - , streambuf(usevec) - {} - - //the underlying memory_streambuf - memory_streambuf streambuf; - - -public: - - size_t size() { return streambuf.size(); } - char* buf() { return streambuf.getbuf(); } - //flushes all the writing state and ensures the stream is ready for reading - void sync() { streambuf.sync(); } - //rewinds the cursors to offset 0 - void rewind() { streambuf.seekpos(0,std::ios::in | std::ios::out); } - - //if the memorystream wraps a vector, the vector will be trimmed to the correct size,. - //you probably need to use this if you are using the vector wrapper - void trim() { streambuf.trim(); } - - void giveBuf() { streambuf.giveBuf(); } -}; - - -#endif diff --git a/src/utils/xstring.h b/src/utils/xstring.h index 71eea548..a5f1d6b6 100644 --- a/src/utils/xstring.h +++ b/src/utils/xstring.h @@ -24,6 +24,7 @@ #include #include "../types.h" +#include "../emufile.h" #ifndef __GNUC__ #define strcasecmp strcmp @@ -91,8 +92,36 @@ template T templateIntegerDecFromIstream(std::istream* is) return ret; } +template T templateIntegerDecFromIstream(EMUFILE* is) +{ + unsigned int ret = 0; + bool pre = true; + + for(;;) + { + int c = is->fgetc(); + if(c == -1) return ret; + int d = c - '0'; + if((d<0 || d>9)) + { + if(!pre) + break; + } + else + { + pre = false; + ret *= 10; + ret += d; + } + } + is->unget(); + return ret; +} + inline uint32 uint32DecFromIstream(std::istream* is) { return templateIntegerDecFromIstream(is); } inline uint64 uint64DecFromIstream(std::istream* is) { return templateIntegerDecFromIstream(is); } +inline uint32 uint32DecFromIstream(EMUFILE* is) { return templateIntegerDecFromIstream(is); } +inline uint64 uint64DecFromIstream(EMUFILE* is) { return templateIntegerDecFromIstream(is); } //puts an optionally 0-padded decimal integer of type T into the ostream (0-padding is quicker) template void putdec(std::ostream* os, T dec) @@ -116,6 +145,28 @@ template void putdec(std::ostream* os, T dec) os->write(temp,DIGITS); } +//puts an optionally 0-padded decimal integer of type T into the ostream (0-padding is quicker) +template void putdec(EMUFILE* os, T dec) +{ + char temp[DIGITS]; + int ctr = 0; + for(int i=0;ifwrite(temp+DIGITS-ctr-1,ctr+1); + else + os->fwrite(temp,DIGITS); +} + std::string mass_replace(const std::string &source, const std::string &victim, const std::string &replacement); std::wstring mbstowcs(std::string str); diff --git a/vc/vc10_fceux.vcxproj b/vc/vc10_fceux.vcxproj index 62373662..2810b5c9 100644 --- a/vc/vc10_fceux.vcxproj +++ b/vc/vc10_fceux.vcxproj @@ -792,7 +792,6 @@ - diff --git a/vc/vc8_fceux.sln b/vc/vc8_fceux.sln index 9802e9d6..638a5f6e 100644 --- a/vc/vc8_fceux.sln +++ b/vc/vc8_fceux.sln @@ -7,6 +7,8 @@ Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 + Release FastBuild|Win32 = Release FastBuild|Win32 + Release FastBuild|x64 = Release FastBuild|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection @@ -14,6 +16,10 @@ Global {6893EF44-FEA3-46DF-B236-C4C200F54294}.Debug|Win32.ActiveCfg = Debug|Win32 {6893EF44-FEA3-46DF-B236-C4C200F54294}.Debug|Win32.Build.0 = Debug|Win32 {6893EF44-FEA3-46DF-B236-C4C200F54294}.Debug|x64.ActiveCfg = Debug|Win32 + {6893EF44-FEA3-46DF-B236-C4C200F54294}.Release FastBuild|Win32.ActiveCfg = Release Fastbuild|Win32 + {6893EF44-FEA3-46DF-B236-C4C200F54294}.Release FastBuild|Win32.Build.0 = Release Fastbuild|Win32 + {6893EF44-FEA3-46DF-B236-C4C200F54294}.Release FastBuild|x64.ActiveCfg = Release Fastbuild|x64 + {6893EF44-FEA3-46DF-B236-C4C200F54294}.Release FastBuild|x64.Build.0 = Release Fastbuild|x64 {6893EF44-FEA3-46DF-B236-C4C200F54294}.Release|Win32.ActiveCfg = Release|Win32 {6893EF44-FEA3-46DF-B236-C4C200F54294}.Release|Win32.Build.0 = Release|Win32 {6893EF44-FEA3-46DF-B236-C4C200F54294}.Release|x64.ActiveCfg = Release|Win32 diff --git a/vc/vc8_fceux.vcproj b/vc/vc8_fceux.vcproj index 1ddd7587..4c211073 100644 --- a/vc/vc8_fceux.vcproj +++ b/vc/vc8_fceux.vcproj @@ -357,6 +357,180 @@ Name="VCPostBuildEventTool" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -511,6 +685,24 @@ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2897,6 +3417,14 @@ + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - @@ -2335,6 +2326,15 @@ CompileAs="1" /> + + + @@ -2394,7 +2394,7 @@ /> - - @@ -2788,7 +2784,7 @@ />