finish porting iostream stuff to EMUFILE*. movies and sram-start movies work once again

This commit is contained in:
zeromus 2009-08-26 19:01:21 +00:00
parent e05c17dfbb
commit 41a10c95f5
15 changed files with 89 additions and 411 deletions

View File

@ -18,11 +18,10 @@ libdesmume_a_SOURCES = \
common.cpp common.h \
debug.cpp debug.h driver.h \
Disassembler.cpp Disassembler.h \
dscard.h fat.h FIFO.cpp FIFO.h \
dscard.h emufile.h emufile.cpp fat.h FIFO.cpp FIFO.h \
GPU.cpp GPU.h \
GPU_osd.cpp GPU_osd.h \
mem.h mc.cpp mc.h \
memorystream.h \
path.h \
readwrite.cpp readwrite.h \
wifi.cpp wifi.h \

View File

@ -717,8 +717,6 @@ void GameInfo::populate()
}
}
#ifdef WIN32
#include "memorystream.h"
#include <fstream>
static std::vector<char> buffer;
static std::vector<char> v;

14
desmume/src/emufile.cpp Normal file
View File

@ -0,0 +1,14 @@
#include "types.h"
#include "emufile.h"
#include <vector>
bool EMUFILE::readAllBytes(std::vector<u8>* dstbuf, const std::string& fname)
{
EMUFILE_FILE file(fname.c_str(),"rb");
if(file.fail()) return false;
int size = file.size();
dstbuf->resize(size);
file.fread(&dstbuf->at(0),size);
return true;
}

View File

@ -38,6 +38,7 @@ public:
virtual ~EMUFILE() {}
static bool readAllBytes(std::vector<u8>* buf, const std::string& fname);
bool fail() { return failbit; }
@ -157,7 +158,7 @@ public:
pos += offset;
break;
case SEEK_END:
pos = size()-len;
pos = size()+offset;
break;
default:
assert(false);
@ -195,16 +196,9 @@ public:
}
virtual int fprintf(const char *format, ...) {
//TODO - BLEHHHHHHHH
char temp[1024];
va_list argptr;
va_start(argptr, format);
int ret = ::vsprintf(temp, format, argptr);
if(ret<0 || ret>=1024) {
assert(false);
return -1;
}
fwrite(temp,ret);
int ret = ::vfprintf(fp, format, argptr);
va_end(argptr);
return ret;
};

View File

