aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backends/dc/vmsave.cpp42
-rw-r--r--common/stream.h6
-rw-r--r--scumm/saveload.cpp6
3 files changed, 43 insertions, 11 deletions
diff --git a/backends/dc/vmsave.cpp b/backends/dc/vmsave.cpp
index 16ea470a53..1ce7c55306 100644
--- a/backends/dc/vmsave.cpp
+++ b/backends/dc/vmsave.cpp
@@ -258,20 +258,25 @@ public:
class OutVMSave : public Common::OutSaveFile {
private:
char *buffer;
- int pos, size;
+ int pos, size, committed;
char filename[16];
+ bool iofailed;
+public:
uint32 write(const void *buf, uint32 cnt);
-public:
OutVMSave(const char *_filename)
- : pos(0)
+ : pos(0), committed(-1), iofailed(false)
{
strncpy(filename, _filename, 16);
buffer = new char[size = MAX_SAVE_SIZE];
}
~OutVMSave();
+
+ bool ioFailed() const { return iofailed; }
+ void clearIOFailed() { iofailed = false; }
+ void flush();
};
class VMSaveManager : public Common::SaveFileManager {
@@ -295,23 +300,38 @@ public:
virtual void listSavefiles(const char *prefix, bool *marks, int num);
};
-OutVMSave::~OutVMSave()
+void OutVMSave::flush()
{
extern const char *gGameName;
extern Icon icon;
+ if(committed >= pos)
+ return;
+
+ char *data = buffer, *compbuf = NULL;
+ int len = pos;
+
if(pos) {
// Try compression
- char *compbuf = new char[pos];
+ 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;
+ data = compbuf;
+ len = destlen;
+ }
}
- displaySaveResult(writeSaveGame(gGameName, buffer,
- pos, filename, icon));
+ vmsaveResult r = writeSaveGame(gGameName, data, len, filename, icon);
+ committed = pos;
+ if(compbuf != NULL)
+ delete[] compbuf;
+ if(r != VMSAVE_OK)
+ iofailed = true;
+ displaySaveResult(r);
+}
+
+OutVMSave::~OutVMSave()
+{
+ flush();
delete[] buffer;
}
diff --git a/common/stream.h b/common/stream.h
index a89e5475dd..32688e08ff 100644
--- a/common/stream.h
+++ b/common/stream.h
@@ -67,6 +67,12 @@ public:
*/
virtual uint32 write(const void *dataPtr, uint32 dataSize) = 0;
+ /**
+ * Commit any buffered data to the underlying channel or
+ * storage medium; unbuffered streams can use the default
+ * implementation.
+ */
+ virtual void flush() {}
// The remaining methods all have default implementations; subclasses
// need not (and should not) overload them.
diff --git a/scumm/saveload.cpp b/scumm/saveload.cpp
index 5252402ec8..3b426358c7 100644
--- a/scumm/saveload.cpp
+++ b/scumm/saveload.cpp
@@ -109,6 +109,12 @@ bool ScummEngine::saveState(int slot, bool compat) {
Serializer ser(0, out, CURRENT_VER);
saveOrLoad(&ser, CURRENT_VER);
+ out->flush();
+ if(out->ioFailed()) {
+ delete out;
+ debug(1, "State save as '%s' FAILED", filename);
+ return false;
+ }
delete out;
debug(1, "State saved as '%s'", filename);
return true;