unify emufile across emulators

This commit is contained in:
zeromus 2010-11-07 23:33:11 +00:00
parent d8f2b333b7
commit 195528abc5
5 changed files with 356 additions and 71 deletions

View File

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

View File

@ -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 <vector>
@ -13,16 +34,226 @@ bool EMUFILE::readAllBytes(std::vector<u8>* 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<u32>(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<todo;i++)
*dst++ = *src++;
}
else
{
memcpy((void*)ptr,buf()+pos,todo);
}
pos += todo;
if(todo<bytes)
failbit = true;
return todo;
}
void EMUFILE_FILE::truncate(s32 length)
{
EMUFILE_FILE* file;
EMUFILE_MEMORY* mem;
file = dynamic_cast<EMUFILE_FILE*>(fp);
mem = dynamic_cast<EMUFILE_MEMORY*>(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;
}

View File

@ -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 <string>
#include <stdarg.h>
//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 <io.h>
#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<u8>* 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<u8> *underlying) : vec(underlying), ownvec(false), pos(0), len(underlying->size()) { }
EMUFILE_MEMORY(std::vector<u8> *underlying) : vec(underlying), ownvec(false), pos(0), len((s32)underlying->size()) { }
EMUFILE_MEMORY(u32 preallocate) : vec(new std::vector<u8>()), ownvec(true), pos(0), len(0) {
vec->resize(preallocate);
len = preallocate;
}
EMUFILE_MEMORY() : vec(new std::vector<u8>()), ownvec(true), pos(0), len(0) { vec->reserve(8192); }
EMUFILE_MEMORY() : vec(new std::vector<u8>()), ownvec(true), pos(0), len(0) { vec->reserve(1024); }
EMUFILE_MEMORY(void* buf, s32 size) : vec(new std::vector<u8>()), 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<u8>* 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<u32>(remain,(u32)bytes);
memcpy((void*)ptr,buf()+pos,todo);
pos += todo;
if(todo<bytes)
failbit = true;
return todo;
}
virtual size_t _fread(const void *ptr, size_t bytes);
//removing these return values for now so we can find any code that might be using them and make sure
//they handle the return values correctly
virtual void fwrite(const void *ptr, size_t bytes){
reserve(pos+bytes);
reserve(pos+(s32)bytes);
memcpy(buf()+pos,ptr,bytes);
pos += bytes;
pos += (s32)bytes;
len = std::max(pos,len);
}
@ -227,6 +255,8 @@ public:
class EMUFILE_FILE : public EMUFILE {
protected:
FILE* fp;
std::string fname;
char mode[16];
private:
void open(const char* fname, const char* mode)
@ -234,6 +264,8 @@ private:
fp = fopen(fname,mode);
if(!fp)
failbit = true;
this->fname = 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);

16
src/emufile_types.h Normal file
View File

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

View File

@ -3,8 +3,10 @@
#include <iosfwd>
#include <stdio.h>
#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;
}