New savefile backend system (bye bye NONSTANDARD_SAVE...)

svn-id: r6007
This commit is contained in:
Marcus Comstedt 2002-12-17 01:15:13 +00:00
parent fadf55aad0
commit 83da387eef
12 changed files with 314 additions and 132 deletions

View file

@ -155,6 +155,33 @@ static bool tryLoad(char *&buffer, int &size, const char *filename, int vm)
return false;
}
static void tryList(const char *prefix, bool *marks, int num, int vm)
{
struct vmsinfo info;
struct superblock super;
struct dir_iterator iter;
struct dir_entry de;
int pl = strlen(prefix);
if(!vmsfs_check_unit(vm, 0, &info))
return;
if(!vmsfs_get_superblock(&info, &super))
return;
vmsfs_open_dir(&super, &iter);
while(vmsfs_next_dir_entry(&iter, &de))
if(de.entry[0]) {
char buf[16], *endp = NULL;
strncpy(buf, (char *)de.entry+4, 12);
buf[12] = 0;
int l = strlen(buf);
long i = 42;
if(l > pl && !strncmp(buf, prefix, pl) &&
(i = strtol(buf+pl, &endp, 10))>=0 && i<num &&
(endp - buf) == l)
marks[i] = true;
}
}
vmsaveResult writeSaveGame(const char *gamename, const char *data, int size,
const char *filename, class Icon &icon)
{
@ -190,104 +217,130 @@ bool readSaveGame(char *&buffer, int &size, const char *filename)
}
struct vmStreamContext {
class VMSave : public SaveFile {
private:
bool issave;
char *buffer;
int pos, size;
char filename[16];
};
bool SerializerStream::fopen(const char *filename, const char *mode)
{
vmStreamContext *c = new vmStreamContext;
context = c;
if(strchr(mode, 'w')) {
c->issave = true;
strncpy(c->filename, filename, 16);
c->pos = 0;
c->buffer = new char[c->size = MAX_SAVE_SIZE];
return true;
} else if(readSaveGame(c->buffer, c->size, filename)) {
if(c->size > 0 && c->buffer[0] != 'S') {
public:
VMSave(const char *_filename, bool _saveOrLoad)
: issave(_saveOrLoad), pos(0), buffer(NULL)
{
strncpy(filename, _filename, 16);
if(issave)
buffer = new char[size = MAX_SAVE_SIZE];
}
~VMSave();
virtual int fread(void *buf, int size, int cnt);
virtual int fwrite(void *buf, int size, int cnt);
bool readSaveGame()
{ return ::readSaveGame(buffer, size, filename); }
void tryUncompress()
{
if(size > 0 && buffer[0] != 'S') {
// Data does not start with "SCVM". Maybe compressed?
char *expbuf = new char[MAX_SAVE_SIZE];
unsigned long destlen = MAX_SAVE_SIZE;
if(!uncompress((Bytef*)expbuf, &destlen, (Bytef*)c->buffer, c->size)) {
delete(c->buffer);
c->buffer = expbuf;
c->size = destlen;
if(!uncompress((Bytef*)expbuf, &destlen, (Bytef*)buffer, size)) {
delete(buffer);
buffer = expbuf;
size = destlen;
} else delete expbuf;
}
c->issave = false;
c->pos = 0;
return true;
}
};
class VMSaveManager : public SaveFileManager {
virtual SaveFile *open_savefile(const char *filename, bool saveOrLoad);
virtual void list_savefiles(const char *prefix, bool *marks, int num);
};
SaveFile *VMSaveManager::open_savefile(const char *filename,
bool saveOrLoad)
{
VMSave *s = new VMSave(filename, saveOrLoad);
if(saveOrLoad)
return s;
else if(s->readSaveGame()) {
s->tryUncompress();
return s;
} else {
delete c;
context = NULL;
return false;
delete s;
return NULL;
}
}
void SerializerStream::fclose()
VMSave::~VMSave()
{
extern const char *gGameName;
extern Icon icon;
if(context) {
vmStreamContext *c = (vmStreamContext *)context;
if(c->issave) {
if(c->pos) {
// Try compression
char *compbuf = new char[c->pos];
unsigned long destlen = c->pos;
if(!compress((Bytef*)compbuf, &destlen, (Bytef*)c->buffer, c->pos)) {
delete c->buffer;
c->buffer = compbuf;
c->pos = destlen;
} else delete compbuf;
}
displaySaveResult(writeSaveGame(gGameName, c->buffer,
c->pos, c->filename, icon));
if(issave) {
if(pos) {
// Try compression
char *compbuf = new char[pos];
unsigned long destlen = pos;
if(!compress((Bytef*)compbuf, &destlen, (Bytef*)buffer, pos)) {
delete buffer;
buffer = compbuf;
pos = destlen;
} else delete compbuf;
}
delete c->buffer;
delete c;
context = NULL;
displaySaveResult(writeSaveGame(gGameName, buffer,
pos, filename, icon));
}
delete buffer;
}
int SerializerStream::fread(void *buf, int size, int cnt)
int VMSave::fread(void *buf, int sz, int cnt)
{
vmStreamContext *c = (vmStreamContext *)context;
if (!c || c->issave)
if (issave)
return -1;
int nbyt = size*cnt;
if (c->pos + nbyt > c->size) {
cnt = (c->size - c->pos)/size;
nbyt = size*cnt;
int nbyt = sz*cnt;
if (pos + nbyt > size) {
cnt = (size - pos)/sz;
nbyt = sz*cnt;
}
if (nbyt)
memcpy(buf, c->buffer + c->pos, nbyt);
c->pos += nbyt;
memcpy(buf, buffer + pos, nbyt);
pos += nbyt;
return cnt;
}
int SerializerStream::fwrite(void *buf, int size, int cnt)
int VMSave::fwrite(void *buf, int sz, int cnt)
{
vmStreamContext *c = (vmStreamContext *)context;
if (!c || !c->issave)
if (!issave)
return -1;
int nbyt = size*cnt;
if (c->pos + nbyt > c->size) {
cnt = (c->size - c->pos)/size;
nbyt = size*cnt;
int nbyt = sz*cnt;
if (pos + nbyt > size) {
cnt = (size - pos)/sz;
nbyt = sz*cnt;
}
if (nbyt)
memcpy(c->buffer + c->pos, buf, nbyt);
c->pos += nbyt;
memcpy(buffer + pos, buf, nbyt);
pos += nbyt;
return cnt;
}
void VMSaveManager::list_savefiles(const char *prefix,
bool *marks, int num)
{
memset(marks, false, num*sizeof(bool));
for(int i=0; i<24; i++)
tryList(prefix, marks, num, i);
}
SaveFileManager *OSystem_Dreamcast::get_savefile_manager()
{
return new VMSaveManager();
}