aboutsummaryrefslogtreecommitdiff
path: root/engines/wintermute/base/base_persistence_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/wintermute/base/base_persistence_manager.cpp')
-rw-r--r--engines/wintermute/base/base_persistence_manager.cpp196
1 files changed, 129 insertions, 67 deletions
diff --git a/engines/wintermute/base/base_persistence_manager.cpp b/engines/wintermute/base/base_persistence_manager.cpp
index 4cb67b87e1..12bc62d5dc 100644
--- a/engines/wintermute/base/base_persistence_manager.cpp
+++ b/engines/wintermute/base/base_persistence_manager.cpp
@@ -31,13 +31,15 @@
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/base_engine.h"
#include "engines/wintermute/base/base_persistence_manager.h"
-#include "engines/wintermute/base/base_save_thumb_helper.h"
#include "engines/wintermute/platform_osystem.h"
#include "engines/wintermute/math/vector2.h"
#include "engines/wintermute/base/gfx/base_image.h"
+#include "engines/wintermute/base/save_thumb_helper.h"
#include "engines/wintermute/base/sound/base_sound.h"
+#include "engines/wintermute/graphics/transparent_surface.h"
#include "engines/wintermute/wintermute.h"
#include "graphics/decoders/bmp.h"
+#include "graphics/scaler.h"
#include "common/memstream.h"
#include "common/str.h"
#include "common/system.h"
@@ -45,37 +47,50 @@
namespace Wintermute {
-#define SAVE_BUFFER_INIT_SIZE 100000
-#define SAVE_BUFFER_GROW_BY 50000
-
-#define SAVE_MAGIC 0x45564153
-#define SAVE_MAGIC_2 0x32564153
+// The original WME-Lite savegames had the following:
+//#define SAVE_MAGIC 0x45564153
+//#define SAVE_MAGIC_2 0x32564153
+// In case anyone tries to load original savegames, or for that matter
+// in case we ever want to attempt to support original savegames, we
+// avoid those numbers, and use this instead:
+#define SAVE_MAGIC_3 0x12564154
//////////////////////////////////////////////////////////////////////////
BasePersistenceManager::BasePersistenceManager(const char *savePrefix, bool deleteSingleton) {
_saving = false;
-// _buffer = NULL;
-// _bufferSize = 0;
_offset = 0;
- _saveStream = NULL;
- _loadStream = NULL;
+ _saveStream = nullptr;
+ _loadStream = nullptr;
_deleteSingleton = deleteSingleton;
if (BaseEngine::instance().getGameRef()) {
_gameRef = BaseEngine::instance().getGameRef();
} else {
- _gameRef = NULL;
+ _gameRef = nullptr;
}
- _richBuffer = NULL;
+ _richBuffer = nullptr;
_richBufferSize = 0;
- _savedDescription = NULL;
+ _scummVMThumbnailData = nullptr;
+ _scummVMThumbSize = 0;
+
+ _savedDescription = nullptr;
// _savedTimestamp = 0;
_savedVerMajor = _savedVerMinor = _savedVerBuild = 0;
_savedExtMajor = _savedExtMinor = 0;
+ _savedTimestamp.tm_sec = 0;
+ _savedTimestamp.tm_min = 0;
+ _savedTimestamp.tm_hour = 0;
+ _savedTimestamp.tm_mday = 0;
+ _savedTimestamp.tm_mon = 0;
+ _savedTimestamp.tm_year = 0;
+ _savedTimestamp.tm_wday = 0;
+
+ _savedPlayTime = 0;
+
_thumbnailDataSize = 0;
- _thumbnailData = NULL;
+ _thumbnailData = nullptr;
if (savePrefix) {
_savePrefix = savePrefix;
} else if (_gameRef) {
@@ -89,28 +104,21 @@ BasePersistenceManager::BasePersistenceManager(const char *savePrefix, bool dele
//////////////////////////////////////////////////////////////////////////
BasePersistenceManager::~BasePersistenceManager() {
cleanup();
- if (_deleteSingleton && BaseEngine::instance().getGameRef() == NULL)
+ if (_deleteSingleton && BaseEngine::instance().getGameRef() == nullptr)
BaseEngine::destroy();
}
//////////////////////////////////////////////////////////////////////////
void BasePersistenceManager::cleanup() {
- /* if (_buffer) {
- if (_saving) free(_buffer);
- else delete[] _buffer; // allocated by file manager
- }
- _buffer = NULL;
-
- _bufferSize = 0;*/
_offset = 0;
delete[] _richBuffer;
- _richBuffer = NULL;
+ _richBuffer = nullptr;
_richBufferSize = 0;
delete[] _savedDescription;
- _savedDescription = NULL; // ref to buffer
+ _savedDescription = nullptr; // ref to buffer
// _savedTimestamp = 0;
_savedVerMajor = _savedVerMinor = _savedVerBuild = 0;
_savedExtMajor = _savedExtMinor = 0;
@@ -118,25 +126,31 @@ void BasePersistenceManager::cleanup() {
_thumbnailDataSize = 0;
if (_thumbnailData) {
delete[] _thumbnailData;
- _thumbnailData = NULL;
+ _thumbnailData = nullptr;
+ }
+
+ _scummVMThumbSize = 0;
+ if (_scummVMThumbnailData) {
+ delete[] _scummVMThumbnailData;
+ _scummVMThumbnailData = nullptr;
}
delete _loadStream;
delete _saveStream;
- _loadStream = NULL;
- _saveStream = NULL;
+ _loadStream = nullptr;
+ _saveStream = nullptr;
}
Common::String BasePersistenceManager::getFilenameForSlot(int slot) const {
// 3 Digits, to allow for one save-slot for autosave + slot 1 - 100 (which will be numbered 0-99 filename-wise)
- return Common::String::format("%s-save%03d.wsv", _savePrefix.c_str(), slot);
+ return Common::String::format("%s.%03d", _savePrefix.c_str(), slot);
}
void BasePersistenceManager::getSaveStateDesc(int slot, SaveStateDescriptor &desc) {
Common::String filename = getFilenameForSlot(slot);
debugC(kWintermuteDebugSaveGame, "Trying to list savegame %s in slot %d", filename.c_str(), slot);
if (DID_FAIL(readHeader(filename))) {
- warning("getSavedDesc(%d) - Failed for %s", slot, filename.c_str());
+ debugC(kWintermuteDebugSaveGame, "getSavedDesc(%d) - Failed for %s", slot, filename.c_str());
return;
}
desc.setSaveSlot(slot);
@@ -144,13 +158,28 @@ void BasePersistenceManager::getSaveStateDesc(int slot, SaveStateDescriptor &des
desc.setDeletableFlag(true);
desc.setWriteProtectedFlag(false);
- if (_thumbnailDataSize > 0) {
- Common::MemoryReadStream thumbStream(_thumbnailData, _thumbnailDataSize);
+ int thumbSize = 0;
+ byte *thumbData = nullptr;
+ if (_scummVMThumbSize > 0) {
+ thumbSize = _scummVMThumbSize;
+ thumbData = _scummVMThumbnailData;
+ } else if (_thumbnailDataSize > 0) {
+ thumbSize = _thumbnailDataSize;
+ thumbData = _thumbnailData;
+ }
+
+ if (thumbSize > 0) {
+ Common::MemoryReadStream thumbStream(thumbData, thumbSize, DisposeAfterUse::NO);
Graphics::BitmapDecoder bmpDecoder;
if (bmpDecoder.loadStream(thumbStream)) {
- Graphics::Surface *surf = new Graphics::Surface;
- surf = bmpDecoder.getSurface()->convertTo(g_system->getOverlayFormat());
- desc.setThumbnail(surf);
+ const Graphics::Surface *bmpSurface = bmpDecoder.getSurface();
+ TransparentSurface *scaleableSurface = new TransparentSurface(*bmpSurface, false);
+ Graphics::Surface *scaled = scaleableSurface->scale(kThumbnailWidth, kThumbnailHeight2);
+ Graphics::Surface *thumb = scaled->convertTo(g_system->getOverlayFormat());
+ desc.setThumbnail(thumb);
+ delete scaleableSurface;
+ scaled->free();
+ delete scaled;
}
}
@@ -165,13 +194,13 @@ void BasePersistenceManager::deleteSaveSlot(int slot) {
}
uint32 BasePersistenceManager::getMaxUsedSlot() {
- Common::String saveMask = Common::String::format("%s-save???.wsv", _savePrefix.c_str());
+ Common::String saveMask = Common::String::format("%s.???", _savePrefix.c_str());
Common::StringArray saves = g_system->getSavefileManager()->listSavefiles(saveMask);
Common::StringArray::iterator it = saves.begin();
int ret = -1;
for (; it != saves.end(); ++it) {
int num = -1;
- sscanf(it->c_str(), "save%d", &num);
+ sscanf(it->c_str(), ".%d", &num);
ret = MAX(ret, num);
}
return ret;
@@ -199,22 +228,21 @@ bool BasePersistenceManager::initSave(const char *desc) {
if (_saveStream) {
// get thumbnails
if (!_gameRef->_cachedThumbnail) {
- _gameRef->_cachedThumbnail = new BaseSaveThumbHelper(_gameRef);
+ _gameRef->_cachedThumbnail = new SaveThumbHelper(_gameRef);
if (DID_FAIL(_gameRef->_cachedThumbnail->storeThumbnail(true))) {
delete _gameRef->_cachedThumbnail;
- _gameRef->_cachedThumbnail = NULL;
+ _gameRef->_cachedThumbnail = nullptr;
}
}
uint32 magic = DCGF_MAGIC;
putDWORD(magic);
- magic = SAVE_MAGIC_2;
+ magic = SAVE_MAGIC_3;
putDWORD(magic);
byte verMajor, verMinor, extMajor, extMinor;
_gameRef->getVersion(&verMajor, &verMinor, &extMajor, &extMinor);
- //uint32 version = MAKELONG(MAKEWORD(VerMajor, VerMinor), MAKEWORD(ExtMajor, ExtMinor));
_saveStream->writeByte(verMajor);
_saveStream->writeByte(verMinor);
_saveStream->writeByte(extMajor);
@@ -243,10 +271,29 @@ bool BasePersistenceManager::initSave(const char *desc) {
if (!thumbnailOK) {
putDWORD(0);
}
+ thumbnailOK = false;
+ // Again for the ScummVM-thumb:
+ if (_gameRef->_cachedThumbnail) {
+ if (_gameRef->_cachedThumbnail->_scummVMThumb) {
+ Common::MemoryWriteStreamDynamic scummVMthumbStream(DisposeAfterUse::YES);
+ if (_gameRef->_cachedThumbnail->_scummVMThumb->writeBMPToStream(&scummVMthumbStream)) {
+ _saveStream->writeUint32LE(scummVMthumbStream.size());
+ _saveStream->write(scummVMthumbStream.getData(), scummVMthumbStream.size());
+ } else {
+ _saveStream->writeUint32LE(0);
+ }
+
+ thumbnailOK = true;
+ }
+ }
+ if (!thumbnailOK) {
+ putDWORD(0);
+ }
+
// in any case, destroy the cached thumbnail once used
delete _gameRef->_cachedThumbnail;
- _gameRef->_cachedThumbnail = NULL;
+ _gameRef->_cachedThumbnail = nullptr;
uint32 dataOffset = _offset +
sizeof(uint32) + // data offset
@@ -270,7 +317,7 @@ bool BasePersistenceManager::readHeader(const Common::String &filename) {
_saving = false;
_loadStream = g_system->getSavefileManager()->openForLoading(filename);
- //_buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename, &_bufferSize);
+
if (_loadStream) {
uint32 magic;
magic = getDWORD();
@@ -282,28 +329,32 @@ bool BasePersistenceManager::readHeader(const Common::String &filename) {
magic = getDWORD();
- if (magic == SAVE_MAGIC || magic == SAVE_MAGIC_2) {
+ if (magic == SAVE_MAGIC_3) {
_savedVerMajor = _loadStream->readByte();
_savedVerMinor = _loadStream->readByte();
_savedExtMajor = _loadStream->readByte();
_savedExtMinor = _loadStream->readByte();
- if (magic == SAVE_MAGIC_2) {
- _savedVerBuild = (byte)getDWORD();
- _savedName = getStringObj();
-
- // load thumbnail
- _thumbnailDataSize = getDWORD();
- if (_thumbnailDataSize > 0) {
- _thumbnailData = new byte[_thumbnailDataSize];
- if (_thumbnailData) {
- getBytes(_thumbnailData, _thumbnailDataSize);
- } else {
- _thumbnailDataSize = 0;
- }
+ _savedVerBuild = (byte)getDWORD();
+ _savedName = getStringObj();
+
+ // load thumbnail
+ _thumbnailDataSize = getDWORD();
+ if (_thumbnailDataSize > 0) {
+ _thumbnailData = new byte[_thumbnailDataSize];
+ if (_thumbnailData) {
+ getBytes(_thumbnailData, _thumbnailDataSize);
+ } else {
+ _thumbnailDataSize = 0;
}
+ }
+
+ _scummVMThumbSize = getDWORD();
+ _scummVMThumbnailData = new byte[_scummVMThumbSize];
+ if (_scummVMThumbnailData) {
+ getBytes(_scummVMThumbnailData, _scummVMThumbSize);
} else {
- _savedVerBuild = 35; // last build with ver1 savegames
+ _scummVMThumbSize = 0;
}
uint32 dataOffset = getDWORD();
@@ -448,7 +499,7 @@ char *BasePersistenceManager::getString() {
if (!strcmp(ret, "(null)")) {
delete[] ret;
- return NULL;
+ return nullptr;
} else {
return ret;
}
@@ -461,7 +512,7 @@ bool BasePersistenceManager::putTimeDate(const TimeDate &t) {
_saveStream->writeSint32LE(t.tm_mday);
_saveStream->writeSint32LE(t.tm_mon);
_saveStream->writeSint32LE(t.tm_year);
- // _saveStream->writeSint32LE(t.tm_wday); //TODO: Add this in when merging next
+ _saveStream->writeSint32LE(t.tm_wday);
if (_saveStream->err()) {
return STATUS_FAILED;
@@ -477,20 +528,26 @@ TimeDate BasePersistenceManager::getTimeDate() {
t.tm_mday = _loadStream->readSint32LE();
t.tm_mon = _loadStream->readSint32LE();
t.tm_year = _loadStream->readSint32LE();
- // t.tm_wday = _loadStream->readSint32LE(); //TODO: Add this in when merging next
+ t.tm_wday = _loadStream->readSint32LE();
return t;
}
void BasePersistenceManager::putFloat(float val) {
- Common::String str = Common::String::format("F%f", val);
+ int32 exponent = 0;
+ float significand = frexp(val, &exponent);
+ Common::String str = Common::String::format("FS%f", significand);
_saveStream->writeUint32LE(str.size());
_saveStream->writeString(str);
+ _saveStream->writeSint32LE(exponent);
}
float BasePersistenceManager::getFloat() {
char *str = getString();
float value = 0.0f;
- int ret = sscanf(str, "F%f", &value);
+ float significand = 0.0f;
+ int32 exponent = _loadStream->readSint32LE();
+ int ret = sscanf(str, "FS%f", &significand);
+ value = ldexp(significand, exponent);
if (ret != 1) {
warning("%s not parsed as float", str);
}
@@ -499,16 +556,21 @@ float BasePersistenceManager::getFloat() {
}
void BasePersistenceManager::putDouble(double val) {
- Common::String str = Common::String::format("D%f", val);
- str.format("D%f", val);
+ int32 exponent = 0;
+ double significand = frexp(val, &exponent);
+ Common::String str = Common::String::format("DS%f", significand);
_saveStream->writeUint32LE(str.size());
_saveStream->writeString(str);
+ _saveStream->writeSint32LE(exponent);
}
double BasePersistenceManager::getDouble() {
char *str = getString();
- float value = 0.0f; // TODO: Do we ever really need to carry a full double-precision number?
- int ret = sscanf(str, "D%f", &value);
+ double value = 0.0f;
+ float significand = 0.0f;
+ int32 exponent = _loadStream->readSint32LE();
+ int ret = sscanf(str, "DS%f", &significand);
+ value = ldexp(significand, exponent);
if (ret != 1) {
warning("%s not parsed as double", str);
}
@@ -791,7 +853,7 @@ bool BasePersistenceManager::transfer(const char *name, void *val) {
if (_saving) {
SystemClassRegistry::getInstance()->getPointerID(*(void **)val, &classID, &instanceID);
- if (*(void **)val != NULL && (classID == -1 || instanceID == -1)) {
+ if (*(void **)val != nullptr && (classID == -1 || instanceID == -1)) {
debugC(kWintermuteDebugSaveGame, "Warning: invalid instance '%s'", name);
}