@ -961,36 +961,36 @@ bool BackupDevice::load_duc(const char* filename)
}
bool BackupDevice::load_movie(std::istream* is) {
bool BackupDevice::load_movie(EMUFILE* is) {
const s32 cookieLen = (s32)strlen(kDesmumeSaveCookie);
is->seekg(-cookieLen, std::ios::end);
is->seekg(-4, std::ios::cur);
is->fseek(-cookieLen, SEEK_END);
is->fseek(-4, SEEK_CUR);
u32 version = 0xFFFFFFFF;
is->read((char*)&version,4);
is->fread((char*)&version,4);
if(version!=0) {
printf("Unknown save file format\n");
return false;
}
is->seekg(-24, std::ios::cur);
is->fseek(-24, SEEK_CUR);
struct{
u32 size,padSize,type,addr_size,mem_size;
}info;
is->read((char*)&info.size,4);
is->read((char*)&info.padSize,4);
is->read((char*)&info.type,4);
is->read((char*)&info.addr_size,4);
is->read((char*)&info.mem_size,4);
is->fread((char*)&info.size,4);
is->fread((char*)&info.padSize,4);
is->fread((char*)&info.type,4);
is->fread((char*)&info.addr_size,4);
is->fread((char*)&info.mem_size,4);
//establish the save data
data.resize(info.size);
is->seekg(0, std::ios::beg);
is->fseek(0, SEEK_SET);
if(info.size>0)
is->read((char*)&data[0],info.size);
is->fread((char*)&data[0],info.size);
state = RUNNING;
addr_size = info.addr_size;

View File

@ -103,7 +103,7 @@ public:
bool load_no_gba(const char *fname);
bool load_raw(const char* filename);
bool save_raw(const char* filename);
bool load_movie(std::istream* is);
bool load_movie(EMUFILE* is);
//call me once a second or so to lazy flush the save data
//here's the reason for this system: we want to dump save files when theyre READ

View File

@ -1,324 +0,0 @@
/* Copyright (C) 2008-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
*/
#ifndef _memorystream_h_
#define _memorystream_h_
#include <iostream>
#include <string.h>
#include <vector>
#include <sstream>
#include <stdexcept>
#include <algorithm>
template<typename T>
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<T>* 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<T>* _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<T>& 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<T> toVector()
{
return std::vector<T>(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;
}
void expand(size_t upto)
{
if(!myBuf && !usevec)
throw new std::runtime_error("memory_streambuf is not expandable");
size_t newcapacity;
if(upto == (size_t)-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;
}
}
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);
}
protected:
int overflow(int c)
{
expand((size_t)-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<char, std::char_traits<char> >
{
public:
memorystream()
: std::basic_iostream<char, std::char_traits<char> >(&streambuf)
{}
memorystream(int sz)
: std::basic_iostream<char, std::char_traits<char> >(&streambuf)
, streambuf(sz)
{}
memorystream(char* usebuf, int buflength)
: std::basic_iostream<char, std::char_traits<char> >(&streambuf)
, streambuf(usebuf, buflength)
{}
memorystream(std::vector<char>* usevec)
: std::basic_iostream<char, std::char_traits<char> >(&streambuf)
, streambuf(usevec)
{}
//the underlying memory_streambuf
memory_streambuf<char> 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(); }
memory_streambuf<char>& getStreambuf() { return streambuf; }
};
#endif

View File

@ -32,7 +32,6 @@
#include "mic.h"
#include "version.h"
#include "GPU_osd.h"
//#include "memorystream.h"
#include "path.h"
#include "emufile.h"
@ -512,50 +511,45 @@ static void openRecordingMovie(const char* fname)
strcpy(curMovieFilename, fname);
}
bool MovieData::loadSramFrom(std::vector<char>* buf)
{//TODO
// memorystream ms(buf);
// MMU_new.backupDevice.load_movie(&ms);
return true;
}
static bool FCEUSS_SaveSRAM(std::ostream* outstream, std:: string fname)
bool MovieData::loadSramFrom(std::vector<u8>* buf)
{
//a temp memory stream. we'll dump some data here and then compress
//TODO - support dumping directly without compressing to save a buffer copy
//TODO
/* memorystream ms;
//size it
FILE * fp = fopen( fname.c_str(), "r" );
if(!fp)
return 0;
fseek( fp, 0, SEEK_END );
int size = ftell(fp);
fclose(fp);
filebuf fb;
fb.open (fname.c_str(), ios::in | ios::binary);//ios::in
istream is(&fb);
char *buffer = new char[size];
is.read(buffer, size);
outstream->write((char*)buffer,size);
fb.close();
*/
EMUFILE_MEMORY ms(buf);
MMU_new.backupDevice.load_movie(&ms);
return true;
}
void MovieData::dumpSramTo(std::vector<char>* buf, std::string sramfname) {
//TODO
// memorystream ms(buf);
// FCEUSS_SaveSRAM(&ms, sramfname);
// ms.trim();
}
//static bool FCEUSS_SaveSRAM(EMUFILE* outstream, const std::string& fname)
//{
// //a temp memory stream. we'll dump some data here and then compress
// //TODO - support dumping directly without compressing to save a buffer copy
////TODO
///* memorystream ms;
//
// //size it
// FILE * fp = fopen( fname.c_str(), "r" );
// if(!fp)
// return 0;
//
// fseek( fp, 0, SEEK_END );
// int size = ftell(fp);
// fclose(fp);
//
// filebuf fb;
// fb.open (fname.c_str(), ios::in | ios::binary);//ios::in
// istream is(&fb);
//
// char *buffer = new char[size];
//
// is.read(buffer, size);
//
// outstream->write((char*)buffer,size);
//
// fb.close();
//*/
//
//
// return true;
//}
//begin recording a new movie
//TODO - BUG - the record-from-another-savestate doesnt work.
@ -589,7 +583,7 @@ void _CDECL_ FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, s
// MovieData::dumpSavestateTo(&currMovieData.savestate,Z_BEST_COMPRESSION);
if(flag == 1)
MovieData::dumpSramTo(&currMovieData.sram, sramfname);
EMUFILE::readAllBytes(&currMovieData.sram, sramfname);
//we are going to go ahead and dump the header. from now on we will only be appending frames
currMovieData.dump(osRecordingMovie, false);

View File

@ -119,8 +119,8 @@ public:
u32 romChecksum;
std::string romSerial;
std::string romFilename;
std::vector<char> savestate;
std::vector<char> sram;
std::vector<u8> savestate;
std::vector<u8> sram;
std::vector<MovieRecord> records;
std::vector<std::wstring> comments;
@ -166,11 +166,10 @@ public:
void clearRecordRange(int start, int len);
void insertEmpty(int at, int frames);
static bool loadSavestateFrom(std::vector<char>* buf);
static void dumpSavestateTo(std::vector<char>* buf, int compressionLevel);
static bool loadSavestateFrom(std::vector<u8>* buf);
static void dumpSavestateTo(std::vector<u8>* buf, int compressionLevel);
static bool loadSramFrom(std::vector<char>* buf);
static void dumpSramTo(std::vector<char>* buf, std::string sramfname);
static bool loadSramFrom(std::vector<u8>* buf);
//void TryDumpIncremental();
private:

View File

@ -37,7 +37,6 @@
#include "GPU_osd.h"
#include "version.h"
#include "memorystream.h"
#include "readwrite.h"
#include "gfx3d.h"
#include "movie.h"

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="Windows-1252"?>
<?xml version="1.0" encoding="shift_jis"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
@ -1242,6 +1242,10 @@
RelativePath="..\dscard.h"
>
</File>
<File
RelativePath="..\emufile.cpp"
>
</File>
<File
RelativePath="..\emufile.h"
>

View File

@ -665,6 +665,10 @@
RelativePath="..\Disassembler.cpp"
>
</File>
<File
RelativePath="..\emufile.cpp"
>
</File>
<File
RelativePath="..\FIFO.cpp"
>
@ -1227,6 +1231,10 @@
RelativePath="..\driver.h"
>
</File>
<File
RelativePath="..\emufile.h"
>
</File>
<File
RelativePath="..\fat.h"
>
@ -1275,10 +1283,6 @@
RelativePath="..\mem.h"
>
</File>
<File
RelativePath="..\memorystream.h"
>
</File>
<File
RelativePath="..\mic.h"
>

View File

@ -118,10 +118,10 @@ static char playfilename[MAX_PATH] = "";
void Describe(HWND hwndDlg)
{
EMUFILE* fp = new EMUFILE_FILE(playfilename,"rb");
EMUFILE_FILE fp(playfilename,"rb");
if(fp.fail()) return;
MovieData md;
LoadFM2(md, fp, INT_MAX, false);
delete fp;
LoadFM2(md, &fp, INT_MAX, false);
u32 num_frames = md.records.size();
@ -241,7 +241,6 @@ INT_PTR CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM
int flag=0;
std::string sramfname;
//Record movie dialog
static INT_PTR CALLBACK RecordDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
@ -249,7 +248,6 @@ static INT_PTR CALLBACK RecordDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
static struct CreateMovieParameters* p = NULL;
std::wstring author = L"";
std::string fname;
int x; //temp vairable
switch(uMsg)
{
case WM_INITDIALOG:
@ -263,6 +261,7 @@ static INT_PTR CALLBACK RecordDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
case IDOK: {
author = GetDlgItemTextW<500>(hwndDlg,IDC_EDIT_AUTHOR);
fname = GetDlgItemText<MAX_PATH>(hwndDlg,IDC_EDIT_FILENAME);
std::string sramfname = GetDlgItemText<MAX_PATH>(hwndDlg,IDC_EDIT_SRAMFILENAME);
if (fname.length())
{
FCEUI_SaveMovie(fname.c_str(), author, flag, sramfname);
@ -332,7 +331,6 @@ static INT_PTR CALLBACK RecordDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
fname.append(".dsv");
*/
SetDlgItemText(hwndDlg, IDC_EDIT_SRAMFILENAME, fname.c_str());
sramfname=(std::string)fname;
}
//if(GetSaveFileName(&ofn))
// UpdateRecordDialogPath(hwndDlg,szChoice);

Binary file not shown.

View File

@ -248,7 +248,6 @@ static void SoundView_SwitchChanOfs(SoundView_DataStruct *data)
static INT_PTR CALLBACK SoundView_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LONG_PTR x;
SoundView_DataStruct *data = (SoundView_DataStruct*)GetWindowLongPtr(hDlg, DWLP_USER);
if((data == NULL) && (uMsg != WM_INITDIALOG))
return 0;