From 195528abc5b4ec42a1fdb685269aa8bf3015d48a Mon Sep 17 00:00:00 2001 From: zeromus Date: Sun, 7 Nov 2010 23:33:11 +0000 Subject: [PATCH] unify emufile across emulators --- src/drivers/win/replay.cpp | 6 +- src/emufile.cpp | 253 +++++++++++++++++++++++++++++++++++-- src/emufile.h | 128 ++++++++++++------- src/emufile_types.h | 16 +++ src/utils/endian.h | 24 ++-- 5 files changed, 356 insertions(+), 71 deletions(-) create mode 100644 src/emufile_types.h diff --git a/src/drivers/win/replay.cpp b/src/drivers/win/replay.cpp index 76e2e26c..ed226987 100644 --- a/src/drivers/win/replay.cpp +++ b/src/drivers/win/replay.cpp @@ -123,7 +123,7 @@ void UpdateReplayCommentsSubs(const char * fname) { MOVIE_INFO info; FCEUFILE *fp = FCEU_fopen(fname,0,"rb",0); - fp->stream = EMUFILE::memwrap(fp->stream); + fp->stream = fp->stream->memwrap(); bool scanok = FCEUI_MovieGetInfo(fp, info, true); delete fp; @@ -149,7 +149,7 @@ void UpdateReplayDialog(HWND hwndDlg) MOVIE_INFO info; FCEUFILE* fp = FCEU_fopen(fn,0,"rb",0); - fp->stream = EMUFILE::memwrap(fp->stream); + fp->stream = fp->stream->memwrap(); bool isarchive = FCEU_isFileInArchive(fn); bool ismovie = FCEUI_MovieGetInfo(fp, info, false); delete fp; @@ -585,7 +585,7 @@ BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP ArchiveScanRecord asr = FCEUD_ScanArchive(filename); if(!asr.isArchive()) { FCEUFILE* fp = FCEU_fopen(filename,0,"rb",0); - fp->stream = EMUFILE::memwrap(fp->stream); + fp->stream = fp->stream->memwrap(); if(fp) { HandleScan(hwndDlg,fp ,items); delete fp; diff --git a/src/emufile.cpp b/src/emufile.cpp index d07ab65f..fbe004f8 100644 --- a/src/emufile.cpp +++ b/src/emufile.cpp @@ -1,4 +1,25 @@ -#include "types.h" +/* +Copyright (C) 2009-2010 DeSmuME team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + #include "emufile.h" #include @@ -13,16 +34,226 @@ bool EMUFILE::readAllBytes(std::vector* dstbuf, const std::string& fname) return true; } -EMUFILE* EMUFILE::memwrap(EMUFILE* fp) +size_t EMUFILE_MEMORY::_fread(const void *ptr, size_t bytes){ + u32 remain = len-pos; + u32 todo = std::min(remain,(u32)bytes); + if(len==0) + { + failbit = true; + return 0; + } + if(todo<=4) + { + u8* src = buf()+pos; + u8* dst = (u8*)ptr; + for(size_t i=0;i(fp); - mem = dynamic_cast(fp); - if(mem) return mem; - mem = new EMUFILE_MEMORY(file->size()); - if(file->size()==0) return mem; - file->fread(mem->buf(),file->size()); - delete file; + fflush(fp); + #ifdef _MSC_VER + _chsize(_fileno(fp),length); + #else + ftruncate(fileno(fp),length); + #endif + fclose(fp); + fp = NULL; + open(fname.c_str(),mode); +} + + +EMUFILE* EMUFILE_FILE::memwrap() +{ + EMUFILE_MEMORY* mem = new EMUFILE_MEMORY(size()); + if(size()==0) return mem; + fread(mem->buf(),size()); return mem; +} + +EMUFILE* EMUFILE_MEMORY::memwrap() +{ + return this; +} + +void EMUFILE::write64le(u64* val) +{ + write64le(*val); +} + +void EMUFILE::write64le(u64 val) +{ +#ifdef LOCAL_BE + u8 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); + fwrite((char*)&s,8); + return 8; +#else + fwrite(&val,8); +#endif +} + + +size_t EMUFILE::read64le(u64 *Bufo) +{ + u64 buf; + if(fread((char*)&buf,8) != 8) + return 0; +#ifndef LOCAL_BE + *Bufo=buf; +#else + *Bufo = LE_TO_LOCAL_64(buf); +#endif + return 1; +} + +u64 EMUFILE::read64le() +{ + u64 temp; + read64le(&temp); + return temp; +} + +void EMUFILE::write32le(u32* val) +{ + write32le(*val); +} + +void EMUFILE::write32le(u32 val) +{ +#ifdef LOCAL_BE + u8 s[4]; + s[0]=(u8)val; + s[1]=(u8)(val>>8); + s[2]=(u8)(val>>16); + s[3]=(u8)(val>>24); + fwrite(s,4); +#else + fwrite(&val,4); +#endif +} + +size_t EMUFILE::read32le(s32* Bufo) { return read32le((u32*)Bufo); } + +size_t EMUFILE::read32le(u32* Bufo) +{ + u32 buf; + if(fread(&buf,4)<4) + return 0; +#ifndef LOCAL_BE + *(u32*)Bufo=buf; +#else + *(u32*)Bufo=((buf&0xFF)<<24)|((buf&0xFF00)<<8)|((buf&0xFF0000)>>8)|((buf&0xFF000000)>>24); +#endif + return 1; +} + +u32 EMUFILE::read32le() +{ + u32 ret; + read32le(&ret); + return ret; +} + +void EMUFILE::write16le(u16* val) +{ + write16le(*val); +} + +void EMUFILE::write16le(u16 val) +{ +#ifdef LOCAL_BE + u8 s[2]; + s[0]=(u8)val; + s[1]=(u8)(val>>8); + fwrite(s,2); +#else + fwrite(&val,2); +#endif +} + +size_t EMUFILE::read16le(s16* Bufo) { return read16le((u16*)Bufo); } + +size_t EMUFILE::read16le(u16* Bufo) +{ + u32 buf; + if(fread(&buf,2)<2) + return 0; +#ifndef LOCAL_BE + *(u16*)Bufo=buf; +#else + *Bufo = LE_TO_LOCAL_16(buf); +#endif + return 1; +} + +u16 EMUFILE::read16le() +{ + u16 ret; + read16le(&ret); + return ret; +} + +void EMUFILE::write8le(u8* val) +{ + write8le(*val); +} + + +void EMUFILE::write8le(u8 val) +{ + fwrite(&val,1); +} + +size_t EMUFILE::read8le(u8* val) +{ + return fread(val,1); +} + +u8 EMUFILE::read8le() +{ + u8 temp; + fread(&temp,1); + return temp; +} + +void EMUFILE::writedouble(double* val) +{ + write64le(double_to_u64(*val)); +} +void EMUFILE::writedouble(double val) +{ + write64le(double_to_u64(val)); +} + +double EMUFILE::readdouble() +{ + double temp; + readdouble(&temp); + return temp; +} + +size_t EMUFILE::readdouble(double* val) +{ + u64 temp; + size_t ret = read64le(&temp); + *val = u64_to_double(temp); + return ret; } \ No newline at end of file diff --git a/src/emufile.h b/src/emufile.h index cbe793ed..6b2e4a62 100644 --- a/src/emufile.h +++ b/src/emufile.h @@ -1,22 +1,27 @@ - /* Copyright (C) 2009 DeSmuME team - * - * This file is part of DeSmuME - * - * DeSmuME is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * DeSmuME is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with DeSmuME; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +/* +Copyright (C) 2009-2010 DeSmuME team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. */ +//don't use emufile for files bigger than 2GB! you have been warned! some day this will be fixed. + #ifndef EMUFILE_H #define EMUFILE_H @@ -28,19 +33,10 @@ #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 +#include "emufile_types.h" -#ifdef _XBOX -#undef min; -#undef max; +#ifdef _MSC_VER +#include #endif class EMUFILE { @@ -53,14 +49,15 @@ public: {} - //takes control of the provided EMUFILE and returns a new EMUFILE which is guranteed to be in memory - static EMUFILE* memwrap(EMUFILE* fp); + //returns a new EMUFILE which is guranteed to be in memory. the EMUFILE you call this on may be deleted. use the returned EMUFILE in its place + virtual EMUFILE* memwrap() = 0; virtual ~EMUFILE() {} static bool readAllBytes(std::vector* buf, const std::string& fname); - bool fail() { return failbit; } + bool fail(bool unset=false) { bool ret = failbit; if(unset) unfail(); return ret; } + void unfail() { failbit=false; } bool eof() { return size()==ftell(); } @@ -87,10 +84,37 @@ public: virtual void fwrite(const void *ptr, size_t bytes) = 0; + void write64le(u64* val); + void write64le(u64 val); + size_t read64le(u64* val); + u64 read64le(); + void write32le(u32* val); + void write32le(s32* val) { write32le((u32*)val); } + void write32le(u32 val); + size_t read32le(u32* val); + size_t read32le(s32* val); + u32 read32le(); + void write16le(u16* val); + void write16le(s16* val) { write16le((u16*)val); } + void write16le(u16 val); + size_t read16le(s16* Bufo); + size_t read16le(u16* val); + u16 read16le(); + void write8le(u8* val); + void write8le(u8 val); + size_t read8le(u8* val); + u8 read8le(); + void writedouble(double* val); + void writedouble(double val); + double readdouble(); + size_t readdouble(double* val); + virtual int fseek(int offset, int origin) = 0; virtual int ftell() = 0; virtual int size() = 0; + + virtual void truncate(s32 length) = 0; }; //todo - handle read-only specially? @@ -107,12 +131,12 @@ protected: public: - EMUFILE_MEMORY(std::vector *underlying) : vec(underlying), ownvec(false), pos(0), len(underlying->size()) { } + EMUFILE_MEMORY(std::vector *underlying) : vec(underlying), ownvec(false), pos(0), len((s32)underlying->size()) { } EMUFILE_MEMORY(u32 preallocate) : vec(new std::vector()), ownvec(true), pos(0), len(0) { vec->resize(preallocate); len = preallocate; } - EMUFILE_MEMORY() : vec(new std::vector()), ownvec(true), pos(0), len(0) { vec->reserve(8192); } + 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->resize(size); if(size != 0) @@ -123,7 +147,19 @@ public: if(ownvec) delete vec; } - u8* buf() { return &(*vec)[0]; } + virtual EMUFILE* memwrap(); + + virtual void truncate(s32 length) + { + vec->resize(length); + len = length; + if(pos>length) pos=length; + } + + u8* buf() { + if(size()==0) reserve(1); + return &(*vec)[0]; + } std::vector* get_vec() { return vec; }; @@ -173,23 +209,15 @@ public: return 0; } - virtual size_t _fread(const void *ptr, size_t bytes){ - u32 remain = len-pos; - u32 todo = std::min(remain,(u32)bytes); - memcpy((void*)ptr,buf()+pos,todo); - pos += todo; - if(todofname = fname; + strcpy(this->mode,mode); } public: @@ -250,8 +282,12 @@ public: return fp; } + virtual EMUFILE* memwrap(); + bool is_open() { return fp != NULL; } + virtual void truncate(s32 length); + virtual int fprintf(const char *format, ...) { va_list argptr; va_start(argptr, format); diff --git a/src/emufile_types.h b/src/emufile_types.h new file mode 100644 index 00000000..690b861e --- /dev/null +++ b/src/emufile_types.h @@ -0,0 +1,16 @@ +#ifndef EMUFILE_TYPES_H +#define EMUFILE_TYPES_H + +#include "types.h" + +typedef uint8 u8; +typedef uint16 u16; +typedef uint32 u32; +typedef uint64 u64; +typedef int8 s8; +typedef int16 s16; +typedef int32 s32; +typedef int64 s64; + + +#endif //EMUFILE_TYPES_H diff --git a/src/utils/endian.h b/src/utils/endian.h index 1ad58649..026b6e48 100644 --- a/src/utils/endian.h +++ b/src/utils/endian.h @@ -3,8 +3,10 @@ #include #include -#include "../emufile.h" #include "../types.h" +#include "../emufile.h" + +class EMUFILE; inline uint64 double_to_u64(double d) { union { @@ -70,9 +72,9 @@ inline int write_double_le(double b, EMUFILE*is) { uint64 temp = double_to_u64(b int read8le(uint8 *Bufo, EMUFILE*is); int read16le(uint16 *Bufo, EMUFILE*is); -inline int read16le(int16 *Bufo, EMUFILE*is) { return read16le((u16*)Bufo,is); } +inline int read16le(int16 *Bufo, EMUFILE*is) { return read16le((uint16*)Bufo,is); } int read32le(uint32 *Bufo, EMUFILE*is); -inline int read32le(int32 *Bufo, EMUFILE*is) { return read32le((u32*)Bufo,is); } +inline int read32le(int32 *Bufo, EMUFILE*is) { return read32le((uint32*)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; } @@ -82,10 +84,10 @@ 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); + case 1: return read8le((uint8*)Bufo,is); + case 2: return read16le((uint16*)Bufo,is); + case 4: return read32le((uint32*)Bufo,is); + case 8: return read64le((uint64*)Bufo,is); default: return 0; } @@ -96,10 +98,10 @@ 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); + case 1: return write8le((uint8*)Bufo,os); + case 2: return write16le((uint16*)Bufo,os); + case 4: return write32le((uint32*)Bufo,os); + case 8: return write64le((uint64*)Bufo,os); default: return 0; }