[Scummvm-cvs-logs] SF.net SVN: scummvm:[41056] scummvm/trunk/engines/gob
drmccoy at users.sourceforge.net
drmccoy at users.sourceforge.net
Sun May 31 04:15:44 CEST 2009
Revision: 41056
http://scummvm.svn.sourceforge.net/scummvm/?rev=41056&view=rev
Author: drmccoy
Date: 2009-05-31 02:15:43 +0000 (Sun, 31 May 2009)
Log Message:
-----------
- A new save system for the GobEngine, one that is not fundamentally broken and is versioned. Unfortunately, this invalidates most save games created on big-endian machines, since endian-issues was a main problem with the old system
- Removed the now superfluous variables sizes
Modified Paths:
--------------
scummvm/trunk/engines/gob/gob.cpp
scummvm/trunk/engines/gob/gob.h
scummvm/trunk/engines/gob/helper.h
scummvm/trunk/engines/gob/inter.cpp
scummvm/trunk/engines/gob/inter.h
scummvm/trunk/engines/gob/inter_v1.cpp
scummvm/trunk/engines/gob/inter_v2.cpp
scummvm/trunk/engines/gob/map_v2.cpp
scummvm/trunk/engines/gob/map_v4.cpp
scummvm/trunk/engines/gob/module.mk
scummvm/trunk/engines/gob/parse.cpp
scummvm/trunk/engines/gob/parse_v1.cpp
scummvm/trunk/engines/gob/parse_v2.cpp
scummvm/trunk/engines/gob/variables.cpp
scummvm/trunk/engines/gob/variables.h
Added Paths:
-----------
scummvm/trunk/engines/gob/save/
scummvm/trunk/engines/gob/save/saveconverter.cpp
scummvm/trunk/engines/gob/save/saveconverter.h
scummvm/trunk/engines/gob/save/saveconverter_v2.cpp
scummvm/trunk/engines/gob/save/saveconverter_v3.cpp
scummvm/trunk/engines/gob/save/saveconverter_v4.cpp
scummvm/trunk/engines/gob/save/saveconverter_v6.cpp
scummvm/trunk/engines/gob/save/savefile.cpp
scummvm/trunk/engines/gob/save/savefile.h
scummvm/trunk/engines/gob/save/savehandler.cpp
scummvm/trunk/engines/gob/save/savehandler.h
scummvm/trunk/engines/gob/save/saveload.cpp
scummvm/trunk/engines/gob/save/saveload.h
scummvm/trunk/engines/gob/save/saveload_v2.cpp
scummvm/trunk/engines/gob/save/saveload_v3.cpp
scummvm/trunk/engines/gob/save/saveload_v4.cpp
scummvm/trunk/engines/gob/save/saveload_v6.cpp
Removed Paths:
-------------
scummvm/trunk/engines/gob/saveload.cpp
scummvm/trunk/engines/gob/saveload.h
scummvm/trunk/engines/gob/saveload_v2.cpp
scummvm/trunk/engines/gob/saveload_v3.cpp
scummvm/trunk/engines/gob/saveload_v4.cpp
scummvm/trunk/engines/gob/saveload_v6.cpp
Modified: scummvm/trunk/engines/gob/gob.cpp
===================================================================
--- scummvm/trunk/engines/gob/gob.cpp 2009-05-31 01:24:08 UTC (rev 41055)
+++ scummvm/trunk/engines/gob/gob.cpp 2009-05-31 02:15:43 UTC (rev 41056)
@@ -47,7 +47,7 @@
#include "gob/parse.h"
#include "gob/scenery.h"
#include "gob/videoplayer.h"
-#include "gob/saveload.h"
+#include "gob/save/saveload.h"
namespace Gob {
@@ -368,7 +368,7 @@
_map = new Map_v2(this);
_goblin = new Goblin_v3(this);
_scenery = new Scenery_v2(this);
- _saveLoad = new SaveLoad_v3(this, _targetName.c_str());
+ _saveLoad = new SaveLoad_v3(this, _targetName.c_str(), SaveLoad_v3::kScreenshotTypeGob3);
break;
case kGameTypeLostInTime:
@@ -382,7 +382,7 @@
_map = new Map_v2(this);
_goblin = new Goblin_v3(this);
_scenery = new Scenery_v2(this);
- _saveLoad = new SaveLoad_v3(this, _targetName.c_str(), 4768, 0, 50);
+ _saveLoad = new SaveLoad_v3(this, _targetName.c_str(), SaveLoad_v3::kScreenshotTypeLost);
break;
case kGameTypeWoodruff:
@@ -413,7 +413,7 @@
_map = new Map_v4(this);
_goblin = new Goblin_v4(this);
_scenery = new Scenery_v2(this);
- _saveLoad = new SaveLoad_v4(this, _targetName.c_str());
+ _saveLoad = new SaveLoad(this, _targetName.c_str());
break;
case kGameTypeAdibou4:
Modified: scummvm/trunk/engines/gob/gob.h
===================================================================
--- scummvm/trunk/engines/gob/gob.h 2009-05-31 01:24:08 UTC (rev 41055)
+++ scummvm/trunk/engines/gob/gob.h 2009-05-31 02:15:43 UTC (rev 41056)
@@ -65,8 +65,8 @@
#define READ_VARO_UINT32(off) _vm->_inter->_variables->readOff32(off)
#define READ_VARO_UINT16(off) _vm->_inter->_variables->readOff16(off)
#define READ_VARO_UINT8(off) _vm->_inter->_variables->readOff8(off)
-#define GET_VAR_STR(var) _vm->_inter->_variables->getAddressVarString(var, 0)
-#define GET_VARO_STR(off) _vm->_inter->_variables->getAddressOffString(off, 0)
+#define GET_VAR_STR(var) _vm->_inter->_variables->getAddressVarString(var)
+#define GET_VARO_STR(off) _vm->_inter->_variables->getAddressOffString(off)
#define GET_VAR_FSTR(var) _vm->_inter->_variables->getAddressVarString(var)
#define GET_VARO_FSTR(off) _vm->_inter->_variables->getAddressOffString(off)
@@ -78,11 +78,14 @@
#define VAR(var) READ_VAR_UINT32(var)
+// WARNING: Reordering these will invalidate save games!
enum Endianness {
kEndiannessLE,
kEndiannessBE
};
+// WARNING: Reordering these will invalidate save games!
+// Add new games to the bottom of the list.
enum GameType {
kGameTypeNone = 0,
kGameTypeGob1,
Modified: scummvm/trunk/engines/gob/helper.h
===================================================================
--- scummvm/trunk/engines/gob/helper.h 2009-05-31 01:24:08 UTC (rev 41055)
+++ scummvm/trunk/engines/gob/helper.h 2009-05-31 02:15:43 UTC (rev 41056)
@@ -49,6 +49,22 @@
return nstr;
}
+/** A strcat that new[]s the buffer. */
+inline char *strdupcat(const char *str1, const char *str2) {
+ if (!str1 || !str2)
+ return 0;
+
+ size_t len1 = strlen(str1);
+ size_t len2 = strlen(str2);
+
+ char *nstr = new char[len1 + len2 + 1];
+
+ memcpy(nstr, str1, len1);
+ memcpy(nstr + len1, str2, len2 + 1);
+
+ return nstr;
+}
+
/** A "smart" reference counting templated class. */
template<typename T>
class ReferenceCounter {
Modified: scummvm/trunk/engines/gob/inter.cpp
===================================================================
--- scummvm/trunk/engines/gob/inter.cpp 2009-05-31 01:24:08 UTC (rev 41055)
+++ scummvm/trunk/engines/gob/inter.cpp 2009-05-31 02:15:43 UTC (rev 41056)
@@ -56,7 +56,6 @@
_soundStopVal = 0;
memset(_varStack, 0, 300);
- memset(_varSizesStack, 0, 300);
_varStackPos = 0;
_noBusyWait = false;
Modified: scummvm/trunk/engines/gob/inter.h
===================================================================
--- scummvm/trunk/engines/gob/inter.h 2009-05-31 01:24:08 UTC (rev 41055)
+++ scummvm/trunk/engines/gob/inter.h 2009-05-31 02:15:43 UTC (rev 41056)
@@ -92,7 +92,6 @@
int16 _animPalDir[8];
byte _varStack[300];
- byte _varSizesStack[300];
int16 _varStackPos;
// The busy-wait detection in o1_keyFunc breaks fast scrolling in Ween
Modified: scummvm/trunk/engines/gob/inter_v1.cpp
===================================================================
--- scummvm/trunk/engines/gob/inter_v1.cpp 2009-05-31 01:24:08 UTC (rev 41055)
+++ scummvm/trunk/engines/gob/inter_v1.cpp 2009-05-31 02:15:43 UTC (rev 41056)
@@ -948,8 +948,7 @@
_vm->_mult->_objects[i].pPosY = new VariableReference(*_vm->_inter->_variables, offPosY);
_vm->_mult->_objects[i].pAnimData =
- (Mult::Mult_AnimData *) _variables->getAddressOff8(offAnim,
- _vm->_global->_inter_animDataSize);
+ (Mult::Mult_AnimData *) _variables->getAddressOff8(offAnim);
_vm->_mult->_objects[i].pAnimData->isStatic = 1;
_vm->_mult->_objects[i].tick = 0;
@@ -2234,7 +2233,7 @@
if (((dataVar >> 2) == 59) && (size == 4))
WRITE_VAR(59, stream->readUint32LE());
else
- retSize = stream->read((byte *) _variables->getAddressOff8(dataVar, size), size);
+ retSize = stream->read((byte *) _variables->getAddressOff8(dataVar), size);
if (retSize == size)
WRITE_VAR(1, 0);
Modified: scummvm/trunk/engines/gob/inter_v2.cpp
===================================================================
--- scummvm/trunk/engines/gob/inter_v2.cpp 2009-05-31 01:24:08 UTC (rev 41055)
+++ scummvm/trunk/engines/gob/inter_v2.cpp 2009-05-31 02:15:43 UTC (rev 41056)
@@ -42,7 +42,7 @@
#include "gob/parse.h"
#include "gob/scenery.h"
#include "gob/video.h"
-#include "gob/saveload.h"
+#include "gob/save/saveload.h"
#include "gob/videoplayer.h"
#include "gob/sound/sound.h"
@@ -890,8 +890,7 @@
_vm->_mult->_objects[i].pPosY = new VariableReference(*_vm->_inter->_variables, offPosY);
_vm->_mult->_objects[i].pAnimData =
- (Mult::Mult_AnimData *) _variables->getAddressOff8(offAnim,
- _vm->_global->_inter_animDataSize);
+ (Mult::Mult_AnimData *) _variables->getAddressOff8(offAnim);
_vm->_mult->_objects[i].pAnimData->isStatic = 1;
_vm->_mult->_objects[i].tick = 0;
@@ -1162,23 +1161,18 @@
varOff = _vm->_parse->parseVarIndex();
_vm->_global->_inter_execPtr++;
- _variables->copyTo(varOff, _varStack + _varStackPos,
- _varSizesStack + _varStackPos,
- _vm->_global->_inter_animDataSize * 4);
+ _variables->copyTo(varOff, _varStack + _varStackPos, _vm->_global->_inter_animDataSize * 4);
_varStackPos += _vm->_global->_inter_animDataSize * 4;
_varStack[_varStackPos] = _vm->_global->_inter_animDataSize * 4;
- _varSizesStack[_varStackPos] = _vm->_global->_inter_animDataSize * 4;
} else {
if (evalExpr(&varOff) != 20)
_vm->_global->_inter_resVal = 0;
memcpy(_varStack + _varStackPos, &_vm->_global->_inter_resVal, 4);
- memcpy(_varSizesStack + _varStackPos, &_vm->_global->_inter_resVal, 4);
_varStackPos += 4;
_varStack[_varStackPos] = 4;
- _varSizesStack[_varStackPos] = 4;
}
}
}
@@ -1186,19 +1180,15 @@
void Inter_v2::o2_popVars() {
byte count;
int16 varOff;
- int16 sizeV;
- int16 sizeS;
+ int16 size;
count = *_vm->_global->_inter_execPtr++;
for (int i = 0; i < count; i++) {
varOff = _vm->_parse->parseVarIndex();
- sizeV = _varStack[--_varStackPos];
- sizeS = _varSizesStack[_varStackPos];
- assert(sizeV == sizeS);
+ size = _varStack[--_varStackPos];
- _varStackPos -= sizeV;
- _variables->copyFrom(varOff, _varStack + _varStackPos,
- _varSizesStack + _varStackPos, sizeV);
+ _varStackPos -= size;
+ _variables->copyFrom(varOff, _varStack + _varStackPos, size);
}
}
@@ -1934,7 +1924,7 @@
size = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
}
- buf = _variables->getAddressOff8(dataVar, size);
+ buf = _variables->getAddressOff8(dataVar);
if (_vm->_global->_inter_resStr[0] == 0) {
WRITE_VAR(1, size);
Modified: scummvm/trunk/engines/gob/map_v2.cpp
===================================================================
--- scummvm/trunk/engines/gob/map_v2.cpp 2009-05-31 01:24:08 UTC (rev 41055)
+++ scummvm/trunk/engines/gob/map_v2.cpp 2009-05-31 02:15:43 UTC (rev 41056)
@@ -56,12 +56,12 @@
uint32 passPos;
var = _vm->_parse->parseVarIndex();
- variables = _vm->_inter->_variables->getAddressOff8(var, 0);
+ variables = _vm->_inter->_variables->getAddressOff8(var);
id = _vm->_inter->load16();
if (id == -1) {
- _passMap = (int8 *) _vm->_inter->_variables->getAddressOff8(var, 0);
+ _passMap = (int8 *) _vm->_inter->_variables->getAddressOff8(var);
return;
}
@@ -105,7 +105,7 @@
tmpPos = mapData.pos();
mapData.seek(passPos);
if ((variables != 0) &&
- (variables != _vm->_inter->_variables->getAddressOff8(0, 0))) {
+ (variables != _vm->_inter->_variables->getAddressOff8(0))) {
_passMap = (int8 *) variables;
mapHeight = _screenHeight / _tilesHeight;
@@ -114,7 +114,7 @@
for (int i = 0; i < mapHeight; i++) {
for (int j = 0; j < mapWidth; j++)
setPass(j, i, mapData.readSByte());
- _vm->_inter->_variables->getAddressOff8(var + i * _passWidth, mapWidth);
+ _vm->_inter->_variables->getAddressOff8(var + i * _passWidth);
}
}
mapData.seek(tmpPos);
Modified: scummvm/trunk/engines/gob/map_v4.cpp
===================================================================
--- scummvm/trunk/engines/gob/map_v4.cpp 2009-05-31 01:24:08 UTC (rev 41055)
+++ scummvm/trunk/engines/gob/map_v4.cpp 2009-05-31 02:15:43 UTC (rev 41056)
@@ -54,7 +54,7 @@
uint32 passPos;
var = _vm->_parse->parseVarIndex();
- variables = _vm->_inter->_variables->getAddressOff8(var, 0);
+ variables = _vm->_inter->_variables->getAddressOff8(var);
id = _vm->_inter->load16();
@@ -62,7 +62,7 @@
warning("Woodruff Stub: loadMapObjects ID >= 65520");
return;
} else if (id == -1) {
- _passMap = (int8 *) _vm->_inter->_variables->getAddressOff8(var, 0);
+ _passMap = (int8 *) _vm->_inter->_variables->getAddressOff8(var);
return;
}
@@ -121,7 +121,7 @@
tmpPos = mapData.pos();
mapData.seek(passPos);
if ((variables != 0) &&
- (variables != _vm->_inter->_variables->getAddressOff8(0, 0))) {
+ (variables != _vm->_inter->_variables->getAddressOff8(0))) {
_passMap = (int8 *) variables;
mapHeight = _screenHeight / _tilesHeight;
@@ -130,7 +130,7 @@
for (int i = 0; i < mapHeight; i++) {
for (int j = 0; j < mapWidth; j++)
setPass(j, i, mapData.readSByte());
- _vm->_inter->_variables->getAddressOff8(var + i * _passWidth, mapWidth);
+ _vm->_inter->_variables->getAddressOff8(var + i * _passWidth);
}
}
mapData.seek(tmpPos);
Modified: scummvm/trunk/engines/gob/module.mk
===================================================================
--- scummvm/trunk/engines/gob/module.mk 2009-05-31 01:24:08 UTC (rev 41055)
+++ scummvm/trunk/engines/gob/module.mk 2009-05-31 02:15:43 UTC (rev 41056)
@@ -46,11 +46,6 @@
parse.o \
parse_v1.o \
parse_v2.o \
- saveload.o \
- saveload_v2.o \
- saveload_v3.o \
- saveload_v4.o \
- saveload_v6.o \
scenery.o \
scenery_v1.o \
scenery_v2.o \
@@ -63,6 +58,18 @@
demos/demoplayer.o \
demos/scnplayer.o \
demos/batplayer.o \
+ save/savefile.o \
+ save/savehandler.o \
+ save/saveload.o \
+ save/saveload_v2.o \
+ save/saveload_v3.o \
+ save/saveload_v4.o \
+ save/saveload_v6.o \
+ save/saveconverter.o \
+ save/saveconverter_v2.o \
+ save/saveconverter_v3.o \
+ save/saveconverter_v4.o \
+ save/saveconverter_v6.o \
sound/sound.o \
sound/sounddesc.o \
sound/pcspeaker.o \
Modified: scummvm/trunk/engines/gob/parse.cpp
===================================================================
--- scummvm/trunk/engines/gob/parse.cpp 2009-05-31 01:24:08 UTC (rev 41055)
+++ scummvm/trunk/engines/gob/parse.cpp 2009-05-31 02:15:43 UTC (rev 41056)
@@ -44,7 +44,7 @@
offset = ptr - _vm->_game->_totFileData;
break;
case kInterVar:
- offset = ptr - ((byte *) _vm->_inter->_variables->getAddressOff8(0, 0));
+ offset = ptr - ((byte *) _vm->_inter->_variables->getAddressOff8(0));
break;
case kResStr:
offset = ptr - ((byte *) _vm->_global->_inter_resStr);
@@ -64,7 +64,7 @@
ptr = _vm->_game->_totFileData;
break;
case kInterVar:
- ptr = (byte *) _vm->_inter->_variables->getAddressOff8(0, 0);
+ ptr = (byte *) _vm->_inter->_variables->getAddressOff8(0);
break;
case kResStr:
ptr = (byte *) _vm->_global->_inter_resStr;
Modified: scummvm/trunk/engines/gob/parse_v1.cpp
===================================================================
--- scummvm/trunk/engines/gob/parse_v1.cpp 2009-05-31 01:24:08 UTC (rev 41055)
+++ scummvm/trunk/engines/gob/parse_v1.cpp 2009-05-31 02:15:43 UTC (rev 41056)
@@ -375,7 +375,7 @@
case OP_LOAD_VAR_STR:
*operPtr = OP_LOAD_IMM_STR;
temp = _vm->_inter->load16() * 4;
- *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8(temp, 0),
+ *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8(temp),
kInterVar);
if (*_vm->_global->_inter_execPtr == 13) {
_vm->_global->_inter_execPtr++;
@@ -404,7 +404,7 @@
break;
}
*valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8(
- temp * 4 + offset * _vm->_global->_inter_animDataSize * 4, 0),
+ temp * 4 + offset * _vm->_global->_inter_animDataSize * 4),
kInterVar);
if (*_vm->_global->_inter_execPtr == 13) {
_vm->_global->_inter_execPtr++;
Modified: scummvm/trunk/engines/gob/parse_v2.cpp
===================================================================
--- scummvm/trunk/engines/gob/parse_v2.cpp 2009-05-31 01:24:08 UTC (rev 41055)
+++ scummvm/trunk/engines/gob/parse_v2.cpp 2009-05-31 02:15:43 UTC (rev 41056)
@@ -554,7 +554,7 @@
*valPtr = (int16) READ_VARO_UINT16(varPos + temp * 2 + offset * 2);
else if (operation == OP_ARRAY_STR) {
*valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8(
- varPos + temp * 4 + offset * _vm->_global->_inter_animDataSize * 4, 0),
+ varPos + temp * 4 + offset * _vm->_global->_inter_animDataSize * 4),
kInterVar);
if (*_vm->_global->_inter_execPtr == 13) {
_vm->_global->_inter_execPtr++;
@@ -612,7 +612,7 @@
case OP_LOAD_VAR_STR:
*operPtr = OP_LOAD_IMM_STR;
temp = _vm->_inter->load16() * 4;
- *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8(varPos + temp, 0), kInterVar);
+ *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8(varPos + temp), kInterVar);
if (*_vm->_global->_inter_execPtr == 13) {
_vm->_global->_inter_execPtr++;
temp += parseValExpr(OP_END_MARKER);
Property changes on: scummvm/trunk/engines/gob/save
___________________________________________________________________
Added: svn:ignore
+ .deps
*.o
lib*.a
Added: scummvm/trunk/engines/gob/save/saveconverter.cpp
===================================================================
--- scummvm/trunk/engines/gob/save/saveconverter.cpp (rev 0)
+++ scummvm/trunk/engines/gob/save/saveconverter.cpp 2009-05-31 02:15:43 UTC (rev 41056)
@@ -0,0 +1,443 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program 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.
+
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/endian.h"
+#include "common/savefile.h"
+
+#include "gob/gob.h"
+#include "gob/save/saveconverter.h"
+#include "gob/save/savefile.h"
+#include "gob/save/savehandler.h"
+#include "gob/helper.h"
+
+namespace Gob {
+
+SaveConverter::SaveConverter(GobEngine *vm, const char *fileName) : _vm(vm) {
+ _fileName = strdupcpy(fileName);
+
+ _data = 0;
+ _stream = 0;
+}
+
+SaveConverter::~SaveConverter() {
+ delete[] _fileName;
+
+ delete _stream;
+ delete[] _data;
+}
+
+void SaveConverter::clear() {
+ delete[] _data;
+ delete _stream;
+
+ _data = 0;
+ _stream = 0;
+}
+
+void SaveConverter::setFileName(const char *fileName) {
+ clear();
+
+ delete[] _fileName;
+
+ _fileName = strdupcpy(fileName);
+}
+
+Common::InSaveFile *SaveConverter::openSave() const {
+ if (!_fileName)
+ return 0;
+
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ return saveMan->openForLoading(_fileName);
+}
+
+void SaveConverter::displayWarning() const {
+ warning("Old save format detected, trying to convert. If this does not work, your "
+ "save is broken and can't be used anymore. Sorry for the inconvenience");
+}
+
+char *SaveConverter::getDescription(const char *fileName) {
+ setFileName(fileName);
+ return getDescription();
+}
+
+char *SaveConverter::getDescription() const {
+ Common::InSaveFile *save;
+
+ // Test if it's an old savd
+ if (!isOldSave(&save) || !save)
+ return 0;
+
+ char *desc = getDescription(*save);
+
+ delete save;
+ return desc;
+}
+
+uint32 SaveConverter::getActualSize(Common::InSaveFile **save) const {
+ Common::InSaveFile *saveFile = openSave();
+
+ if (!saveFile)
+ return false;
+
+ // Is it a valid new save?
+ if (SaveContainer::isSave(*saveFile)) {
+ delete saveFile;
+ return false;
+ }
+
+ int32 saveSize = saveFile->size();
+
+ if (saveSize <= 0) {
+ delete saveFile;
+ return 0;
+ }
+
+ if (save)
+ *save = saveFile;
+ else
+ delete saveFile;
+
+ return saveSize;
+}
+
+bool SaveConverter::swapDataEndian(byte *data, const byte *sizes, uint32 count) {
+ if (!data || !sizes || (count == 0))
+ return false;
+
+ while (count-- > 0) {
+ if (*sizes == 3) // 32bit value (3 additional bytes)
+ *((uint32 *) data) = SWAP_BYTES_32(*((uint32 *) data));
+ else if (*sizes == 1) // 16bit value (1 additional byte)
+ *((uint16 *) data) = SWAP_BYTES_16(*((uint16 *) data));
+ else if (*sizes != 0) // else, it has to be an 8bit value
+ return false;
+
+ count -= *sizes;
+ data += *sizes + 1;
+ sizes += *sizes + 1;
+ }
+
+ return true;
+}
+
+SavePartInfo *SaveConverter::readInfo(Common::SeekableReadStream &stream,
+ uint32 descLength, bool hasSizes) const {
+
+ uint32 varSize = SaveHandler::getVarSize(_vm);
+ if (varSize == 0)
+ return 0;
+
+ char *desc = getDescription(stream);
+ if (!desc)
+ return 0;
+
+ // If it has sizes, skip them
+ if (hasSizes)
+ if (!stream.skip(descLength)) {
+ delete[] desc;
+ return 0;
+ }
+
+ SavePartInfo *info = new SavePartInfo(descLength, (uint32) _vm->getGameType(),
+ 0, _vm->getEndianness(), varSize);
+
+ info->setDesc(desc);
+
+ delete[] desc;
+
+ return info;
+}
+
+byte *SaveConverter::readData(Common::SeekableReadStream &stream,
+ uint32 count, bool endian) const {
+
+ byte *data = new byte[count];
+
+ // Read variable data
+ if (stream.read(data, count) != count) {
+ delete[] data;
+ return 0;
+ }
+
+ /* Check the endianness. The old save data was always written
+ * as little endian, so we might need to swap the bytes. */
+
+ if (endian && (_vm->getEndianness() == kEndiannessBE)) {
+ // Big endian => swapping needed
+
+ // Read variable sizes
+ byte *sizes = new byte[count];
+ if (stream.read(sizes, count) != count) {
+ delete[] data;
+ delete[] sizes;
+ return 0;
+ }
+
+ // Swap bytes
+ if (!swapDataEndian(data, sizes, count)) {
+ delete[] data;
+ delete[] sizes;
+ return 0;
+ }
+
+ delete[] sizes;
+
+ } else {
+ // Little endian => just skip the sizes part
+
+ if (!stream.skip(count)) {
+ delete[] data;
+ return 0;
+ }
+ }
+
+ return data;
+}
+
+SavePartVars *SaveConverter::readVars(Common::SeekableReadStream &stream,
+ uint32 count, bool endian) const {
+
+ byte *data = readData(stream, count, endian);
+ if (!data)
+ return 0;
+
+ SavePartVars *vars = new SavePartVars(_vm, count);
+
+ // Read variables into part
+ if (!vars->readFromRaw(data, count)) {
+ delete[] data;
+ delete vars;
+ return 0;
+ }
+
+ delete[] data;
+ return vars;
+}
+
+SavePartMem *SaveConverter::readMem(Common::SeekableReadStream &stream,
+ uint32 count, bool endian) const {
+
+ byte *data = readData(stream, count, endian);
+ if (!data)
+ return 0;
+
+ SavePartMem *mem = new SavePartMem(count);
+
+ // Read mem into part
+ if (!mem->readFrom(data, 0, count)) {
+ delete[] data;
+ delete mem;
+ return 0;
+ }
+
+ delete[] data;
+ return mem;
+}
+
+SavePartSprite *SaveConverter::readSprite(Common::SeekableReadStream &stream,
+ uint32 width, uint32 height, bool palette) const {
+
+ assert((width > 0) && (height > 0));
+
+ uint32 spriteSize = width * height;
+
+ byte pal[768];
+ if (palette)
+ if (stream.read(pal, 768) != 768)
+ return 0;
+
+ byte *data = new byte[spriteSize];
+
+ // Read variable data
+ if (stream.read(data, spriteSize) != spriteSize) {
+ delete[] data;
+ return 0;
+ }
+
+ SavePartSprite *sprite = new SavePartSprite(width, height);
+
+ if (!sprite->readSpriteRaw(data, spriteSize)) {
+ delete[] data;
+ return 0;
+ }
+
+ delete[] data;
+
+ if (palette)
+ if (!sprite->readPalette(pal))
+ return 0;
+
+ return sprite;
+}
+
+bool SaveConverter::createStream(SaveWriter &writer) {
+ // Allocate memory for the internal new save data
+ uint32 contSize = writer.getSize();
+ _data = new byte[contSize];
+
+ // Save the newly created new save data
+ Common::MemoryWriteStream writeStream(_data, contSize);
+ if (!writer.save(writeStream))
+ return false;
+
+ // Create a reading stream upon that new save data
+ _stream = new Common::MemoryReadStream(_data, contSize);
+
+ return true;
+}
+
+/* Stream functions. If the new save data stream is available, redirect the stream
+ * operations to that stream. Normal stream error behaviour if not. */
+
+bool SaveConverter::err() const {
+ if (!_data || !_stream)
+ return true;
+
+ return _stream->err();
+}
+
+void SaveConverter::clearErr() {
+ if (!_data || !_stream)
+ return;
+
+ _stream->clearErr();
+}
+
+bool SaveConverter::eos() const {
+ if (!_data || !_stream)
+ return true;
+
+ return _stream->eos();
+}
+
+uint32 SaveConverter::read(void *dataPtr, uint32 dataSize) {
+ if (!_data || !_stream)
+ return 0;
+
+ return _stream->read(dataPtr, dataSize);
+}
+
+int32 SaveConverter::pos() const {
+ if (!_data || !_stream)
+ return -1;
+
+ return _stream->pos();
+}
+
+int32 SaveConverter::size() const {
+ if (!_data || !_stream)
+ return -1;
+
+ return _stream->size();
+}
+
+bool SaveConverter::seek(int32 offset, int whence) {
+ if (!_data || !_stream)
+ return false;
+
+ return _stream->seek(offset, whence);
+}
+
+
+SaveConverter_Notes::SaveConverter_Notes(GobEngine *vm, uint32 notesSize,
+ const char *fileName) : SaveConverter(vm, fileName) {
+
+ _size = notesSize;
+}
+
+SaveConverter_Notes::~SaveConverter_Notes() {
+}
+
+int SaveConverter_Notes::isOldSave(Common::InSaveFile **save) const {
+ if (_size == 0)
+ return 0;
+
+ uint32 saveSize = getActualSize(save);
+ if (saveSize == 0)
+ return 0;
+
+ // The size of the old save always follows that rule
+ if (saveSize == (_size * 2))
+ return 1;
+
+ // Not an old save, clean up
+ if (save) {
+ delete *save;
+ *save = 0;
+ }
+
+ return 0;
+}
+
+char *SaveConverter_Notes::getDescription(Common::SeekableReadStream &save) const {
+ return 0;
+}
+
+bool SaveConverter_Notes::loadFail(SavePartVars *vars, Common::InSaveFile *save) {
+ delete vars;
+ delete save;
+
+ clear();
+
+ return false;
+}
+
+// Loads the old save by constructing a new save containing the old save's data
+bool SaveConverter_Notes::load() {
+ if (_size == 0)
+ return false;
+
+ Common::InSaveFile *save;
+
+ // Test if it's an old savd
+ if (!isOldSave(&save) || !save)
+ return false;
+
+ displayWarning();
+
+ SaveWriter writer(1, 0);
+
+ SavePartVars *vars = readVars(*save, _size, false);
+ if (!vars)
+ return loadFail(0, save);
+
+ // We don't need the save anymore
+ delete save;
+
+ // Write all parts
+ if (!writer.writePart(0, vars))
+ return loadFail(0, 0);
+
+ // We don't need this anymore
+ delete vars;
+
+ // Create the final read stream
+ if (!createStream(writer))
+ return loadFail(0, 0);
+
+ return true;
+}
+
+} // End of namespace Gob
Property changes on: scummvm/trunk/engines/gob/save/saveconverter.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Rev Author URL Id
Added: svn:eol-style
+ native
Added: scummvm/trunk/engines/gob/save/saveconverter.h
===================================================================
--- scummvm/trunk/engines/gob/save/saveconverter.h (rev 0)
+++ scummvm/trunk/engines/gob/save/saveconverter.h 2009-05-31 02:15:43 UTC (rev 41056)
@@ -0,0 +1,206 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program 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.
+
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GOB_SAVE_SAVECONVERTER_H
+#define GOB_SAVE_SAVECONVERTER_H
+
+#include "common/stream.h"
+
+namespace Gob {
+
+class GobEngine;
+class SavePartInfo;
+class SavePartVars;
+class SavePartMem;
+class SavePartSprite;
+class SaveWriter;
+
+/** A wrapping stream class for old saves. */
+class SaveConverter : public Common::SeekableReadStream {
+public:
+ SaveConverter(GobEngine *vm, const char *fileName = 0);
+ virtual ~SaveConverter();
+
+ /** Clear the converter. */
+ virtual void clear();
+ /** Set the filename on which to operate. */
+ virtual void setFileName(const char *fileName);
+
+ /** Is it actually an old save? */
+ virtual int isOldSave(Common::InSaveFile **save = 0) const = 0;
+ /** Directly return the description without processing the whole save. */
+ virtual char *getDescription(Common::SeekableReadStream &save) const = 0;
+ /** Load the whole save. */
+ virtual bool load() = 0;
+
+ /** Set the name and return the description. */
+ char *getDescription(const char *fileName);
+ /** Get the current fileName's description. */
+ char *getDescription() const;
+
+ // Stream
+ virtual bool err() const;
+ virtual void clearErr();
+ // ReadStream
+ virtual bool eos() const;
+ virtual uint32 read(void *dataPtr, uint32 dataSize);
+ // SeekableReadStream
+ virtual int32 pos() const;
+ virtual int32 size() const;
+ virtual bool seek(int32 offset, int whence = SEEK_SET);
+
+protected:
+ GobEngine *_vm;
+
+ char *_fileName;
+
+ byte *_data;
+ Common::MemoryReadStream *_stream;
+
+ Common::InSaveFile *openSave() const;
+
+ /** Write a warning to stdout to notify the user what's going on. */
+ virtual void displayWarning() const;
+
+ virtual uint32 getActualSize(Common::InSaveFile **save = 0) const;
+
+ SavePartInfo *readInfo(Common::SeekableReadStream &stream,
+ uint32 descLength, bool hasSizes = true) const;
+ SavePartVars *readVars(Common::SeekableReadStream &stream,
+ uint32 count, bool endian) const;
+ SavePartMem *readMem(Common::SeekableReadStream &stream,
+ uint32 count, bool endian) const;
+ SavePartSprite *readSprite(Common::SeekableReadStream &stream,
+ uint32 width, uint32 height, bool palette) const;
+
+ bool createStream(SaveWriter &writer);
+
+ /** Swap the endianness of the complete data area. */
+ static bool swapDataEndian(byte *data, const byte *sizes, uint32 count);
+
+private:
+ byte *readData(Common::SeekableReadStream &stream,
+ uint32 count, bool endian) const;
+};
+
+/** A wrapper for old notes saves. */
+class SaveConverter_Notes : public SaveConverter {
+public:
+ SaveConverter_Notes(GobEngine *vm, uint32 notesSize, const char *fileName = 0);
+ ~SaveConverter_Notes();
+
+ int isOldSave(Common::InSaveFile **save = 0) const;
+ char *getDescription(Common::SeekableReadStream &save) const;
+
+ bool load();
+
+private:
+ uint32 _size;
+
+ bool loadFail(SavePartVars *vars, Common::InSaveFile *save);
+};
+
+/** A wrapper for old v2-style saves (Gobliins 2, Ween: The Prophecy and Bargon Attack). */
+class SaveConverter_v2 : public SaveConverter {
+public:
+ SaveConverter_v2(GobEngine *vm, const char *fileName = 0);
+ ~SaveConverter_v2();
+
+ int isOldSave(Common::InSaveFile **save = 0) const;
+ char *getDescription(Common::SeekableReadStream &save) const;
+
+ bool load();
+
+private:
+ static const uint32 kSlotCount = 15;
+ static const uint32 kSlotNameLength = 40;
+
+ bool loadFail(SavePartInfo *info, SavePartVars *vars,
+ Common::InSaveFile *save);
+};
+
+/** A wrapper for old v3-style saves (Goblins 3 and Lost in Time). */
+class SaveConverter_v3 : public SaveConverter {
+public:
+ SaveConverter_v3(GobEngine *vm, const char *fileName = 0);
+ ~SaveConverter_v3();
+
+ int isOldSave(Common::InSaveFile **save = 0) const;
+ char *getDescription(Common::SeekableReadStream &save) const;
+
+ bool load();
+
+private:
+ static const uint32 kSlotCount = 30;
+ static const uint32 kSlotNameLength = 40;
+
+ bool loadFail(SavePartInfo *info, SavePartVars *vars,
+ SavePartSprite *sprite, Common::InSaveFile *save);
+
+ void getScreenShotProps(int type,
+ bool &used, uint32 &width, uint32 &height);
+};
+
+/** A wrapper for old v4-style saves (Woodruff). */
+class SaveConverter_v4 : public SaveConverter {
+public:
+ SaveConverter_v4(GobEngine *vm, const char *fileName = 0);
+ ~SaveConverter_v4();
+
+ int isOldSave(Common::InSaveFile **save = 0) const;
+ char *getDescription(Common::SeekableReadStream &save) const;
+
+ bool load();
+
+private:
+ static const uint32 kSlotCount = 60;
+ static const uint32 kSlotNameLength = 40;
+
+ bool loadFail(SavePartInfo *info, SavePartVars *vars,
+ SavePartMem *props, Common::InSaveFile *save);
+};
+
+/** A wrapper for old v6-style saves (Urban Runner). */
+class SaveConverter_v6 : public SaveConverter {
+public:
+ SaveConverter_v6(GobEngine *vm, const char *fileName = 0);
+ ~SaveConverter_v6();
+
+ int isOldSave(Common::InSaveFile **save = 0) const;
+ char *getDescription(Common::SeekableReadStream &save) const;
+
+ bool load();
+
+private:
+ static const uint32 kSlotCount = 15;
+ static const uint32 kSlotNameLength = 40;
+
+ bool loadFail(SavePartInfo *info, SavePartVars *vars,
+ Common::InSaveFile *save);
+};
+
+} // End of namespace Gob
+
+#endif // GOB_SAVE_SAVECONVERTER_H
Property changes on: scummvm/trunk/engines/gob/save/saveconverter.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Rev Author URL Id
Added: svn:eol-style
+ native
Added: scummvm/trunk/engines/gob/save/saveconverter_v2.cpp
===================================================================
--- scummvm/trunk/engines/gob/save/saveconverter_v2.cpp (rev 0)
+++ scummvm/trunk/engines/gob/save/saveconverter_v2.cpp 2009-05-31 02:15:43 UTC (rev 41056)
@@ -0,0 +1,135 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program 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.
+
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/endian.h"
+#include "common/savefile.h"
+
+#include "gob/gob.h"
+#include "gob/save/saveconverter.h"
+#include "gob/save/savefile.h"
+#include "gob/save/savehandler.h"
+
+namespace Gob {
+
+SaveConverter_v2::SaveConverter_v2(GobEngine *vm, const char *fileName) :
+ SaveConverter(vm, fileName) {
+}
+
+SaveConverter_v2::~SaveConverter_v2() {
+}
+
+int SaveConverter_v2::isOldSave(Common::InSaveFile **save) const {
+ uint32 varSize = SaveHandler::getVarSize(_vm);
+ if (varSize == 0)
+ return 0;
+
+ uint32 saveSize = getActualSize(save);
+ if (saveSize == 0)
+ return 0;
+
+ // The size of the old save always follows that rule
+ if (saveSize == (varSize * 2 + kSlotNameLength * 2))
+ return 1;
+
+ // Not an old save, clean up
+ if (save) {
+ delete *save;
+ *save = 0;
+ }
+
+ return 0;
+}
+
+char *SaveConverter_v2::getDescription(Common::SeekableReadStream &save) const {
+ char *desc = new char[kSlotNameLength];
+
+ // Read the description
+ if (save.read(desc, kSlotNameLength) != kSlotNameLength) {
+ delete desc;
+ return 0;
+ }
+
+ return desc;
+}
+
+bool SaveConverter_v2::loadFail(SavePartInfo *info, SavePartVars *vars,
+ Common::InSaveFile *save) {
+
+ delete info;
+ delete vars;
+ delete save;
+
+ clear();
+
+ return false;
+}
+
+// Loads the old save by constructing a new save containing the old save's data
+bool SaveConverter_v2::load() {
+ clear();
+
+ uint32 varSize = SaveHandler::getVarSize(_vm);
+ if (varSize == 0)
+ return false;
+
+ Common::InSaveFile *save;
+
+ // Test if it's an old savd
+ if (!isOldSave(&save) || !save)
+ return false;
+
+ displayWarning();
+
+ SaveWriter writer(2, 0);
+
+ SavePartInfo *info = readInfo(*save, kSlotNameLength);
+ if (!info)
+ return loadFail(0, 0, save);
+
+ SavePartVars *vars = readVars(*save, varSize, true);
+ if (!vars)
+ return loadFail(info, 0, save);
+
+ // We don't need the save anymore
+ delete save;
+
+ // Write all parts
+ if (!writer.writePart(0, info))
+ return loadFail(info, vars, 0);
+ if (!writer.writePart(1, vars))
+ return loadFail(info, vars, 0);
+
+ // We don't need those anymore
+ delete info;
+ delete vars;
+
+ // Create the final read stream
+ if (!createStream(writer))
+ return loadFail(0, 0, 0);
+
+ return true;
+}
+
+} // End of namespace Gob
Property changes on: scummvm/trunk/engines/gob/save/saveconverter_v2.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Rev Author URL Id
Added: svn:eol-style
+ native
Added: scummvm/trunk/engines/gob/save/saveconverter_v3.cpp
===================================================================
--- scummvm/trunk/engines/gob/save/saveconverter_v3.cpp (rev 0)
+++ scummvm/trunk/engines/gob/save/saveconverter_v3.cpp 2009-05-31 02:15:43 UTC (rev 41056)
@@ -0,0 +1,188 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program 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.
+
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/endian.h"
+#include "common/savefile.h"
+
+#include "gob/gob.h"
+#include "gob/save/saveconverter.h"
+#include "gob/save/savefile.h"
+#include "gob/save/savehandler.h"
+
+namespace Gob {
+
+SaveConverter_v3::SaveConverter_v3(GobEngine *vm, const char *fileName) :
+ SaveConverter(vm, fileName) {
+}
+
+SaveConverter_v3::~SaveConverter_v3() {
+}
+
+int SaveConverter_v3::isOldSave(Common::InSaveFile **save) const {
+ uint32 varSize = SaveHandler::getVarSize(_vm);
+ if (varSize == 0)
+ return 0;
+
+ uint32 saveSize = getActualSize(save);
+ if (saveSize == 0)
+ return 0;
+
+ // The size of the old save always follows one of these rules
+ if (saveSize == (varSize * 2 + kSlotNameLength + 1000))
+ return 1; // No screenshot
+ if (saveSize == (varSize * 2 + kSlotNameLength + 1000 + 19968))
+ return 2; // Big screenshot, Goblins 3
+ if (saveSize == (varSize * 2 + kSlotNameLength + 1000 + 4768))
+ return 3; // Small screenshot, Lost in Time
+
+ // Not an old save, clean up
+ if (save) {
+ delete *save;
+ *save = 0;
+ }
+
+ return 0;
+}
+
+char *SaveConverter_v3::getDescription(Common::SeekableReadStream &save) const {
+ // The description starts at 1000
+ if (!save.seek(1000))
+ return 0;
+
+ char *desc = new char[kSlotNameLength];
+
+ // Read the description
+ if (save.read(desc, kSlotNameLength) != kSlotNameLength) {
+ delete desc;
+ return 0;
+ }
+
+ return desc;
+}
+
+bool SaveConverter_v3::loadFail(SavePartInfo *info, SavePartVars *vars,
+ SavePartSprite *sprite, Common::InSaveFile *save) {
+
+ delete info;
+ delete vars;
+ delete sprite;
+ delete save;
+
+ clear();
+
+ return false;
+}
+
+void SaveConverter_v3::getScreenShotProps(int type,
+ bool &used, uint32 &width, uint32 &height) {
+
+ switch (type) {
+ case 2:
+ used = true;
+ width = 120;
+ height = 160;
+ break;
+
+ case 3:
+ used = true;
+ width = 80;
+ height = 50;
+ break;
+
+ default:
+ used = false;
+ width = 0;
+ height = 0;
+ break;
+ }
+}
+
+// Loads the old save by constructing a new save containing the old save's data
+bool SaveConverter_v3::load() {
+ clear();
+
+ uint32 varSize = SaveHandler::getVarSize(_vm);
+ if (varSize == 0)
+ return false;
+
+ Common::InSaveFile *save;
+
+ int type = isOldSave(&save);
+
+ // Test if it's an old savd
+ if ((type == 0) || !save)
+ return false;
+
+ displayWarning();
+
+ bool screenShot;
+ uint32 screenShotWidth;
+ uint32 screenShotHeight;
+
+ getScreenShotProps(type, screenShot, screenShotWidth, screenShotHeight);
+
+ SaveWriter writer(screenShot ? 3 : 2, 0);
+
+ SavePartInfo *info = readInfo(*save, kSlotNameLength, false);
+ if (!info)
+ return loadFail(0, 0, 0, save);
+
+ SavePartVars *vars = readVars(*save, varSize, true);
+ if (!vars)
+ return loadFail(info, 0, 0, save);
+
+ if (screenShot) {
+ SavePartSprite *sprite = readSprite(*save, screenShotWidth, screenShotHeight, true);
+
+ if (!sprite)
+ return loadFail(info, vars, 0, save);
+
+ if (!writer.writePart(2, sprite))
+ return loadFail(info, vars, sprite, save);
+
+ delete sprite;
+ }
+
+ // We don't need the save anymore
+ delete save;
+
+ // Write all parts
+ if (!writer.writePart(0, info))
+ return loadFail(info, vars, 0, 0);
+ if (!writer.writePart(1, vars))
+ return loadFail(info, vars, 0, 0);
+
+ // We don't need those anymore
+ delete info;
+ delete vars;
+
+ // Create the final read stream
+ if (!createStream(writer))
+ return loadFail(0, 0, 0, 0);
+
+ return true;
+}
+
+} // End of namespace Gob
Property changes on: scummvm/trunk/engines/gob/save/saveconverter_v3.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Rev Author URL Id
Added: svn:eol-style
+ native
Added: scummvm/trunk/engines/gob/save/saveconverter_v4.cpp
===================================================================
--- scummvm/trunk/engines/gob/save/saveconverter_v4.cpp (rev 0)
+++ scummvm/trunk/engines/gob/save/saveconverter_v4.cpp 2009-05-31 02:15:43 UTC (rev 41056)
@@ -0,0 +1,147 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program 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.
+
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/endian.h"
+#include "common/savefile.h"
+
+#include "gob/gob.h"
+#include "gob/save/saveconverter.h"
+#include "gob/save/savefile.h"
+#include "gob/save/savehandler.h"
+
+namespace Gob {
+
+SaveConverter_v4::SaveConverter_v4(GobEngine *vm, const char *fileName) :
+ SaveConverter(vm, fileName) {
+}
+
+SaveConverter_v4::~SaveConverter_v4() {
+}
+
+int SaveConverter_v4::isOldSave(Common::InSaveFile **save) const {
+ uint32 varSize = SaveHandler::getVarSize(_vm);
+ if (varSize == 0)
+ return 0;
+
+ uint32 saveSize = getActualSize(save);
+ if (saveSize == 0)
+ return 0;
+
+ // The size of the old save always follows that rule
+ if (saveSize == (varSize * 2 + kSlotNameLength + 1000 + 512000))
+ return 1;
+
+ // Not an old save, clean up
+ if (save) {
+ delete *save;
+ *save = 0;
+ }
+
+ return 0;
+}
+
+char *SaveConverter_v4::getDescription(Common::SeekableReadStream &save) const {
+ // The description starts at 1000
+ if (!save.seek(1000))
+ return 0;
+
+ char *desc = new char[kSlotNameLength];
+
+ // Read the description
+ if (save.read(desc, kSlotNameLength) != kSlotNameLength) {
+ delete desc;
+ return 0;
+ }
+
+ return desc;
+}
+
+bool SaveConverter_v4::loadFail(SavePartInfo *info, SavePartVars *vars,
+ SavePartMem *props, Common::InSaveFile *save) {
+
+ delete info;
+ delete vars;
+ delete props;
+ delete save;
+
+ clear();
+
+ return false;
+}
+
+// Loads the old save by constructing a new save containing the old save's data
+bool SaveConverter_v4::load() {
+ clear();
+
+ uint32 varSize = SaveHandler::getVarSize(_vm);
+ if (varSize == 0)
+ return false;
+
+ Common::InSaveFile *save;
+
+ // Test if it's an old savd
+ if (!isOldSave(&save) || !save)
+ return false;
+
+ displayWarning();
+
+ SaveWriter writer(3, 0);
+
+ SavePartInfo *info = readInfo(*save, kSlotNameLength, false);
+ if (!info)
+ return loadFail(0, 0, 0, save);
+
+ SavePartVars *vars = readVars(*save, varSize, true);
+ if (!vars)
+ return loadFail(info, 0, 0, save);
+
+ SavePartMem *props = readMem(*save, 256000, true);
+ if (!props)
+ return loadFail(info, vars, 0, save);
+
+ // We don't need the save anymore
+ delete save;
+
+ // Write all parts
+ if (!writer.writePart(0, info))
+ return loadFail(info, vars, props, 0);
+ if (!writer.writePart(1, vars))
+ return loadFail(info, vars, props, 0);
+ if (!writer.writePart(2, props))
+ return loadFail(info, vars, props, 0);
+
+ // We don't need those anymore
+ delete info;
+ delete vars;
+ delete props;
+
+ // Create the final read stream
+ if (!createStream(writer))
+ return loadFail(0, 0, 0, 0);
+
+ return true;
+}
+
+} // End of namespace Gob
Property changes on: scummvm/trunk/engines/gob/save/saveconverter_v4.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Rev Author URL Id
Added: svn:eol-style
+ native
Added: scummvm/trunk/engines/gob/save/saveconverter_v6.cpp
===================================================================
--- scummvm/trunk/engines/gob/save/saveconverter_v6.cpp (rev 0)
+++ scummvm/trunk/engines/gob/save/saveconverter_v6.cpp 2009-05-31 02:15:43 UTC (rev 41056)
@@ -0,0 +1,135 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program 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.
+
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/endian.h"
+#include "common/savefile.h"
+
+#include "gob/gob.h"
+#include "gob/save/saveconverter.h"
+#include "gob/save/savefile.h"
+#include "gob/save/savehandler.h"
+
+namespace Gob {
+
+SaveConverter_v6::SaveConverter_v6(GobEngine *vm, const char *fileName) :
+ SaveConverter(vm, fileName) {
+}
+
+SaveConverter_v6::~SaveConverter_v6() {
+}
+
+int SaveConverter_v6::isOldSave(Common::InSaveFile **save) const {
+ uint32 varSize = SaveHandler::getVarSize(_vm);
+ if (varSize == 0)
+ return 0;
+
+ uint32 saveSize = getActualSize(save);
+ if (saveSize == 0)
+ return 0;
+
+ // The size of the old save always follows that rule
+ if (saveSize == (varSize * 2 + kSlotNameLength * 2))
+ return 1;
+
+ // Not an old save, clean up
+ if (save) {
+ delete *save;
+ *save = 0;
+ }
+
+ return 0;
+}
+
+char *SaveConverter_v6::getDescription(Common::SeekableReadStream &save) const {
+ char *desc = new char[kSlotNameLength];
+
+ // Read the description
+ if (save.read(desc, kSlotNameLength) != kSlotNameLength) {
+ delete desc;
+ return 0;
+ }
+
+ return desc;
+}
+
+bool SaveConverter_v6::loadFail(SavePartInfo *info, SavePartVars *vars,
+ Common::InSaveFile *save) {
+
+ delete info;
+ delete vars;
+ delete save;
+
+ clear();
+
+ return false;
+}
+
+// Loads the old save by constructing a new save containing the old save's data
+bool SaveConverter_v6::load() {
+ clear();
+
+ uint32 varSize = SaveHandler::getVarSize(_vm);
+ if (varSize == 0)
+ return false;
+
+ Common::InSaveFile *save;
+
+ // Test if it's an old savd
+ if (!isOldSave(&save) || !save)
+ return false;
+
+ displayWarning();
+
+ SaveWriter writer(2, 0);
+
+ SavePartInfo *info = readInfo(*save, kSlotNameLength);
+ if (!info)
+ return loadFail(0, 0, save);
+
+ SavePartVars *vars = readVars(*save, varSize, true);
+ if (!vars)
+ return loadFail(info, 0, save);
+
+ // We don't need the save anymore
+ delete save;
+
+ // Write all parts
+ if (!writer.writePart(0, info))
+ return loadFail(info, vars, 0);
+ if (!writer.writePart(1, vars))
+ return loadFail(info, vars, 0);
+
+ // We don't need those anymore
+ delete info;
+ delete vars;
+
+ // Create the final read stream
+ if (!createStream(writer))
+ return loadFail(0, 0, 0);
+
+ return true;
+}
+
+} // End of namespace Gob
Property changes on: scummvm/trunk/engines/gob/save/saveconverter_v6.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Rev Author URL Id
Added: svn:eol-style
+ native
Added: scummvm/trunk/engines/gob/save/savefile.cpp
===================================================================
--- scummvm/trunk/engines/gob/save/savefile.cpp (rev 0)
+++ scummvm/trunk/engines/gob/save/savefile.cpp 2009-05-31 02:15:43 UTC (rev 41056)
@@ -0,0 +1,979 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program 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.
+
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/util.h"
+#include "common/endian.h"
+#include "common/system.h"
+#include "common/savefile.h"
+
+#include "gob/gob.h"
+#include "gob/save/savefile.h"
+#include "gob/video.h"
+#include "gob/helper.h"
+#include "gob/inter.h"
+#include "gob/variables.h"
+
+namespace Gob {
+
+static inline bool flushStream(Common::WriteStream &stream) {
+ // Flush and check for errors
+
+ if (!stream.flush())
+ return false;
+ if (stream.err())
+ return false;
+
+ return true;
+}
+
+SaveHeader::SaveHeader(uint32 type, uint32 version, uint32 size) {
+ _type = type;
+ _version = version;
+ _size = size;
+}
+
+bool SaveHeader::read(Common::ReadStream &stream) {
+ // Read the header and verify the global IDs
+ if (stream.readUint32BE() != kID1)
+ return false;
+ if (stream.readUint32BE() != kID2)
+ return false;
+
+ _type = stream.readUint32BE();
+ _version = stream.readUint32LE();
+ _size = stream.readUint32LE();
+
+ return !stream.err();
+}
+
+bool SaveHeader::verify(Common::ReadStream &stream) const {
+ // Compare the header with the stream's content
+
+ if (stream.readUint32BE() != kID1)
+ return false;
+ if (stream.readUint32BE() != kID2)
+ return false;
+ if (stream.readUint32BE() != _type)
+ return false;
+ if (stream.readUint32LE() != _version)
+ return false;
+ if (stream.readUint32LE() != _size)
+ return false;
+
+ return !stream.err();
+}
+
+bool SaveHeader::verifyReadSize(Common::ReadStream &stream) {
+ // Compare the header with the stream's content, expect for the size
+
+ if (stream.readUint32BE() != kID1)
+ return false;
+ if (stream.readUint32BE() != kID2)
+ return false;
+ if (stream.readUint32BE() != _type)
+ return false;
+ if (stream.readUint32LE() != _version)
+ return false;
+
+ // Read the size out of the stream instead
+ _size = stream.readUint32LE();
+
+ return !stream.err();
+}
+
+bool SaveHeader::write(Common::WriteStream &stream) const {
+ stream.writeUint32BE(kID1);
+ stream.writeUint32BE(kID2);
+ stream.writeUint32BE(_type);
+ stream.writeUint32LE(_version);
+ stream.writeUint32LE(_size);
+
+ return flushStream(stream);
+}
+
+uint32 SaveHeader::getType() const {
+ return _type;
+}
+
+uint32 SaveHeader::getVersion() const {
+ return _version;
+}
+
+uint32 SaveHeader::getSize() const {
+ return _size;
+}
+
+void SaveHeader::setType(uint32 type) {
+ _type = type;
+}
+
+void SaveHeader::setVersion(uint32 version) {
+ _version = version;
+}
+
+void SaveHeader::setSize(uint32 size) {
+ _size = size;
+}
+
+SavePart::SavePart() {
+}
+
+SavePart::~SavePart() {
+}
+
+uint32 SavePart::getSize() const {
+ // A part's size is the content's size plus the header's size
+ return _header.getSize() + SaveHeader::kSize;
+}
+
+SavePartMem::SavePartMem(uint32 size) : SavePart(), _size(size) {
+ _header.setType(kID);
+ _header.setVersion(kVersion);
+ _header.setSize(size);
+
+ _data = new byte[size];
+}
+
+SavePartMem::~SavePartMem() {
+ delete[] _data;
+}
+
+bool SavePartMem::read(Common::ReadStream &stream) {
+ if (!_header.verify(stream))
+ return false;
+
+ if (stream.read(_data, _size) != _size)
+ return false;
+
+ return !stream.err();
+}
+
+bool SavePartMem::write(Common::WriteStream &stream) const {
+ if (!_header.write(stream))
+ return false;
+
+ if (stream.write(_data, _size) != _size)
+ return false;
+
+ return flushStream(stream);
+}
+
+bool SavePartMem::readFrom(const byte *data, uint32 offset, uint32 size) {
+ if ((offset + size) > _size)
+ return false;
+
+ memcpy(_data + offset, data, size);
+
+ return true;
+}
+
+bool SavePartMem::writeInto(byte *data, uint32 offset, uint32 size) const {
+ if ((offset + size) > _size)
+ return false;
+
+ memcpy(data, _data + offset, size);
+
+ return true;
+}
+
+SavePartVars::SavePartVars(GobEngine *vm, uint32 size) : SavePart(), _size(size), _vm(vm) {
+ _header.setType(kID);
+ _header.setVersion(kVersion);
+ _header.setSize(size);
+
+ _data = new byte[size];
+}
+
+SavePartVars::~SavePartVars() {
+ delete[] _data;
+}
+
+bool SavePartVars::read(Common::ReadStream &stream) {
+ if (!_header.verify(stream))
+ return false;
+
+ if (stream.read(_data, _size) != _size)
+ return false;
+
+ return !stream.err();
+}
+
+bool SavePartVars::write(Common::WriteStream &stream) const {
+ if (!_header.write(stream))
+ return false;
+
+ if (stream.write(_data, _size) != _size)
+ return false;
+
+ return flushStream(stream);
+}
+
+bool SavePartVars::readFrom(uint32 var, uint32 offset, uint32 size) {
+ if (!_vm->_inter->_variables)
+ return false;
+
+ if ((offset + size) > _size)
+ return false;
+
+ // Get raw variables
+ return _vm->_inter->_variables->copyTo(var, _data + offset, size);
+}
+
+bool SavePartVars::readFromRaw(const byte *data, uint32 size) {
+ if (size != _size)
+ return false;
+
+ memcpy(_data, data, size);
+ return true;
+}
+
+bool SavePartVars::writeInto(uint32 var, uint32 offset, uint32 size) const {
+ if (!_vm->_inter->_variables)
+ return false;
+
+ if ((offset + size) > _size)
+ return false;
+
+ // Write raw variables
+ if (!_vm->_inter->_variables->copyFrom(var, _data + offset, size))
+ return false;
+
+ return true;
+}
+
+SavePartSprite::SavePartSprite(uint32 width, uint32 height) {
+ assert((width > 0) && (height > 0));
+
+ _width = width;
+ _height = height;
+
+ _header.setType(kID);
+ _header.setVersion(kVersion);
+ // width + height + sprite + palette
+ _header.setSize(4 + 4 + _width * _height + 768);
+
+ _dataSprite = new byte[_width * _height];
+ _dataPalette = new byte[768];
+
+ memset(_dataSprite, 0, _width * _height);
+ memset(_dataPalette, 0, 768);
+}
+
+SavePartSprite::~SavePartSprite() {
+ delete[] _dataSprite;
+ delete[] _dataPalette;
+}
+
+bool SavePartSprite::read(Common::ReadStream &stream) {
+ if (!_header.verify(stream))
+ return false;
+
+ // The sprite's dimensions have to fit
+ if (stream.readUint32LE() != _width)
+ return false;
+ if (stream.readUint32LE() != _height)
+ return false;
+
+ // Sprite data
+ if (stream.read(_dataSprite, _width * _height) != (_width * _height))
+ return false;
+
+ // Palette data
+ if (stream.read(_dataPalette, 768) != 768)
+ return false;
+
+ return !stream.err();
+}
+
+bool SavePartSprite::write(Common::WriteStream &stream) const {
+ if (!_header.write(stream))
+ return false;
+
+ // The sprite's dimensions
+ stream.writeUint32LE(_width);
+ stream.writeUint32LE(_height);
+
+ // Sprite data
+ if (stream.write(_dataSprite, _width * _height) != (_width * _height))
+ return false;
+
+ // Palette data
+ if (stream.write(_dataPalette, 768) != 768)
+ return false;
+
+ return flushStream(stream);
+}
+
+bool SavePartSprite::readPalette(const byte *palette) {
+ memcpy(_dataPalette, palette, 768);
+
+ return true;
+}
+
+bool SavePartSprite::readSprite(const SurfaceDesc *sprite) {
+ if (!sprite)
+ return false;
+
+ // The sprite's dimensions have to fit
+ if (((uint32) sprite->getWidth()) != _width)
+ return false;
+ if (((uint32) sprite->getHeight()) != _height)
+ return false;
+
+ memcpy(_dataSprite, sprite->getVidMem(), _width * _height);
+
+ return true;
+}
+
+bool SavePartSprite::readSpriteRaw(const byte *data, uint32 size) {
+ if (size != (_width * _height))
+ return false;
+
+ memcpy(_dataSprite, data, size);
+ return true;
+}
+
+bool SavePartSprite::writePalette(byte *palette) const {
+ memcpy(palette, _dataPalette, 768);
+
+ return true;
+}
+
+bool SavePartSprite::writeSprite(SurfaceDesc *sprite) const {
+ if (!sprite)
+ return false;
+
+ // The sprite's dimensions have to fit
+ if (((uint32) sprite->getWidth()) != _width)
+ return false;
+ if (((uint32) sprite->getHeight()) != _height)
+ return false;
+
+ memcpy(sprite->getVidMem(), _dataSprite, _width * _height);
+
+ return true;
+}
+
+SavePartInfo::SavePartInfo(uint32 descMaxLength, uint32 gameID,
+ uint32 gameVersion, byte endian, uint32 varCount) {
+
+ _header.setType(kID);
+ _header.setVersion(kVersion);
+ // descMaxLength + gameID + gameVersion + endian + varCount
+ _header.setSize(descMaxLength + 4 + 4 + 4 + 1 + 4);
+
+ _descMaxLength = descMaxLength;
+ _gameID = gameID;
+ _gameVersion = gameVersion;
+ _endian = endian;
+ _varCount = varCount;
+
+ _desc = new char[_descMaxLength + 1];
+ memset(_desc, 0, _descMaxLength + 1);
+}
+
+SavePartInfo::~SavePartInfo() {
+ delete[] _desc;
+}
+
+const char *SavePartInfo::getDesc() const {
+ return _desc;
+}
+
+uint32 SavePartInfo::getDescMaxLength() const {
+ return _descMaxLength;
+}
+
+void SavePartInfo::setVarCount(uint32 varCount) {
+ _varCount = varCount;
+}
+
+void SavePartInfo::setDesc(const char *desc) {
+ if (!desc) {
+ memset(_desc, 0, _descMaxLength + 1);
+ return;
+ }
+
+ uint32 n = MIN<uint32>(strlen(desc), _descMaxLength);
+
+ // Copy the description and fill with 0
+ memcpy(_desc, desc, n);
+ memset(_desc + n, 0, _descMaxLength + 1 - n);
+}
+
+void SavePartInfo::setDesc(const byte *desc, uint32 size) {
+ if (!desc || !size) {
+ memset(_desc, 0, _descMaxLength + 1);
+ return;
+ }
+
+ uint32 n = MIN<uint32>(size, _descMaxLength);
+ memcpy(_desc, desc, n);
+ memset(_desc + n, 0, _descMaxLength + 1 - n);
+}
+
+bool SavePartInfo::read(Common::ReadStream &stream) {
+ if (!_header.verify(stream))
+ return false;
+
+ if (stream.readUint32LE() != _gameID)
+ return false;
+ if (stream.readUint32LE() != _gameVersion)
+ return false;
+ if (stream.readByte() != _endian)
+ return false;
+ if (stream.readUint32LE() != _varCount)
+ return false;
+ if (stream.readUint32LE() != _descMaxLength)
+ return false;
+
+ if (stream.read(_desc, _descMaxLength) != _descMaxLength)
+ return false;
+
+ _desc[_descMaxLength] = 0;
+
+ return !stream.err();
+}
+
+bool SavePartInfo::write(Common::WriteStream &stream) const {
+ if (!_header.write(stream))
+ return false;
+
+ stream.writeUint32LE(_gameID);
+ stream.writeUint32LE(_gameVersion);
+ stream.writeByte(_endian);
+ stream.writeUint32LE(_varCount);
+ stream.writeUint32LE(_descMaxLength);
+
+ if (stream.write(_desc, _descMaxLength) != _descMaxLength)
+ return false;
+
+ return flushStream(stream);
+}
+
+SaveContainer::Part::Part(uint32 s) {
+ size = s;
+ data = new byte[size];
+}
+
+SaveContainer::Part::~Part() {
+ delete[] data;
+}
+
+Common::WriteStream *SaveContainer::Part::createWriteStream() {
+ return new Common::MemoryWriteStream(data, size);
+}
+
+Common::ReadStream *SaveContainer::Part::createReadStream() const {
+ return new Common::MemoryReadStream(data, size);
+}
+
+SaveContainer::SaveContainer(uint32 partCount, uint32 slot) {
+ assert(partCount > 0);
+
+ _slot = slot;
+ _partCount = partCount;
+
+ _parts.resize(partCount);
+ for (PartIterator it = _parts.begin(); it != _parts.end(); ++it)
+ *it = 0;
+
+ _header.setType(kID);
+ _header.setVersion(kVersion);
+ _header.setSize(4); // uint32 # of parts
+}
+
+SaveContainer::~SaveContainer() {
+ clear();
+}
+
+uint32 SaveContainer::getSlot() const {
+ return _slot;
+}
+
+uint32 SaveContainer::getSize() const {
+ return _header.getSize() + SaveHeader::kSize;
+}
+
+bool SaveContainer::hasAllParts() const {
+ for (PartConstIterator it = _parts.begin(); it != _parts.end(); ++it)
+ if (!*it)
+ return false;
+
+ return true;
+}
+
+uint32 SaveContainer::calcSize() const {
+ uint32 size = 4; // uint32 # of parts
+
+ for (PartConstIterator it = _parts.begin(); it != _parts.end(); ++it)
+ if (*it)
+ // uint32 part size
+ size += (*it)->size + 4;
+
+ return size;
+}
+
+void SaveContainer::clear() {
+ for (PartIterator it = _parts.begin(); it != _parts.end(); ++it) {
+ Part *&p = *it;
+
+ delete p;
+ p = 0;
+ }
+}
+
+bool SaveContainer::writePart(uint32 partN, const SavePart *part) {
+ // Sanity checks
+ if (!part)
+ return false;
+ if (partN >= _partCount)
+ return false;
+
+ Part *&p = _parts[partN];
+
+ delete p;
+ // Create the part
+ p = new Part(part->getSize());
+
+ Common::WriteStream *pStream = p->createWriteStream();
+
+ // Write
+ if (!part->write(*pStream)) {
+ delete p;
+ p = 0;
+
+ delete pStream;
+ return false;
+ }
+
+ delete pStream;
+
+ // Update size
+ _header.setSize(calcSize());
+
+ return true;
+}
+
+bool SaveContainer::readPart(uint32 partN, SavePart *part) const {
+ // Sanity checks
+ if (!part)
+ return false;
+ if (partN >= _partCount)
+ return false;
+
+ const Part * const &p = _parts[partN];
+
+ // Check if the part actually exists
+ if (!p)
+ return false;
+
+ Common::ReadStream *pStream = p->createReadStream();
+
+ // Read
+ if (!part->read(*pStream)) {
+ delete pStream;
+ return false;
+ }
+
+ delete pStream;
+ return true;
+}
+
+bool SaveContainer::readPartHeader(uint32 partN, SaveHeader *header) const {
+ // Sanity checks
+ if (!header)
+ return false;
+ if (partN >= _partCount)
+ return false;
+
+ const Part * const &p = _parts[partN];
+
+ // Check if the part actually exists
+ if (!p)
+ return false;
+
+ Common::ReadStream *pStream = p->createReadStream();
+
+ // Read
+ if (!header->read(*pStream)) {
+ delete pStream;
+ return false;
+ }
+
+ delete pStream;
+ return true;
+}
+
+bool SaveContainer::read(Common::ReadStream &stream) {
+ // Verify the header and get the container's size
+ if (!_header.verifyReadSize(stream))
+ return false;
+
+ // The part count has to be correct
+ if (stream.readUint32LE() != _partCount)
+ return false;
+
+ // Iterate over all parts
+ for (PartIterator it = _parts.begin(); it != _parts.end(); ++it) {
+ // Read the size
+ uint32 size = stream.readUint32LE();
+
+ if (stream.err()) {
+ clear();
+ return false;
+ }
+
+ Part *&p = *it;
+
+ delete p;
+ // Create a suitable part
+ p = new Part(size);
+ }
+
+ // Update size
+ _header.setSize(calcSize());
+
+ // Iterate over all parts
+ for (PartIterator it = _parts.begin(); it != _parts.end(); ++it) {
+ Part *&p = *it;
+
+ // Read the part
+ if (stream.read(p->data, p->size) != p->size) {
+ clear();
+ return false;
+ }
+ }
+
+ return !stream.err();
+}
+
+bool SaveContainer::write(Common::WriteStream &stream) const {
+ // Write the header
+ if (!_header.write(stream))
+ return false;
+
+ // Write the part count
+ stream.writeUint32LE(_partCount);
+
+ // Iterate over all parts
+ for (PartConstIterator it = _parts.begin(); it != _parts.end(); ++it) {
+ // Part doesn't actually exist => error
+ if (!*it)
+ return false;
+
+ // Write the part's size
+ stream.writeUint32LE((*it)->size);
+ }
+
+ if (!flushStream(stream))
+ return false;
+
+ // Iterate over all parts
+ for (PartConstIterator it = _parts.begin(); it != _parts.end(); ++it) {
+ Part * const &p = *it;
+
+ // Write the part
+ if (stream.write(p->data, p->size) != p->size)
+ return false;
+ }
+
+ return flushStream(stream);
+}
+
+Common::Array<SaveContainer::PartInfo> *SaveContainer::getPartsInfo(Common::SeekableReadStream &stream) {
+ Common::Array<PartInfo> *parts = 0;
+
+ // Remember the stream's position to seek back to
+ uint32 startPos = stream.pos();
+
+ SaveHeader header;
+
+ header.setType(kID);
+ header.setVersion(kVersion);
+
+ // Verify the header
+ if (!header.verifyReadSize(stream)) {
+ // Seek back
+ stream.seek(startPos);
+ return 0;
+ }
+
+ // Read the part count
+ uint32 partCount = stream.readUint32LE();
+
+ // Create a part information array
+ parts = new Common::Array<PartInfo>;
+ parts->resize(partCount);
+
+ // Read all part sizes
+ for (uint32 i = 0; i < partCount; i++)
+ (*parts)[i].size = stream.readUint32LE();
+
+ // Iterate over all parts
+ for (uint32 i = 0; i < partCount; i++) {
+ // The part's offset (from the starting point of the stream)
+ (*parts)[i].offset = stream.pos() - startPos;
+
+ SaveHeader partHeader;
+
+ // Read the header
+ if (!partHeader.read(stream)) {
+ // Seek back
+ stream.seek(startPos);
+ delete parts;
+ return 0;
+ }
+
+ // Fill in the ID
+ (*parts)[i].id = partHeader.getType();
+
+ // Skip the part's content
+ stream.skip(partHeader.getSize());
+ }
+
+ if (stream.err()) {
+ delete parts;
+ parts = 0;
+ }
+
+ // Seek back
+ stream.seek(startPos);
+
+ return parts;
+}
+
+bool SaveContainer::isSave(Common::SeekableReadStream &stream) {
+ // Remember the stream's position to seek back to
+ uint32 startPos = stream.pos();
+
+ SaveHeader header;
+
+ header.setType(kID);
+ header.setVersion(kVersion);
+
+ bool result = header.verifyReadSize(stream);
+
+ // Seek back
+ stream.seek(startPos);
+
+ return result;
+}
+
+
+SaveReader::SaveReader(uint32 partCount, uint32 slot, const char *fileName) :
+ SaveContainer(partCount, slot) {
+
+ _fileName = strdupcpy(fileName);
+ _stream = 0;
+
+ _loaded = false;
+}
+
+SaveReader::SaveReader(uint32 partCount, uint32 slot, Common::SeekableReadStream &stream) :
+ SaveContainer(partCount, slot) {
+
+ _fileName = 0;
+ _stream = &stream;
+
+ _loaded = false;
+}
+
+SaveReader::~SaveReader() {
+ delete[] _fileName;
+}
+
+// Open the save and read it
+bool SaveReader::load() {
+
+ Common::InSaveFile *in = 0;
+ Common::SeekableReadStream *stream;
+
+ if (_fileName) {
+ in = openSave();
+
+ if (!in)
+ return false;
+
+ stream = in;
+ } else if (_stream)
+ stream = _stream;
+ else
+ return false;
+
+ if (!SaveContainer::read(*stream)) {
+ delete in;
+ return false;
+ }
+
+ delete in;
+ _loaded = true;
+ return true;
+}
+
+bool SaveReader::readPartHeader(uint32 partN, SaveHeader *header) const {
+ // The save has to be loaded
+ if (!_loaded)
+ return false;
+
+ return SaveContainer::readPartHeader(partN, header);
+}
+
+bool SaveReader::readPart(uint32 partN, SavePart *part) const {
+ // The save has to be loaded
+ if (!_loaded)
+ return false;
+
+ if (!SaveContainer::readPart(partN, part))
+ return false;
+
+ return true;
+}
+
+Common::InSaveFile *SaveReader::openSave(const char *fileName) {
+ if (!fileName)
+ return 0;
+
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ return saveMan->openForLoading(fileName);
+}
+
+Common::InSaveFile *SaveReader::openSave() {
+ return openSave(_fileName);
+}
+
+bool SaveReader::getInfo(Common::SeekableReadStream &stream, SavePartInfo &info) {
+ // Remeber the stream's starting position to seek back to
+ uint32 startPos = stream.pos();
+
+ // Get parts' basic information
+ Common::Array<SaveContainer::PartInfo> *partsInfo = getPartsInfo(stream);
+
+ // No parts => fail
+ if (!partsInfo) {
+ stream.seek(startPos);
+ return false;
+ }
+
+ bool result = false;
+ // Iterate over all parts
+ for (Common::Array<SaveContainer::PartInfo>::iterator it = partsInfo->begin();
+ it != partsInfo->end(); ++it) {
+
+ // Check for the info part
+ if (it->id == SavePartInfo::kID) {
+ if (!stream.seek(it->offset))
+ break;
+
+ // Read it
+ result = info.read(stream);
+ break;
+ }
+ }
+
+ stream.seek(startPos);
+
+ delete partsInfo;
+ return result;
+}
+
+bool SaveReader::getInfo(const char *fileName, SavePartInfo &info) {
+ Common::InSaveFile *in = openSave(fileName);
+
+ if (!in)
+ return false;
+
+ bool result = getInfo(*in, info);
+
+ delete in;
+
+ return result;
+}
+
+SaveWriter::SaveWriter(uint32 partCount, uint32 slot, const char *fileName) :
+ SaveContainer(partCount, slot) {
+
+ _fileName = strdupcpy(fileName);
+}
+
+SaveWriter::~SaveWriter() {
+ delete[] _fileName;
+}
+
+bool SaveWriter::writePart(uint32 partN, const SavePart *part) {
+ // Write the part
+ if (!SaveContainer::writePart(partN, part))
+ return false;
+
+ // If all parts have been written, save and clear
+ if (hasAllParts() && canSave()) {
+ if (save()) {
+ clear();
+ return true;
+ }
+
+ return false;
+ }
+
+ return true;
+}
+
+bool SaveWriter::save(Common::WriteStream &stream) {
+ return SaveContainer::write(stream);
+}
+
+bool SaveWriter::save() {
+ Common::OutSaveFile *out = openSave();
+
+ if (!out)
+ return false;
+
+ bool success = save(*out);
+
+ delete out;
+
+ return success;
+}
+
+bool SaveWriter::canSave() const {
+ if (!_fileName)
+ return false;
+
+ return true;
+}
+
+Common::OutSaveFile *SaveWriter::openSave(const char *fileName) {
+ if (!fileName)
+ return 0;
+
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ return saveMan->openForSaving(fileName);
+}
+
+Common::OutSaveFile *SaveWriter::openSave() {
+ return openSave(_fileName);
+}
+
+} // End of namespace Gob
Property changes on: scummvm/trunk/engines/gob/save/savefile.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Rev Author URL Id
Added: svn:eol-style
+ native
Added: scummvm/trunk/engines/gob/save/savefile.h
===================================================================
--- scummvm/trunk/engines/gob/save/savefile.h (rev 0)
+++ scummvm/trunk/engines/gob/save/savefile.h 2009-05-31 02:15:43 UTC (rev 41056)
@@ -0,0 +1,347 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program 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.
+
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GOB_SAVE_SAVEFILE_H
+#define GOB_SAVE_SAVEFILE_H
+
+#include "common/endian.h"
+#include "common/array.h"
+#include "common/savefile.h"
+
+namespace Gob {
+
+class GobEngine;
+class SurfaceDesc;
+
+/** A class wrapping a save part header.
+ *
+ * A save part header consists of 4 fields:
+ * ID : The 8 character ID \0SCVMGOB
+ * Type : The 4 character ID for this part's type
+ * Version : This part's version. Each type has its own version counter
+ * Size : The size of the contents, i.e. excluding this header
+*/
+class SaveHeader {
+public:
+ /** The size of the header. */
+ static const int kSize = 20;
+ static const uint32 kID1 = MKID_BE('\0SCV');
+ static const uint32 kID2 = MKID_BE('MGOB');
+
+ SaveHeader(uint32 type = 0, uint32 version = 0, uint32 size = 0);
+
+ /** Read the header out of a stream into this class. */
+ bool read(Common::ReadStream &stream);
+ /** Read the header out of a stream and checks it against this class's contents. */
+ bool verify(Common::ReadStream &stream) const;
+ /** Read the header out of a stream and checks it against this class's contents,
+ * but read the size field instead.
+ */
+ bool verifyReadSize(Common::ReadStream &stream);
+ /** Write this class's contents into a stream. */
+ bool write(Common::WriteStream &stream) const;
+
+ uint32 getType() const;
+ uint32 getVersion() const;
+ uint32 getSize() const;
+
+ void setType(uint32 type);
+ void setVersion(uint32 version);
+ void setSize(uint32 size);
+
+private:
+ /** An ID specifying the part's type. */
+ uint32 _type;
+ /** The part's version. */
+ uint32 _version;
+ /** The size of the contents. */
+ uint32 _size;
+};
+
+/** An abstract class for a part in a save file. */
+class SavePart {
+public:
+ SavePart();
+ virtual ~SavePart();
+
+ /** Return the total size of the part. */
+ virtual uint32 getSize() const;
+
+ /** Read the part (with header) out of the stream. */
+ virtual bool read(Common::ReadStream &stream) = 0;
+ /** Write the part (with header) into the stream. */
+ virtual bool write(Common::WriteStream &stream) const = 0;
+
+protected:
+ SaveHeader _header;
+};
+
+/** A save part consisting of plain memory. */
+class SavePartMem : public SavePart {
+public:
+ static const uint32 kVersion = 1;
+ static const uint32 kID = MKID_BE('PMEM');
+
+ SavePartMem(uint32 size);
+ ~SavePartMem();
+
+ bool read(Common::ReadStream &stream);
+ bool write(Common::WriteStream &stream) const;
+
+ /** Read size bytes of data into the part at the specified offset. */
+ bool readFrom(const byte *data, uint32 offset, uint32 size);
+ /** Write size bytes of the part at the specified offset int data. */
+ bool writeInto(byte *data, uint32 offset, uint32 size) const;
+
+private:
+ uint32 _size;
+ byte *_data;
+};
+
+/** A save part holding script variables. */
+class SavePartVars : public SavePart {
+public:
+ static const uint32 kVersion = 1;
+ static const uint32 kID = MKID_BE('VARS');
+
+ SavePartVars(GobEngine *vm, uint32 size);
+ ~SavePartVars();
+
+ bool read(Common::ReadStream &stream);
+ bool write(Common::WriteStream &stream) const;
+
+ /** Read size bytes of variables starting at var into the part at the specified offset. */
+ bool readFrom(uint32 var, uint32 offset, uint32 size);
+ /** Write size bytes of the part at the specified offset into the variable starting at var. */
+ bool writeInto(uint32 var, uint32 offset, uint32 size) const;
+
+ /** Read size bytes of raw data into the part. */
+ bool readFromRaw(const byte *data, uint32 size);
+
+private:
+ GobEngine *_vm;
+
+ uint32 _size;
+ byte *_data;
+};
+
+/** A save part holding a sprite. */
+class SavePartSprite : public SavePart {
+public:
+ static const uint32 kVersion = 1;
+ static const uint32 kID = MKID_BE('SPRT');
+
+ SavePartSprite(uint32 width, uint32 height);
+ ~SavePartSprite();
+
+ bool read(Common::ReadStream &stream);
+ bool write(Common::WriteStream &stream) const;
+
+ /** Read a palette into the part. */
+ bool readPalette(const byte *palette);
+ /** Read a sprite into the part. */
+ bool readSprite(const SurfaceDesc *sprite);
+
+ /** Read size bytes of raw data into the sprite. */
+ bool readSpriteRaw(const byte *data, uint32 size);
+
+ /** Write a palette out of the part. */
+ bool writePalette(byte *palette) const;
+ /** Write a sprite out of the part. */
+ bool writeSprite(SurfaceDesc *sprite) const;
+
+private:
+ uint32 _width;
+ uint32 _height;
+
+ byte *_dataSprite;
+ byte *_dataPalette;
+};
+
+/** A save part containing informations about the save's game. */
+class SavePartInfo : public SavePart {
+public:
+ static const uint32 kVersion = 1;
+ static const uint32 kID = MKID_BE('INFO');
+
+ /** The constructor.
+ *
+ * @param descMaxLength The maximal number of bytes that fit into the description.
+ * @param gameID An ID for the game (Gob1, Gob2, Gob3, ...).
+ * @param gameVersion An ID for game specific versioning
+ * @param endian Endianness of the platform the game originally ran on.
+ * @param varCount The number of script variables.
+ */
+ SavePartInfo(uint32 descMaxLength, uint32 gameID,
+ uint32 gameVersion, byte endian, uint32 varCount);
+ ~SavePartInfo();
+
+ /** Return the save's description. */
+ const char *getDesc() const;
+ /** Return the description's maximal length. */
+ uint32 getDescMaxLength() const;
+
+ /** Set the variable count. */
+ void setVarCount(uint32 varCount);
+ /** Set the save's description. */
+ void setDesc(const char *desc = 0);
+ /** Set the save's description. */
+ void setDesc(const byte *desc, uint32 size);
+
+ bool read(Common::ReadStream &stream);
+ bool write(Common::WriteStream &stream) const;
+
+private:
+ char *_desc;
+ uint32 _descMaxLength;
+ uint32 _gameID;
+ uint32 _gameVersion;
+ uint32 _varCount;
+ byte _endian;
+};
+
+/** A container for several save parts. */
+class SaveContainer {
+public:
+ static const uint32 kVersion = 1;
+ static const uint32 kID = MKID_BE('CONT');
+
+ /** The constructor.
+ *
+ * @param partCount The number parts this container shall hold.
+ * @param slot The save slot this save's for.
+ */
+ SaveContainer(uint32 partCount, uint32 slot);
+ ~SaveContainer();
+
+ uint32 getSlot() const;
+ uint32 getSize() const;
+
+ /** All parts filled? */
+ bool hasAllParts() const;
+
+ /** Empty all parts. */
+ void clear();
+
+ /** Write a SavePart into the container's part. */
+ bool writePart(uint32 partN, const SavePart *part);
+ /** Read the container's part's content into a SavePart. */
+ bool readPart(uint32 partN, SavePart *part) const;
+ /** Read only the container's part's header. */
+ bool readPartHeader(uint32 partN, SaveHeader *header) const;
+
+ /** Checks if the stream is a valid save container. */
+ static bool isSave(Common::SeekableReadStream &stream);
+
+protected:
+ /** A part. */
+ struct Part {
+ uint32 size;
+ byte *data;
+
+ Part(uint32 s);
+ ~Part();
+
+ Common::WriteStream *createWriteStream();
+ Common::ReadStream *createReadStream() const;
+ };
+
+ /** Basic information about a part. */
+ struct PartInfo {
+ uint32 id;
+ uint32 offset;
+ uint32 size;
+ };
+
+ typedef Common::Array<Part *>::iterator PartIterator;
+ typedef Common::Array<Part *>::const_iterator PartConstIterator;
+
+ uint32 _partCount;
+ uint32 _slot;
+
+ SaveHeader _header;
+ Common::Array<Part *> _parts;
+
+ uint32 calcSize() const;
+
+ bool read(Common::ReadStream &stream);
+ bool write(Common::WriteStream &stream) const;
+
+ /** Get an array containing basic information about all parts in the container in the stream. */
+ static Common::Array<PartInfo> *getPartsInfo(Common::SeekableReadStream &stream);
+};
+
+/** Reads a save. */
+class SaveReader : public SaveContainer {
+public:
+ SaveReader(uint32 partCount, uint32 slot, const char *fileName);
+ SaveReader(uint32 partCount, uint32 slot, Common::SeekableReadStream &stream);
+ ~SaveReader();
+
+ bool load();
+
+ bool readPart(uint32 partN, SavePart *part) const;
+ bool readPartHeader(uint32 partN, SaveHeader *header) const;
+
+ /** Find and read the save's info part. */
+ static bool getInfo(Common::SeekableReadStream &stream, SavePartInfo &info);
+ /** Find and read the save's info part. */
+ static bool getInfo(const char *fileName, SavePartInfo &info);
+
+protected:
+ char *_fileName;
+ Common::SeekableReadStream *_stream;
+
+ bool _loaded;
+
+ static Common::InSaveFile *openSave(const char *fileName);
+ Common::InSaveFile *openSave();
+};
+
+/** Writes a save. */
+class SaveWriter: public SaveContainer {
+public:
+ SaveWriter(uint32 partCount, uint32 slot, const char *fileName = 0);
+ ~SaveWriter();
+
+ bool writePart(uint32 partN, const SavePart *part);
+
+ bool save(Common::WriteStream &stream);
+
+protected:
+ bool save();
+
+ char *_fileName;
+
+ /** Is everything ready for saving? */
+ bool canSave() const;
+
+ static Common::OutSaveFile *openSave(const char *fileName);
+ Common::OutSaveFile *openSave();
+};
+
+} // End of namespace Gob
+
+#endif // GOB_SAVE_SAVEFILE_H
Property changes on: scummvm/trunk/engines/gob/save/savefile.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Rev Author URL Id
Added: svn:eol-style
+ native
Added: scummvm/trunk/engines/gob/save/savehandler.cpp
===================================================================
--- scummvm/trunk/engines/gob/save/savehandler.cpp (rev 0)
+++ scummvm/trunk/engines/gob/save/savehandler.cpp 2009-05-31 02:15:43 UTC (rev 41056)
@@ -0,0 +1,503 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program 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.
+
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/endian.h"
+
+#include "gob/gob.h"
+#include "gob/save/savehandler.h"
+#include "gob/save/savefile.h"
+#include "gob/save/saveconverter.h"
+#include "gob/global.h"
+#include "gob/video.h"
+#include "gob/draw.h"
+#include "gob/variables.h"
+#include "gob/inter.h"
+
+namespace Gob {
+
+SlotFile::SlotFile(GobEngine *vm, uint32 slotCount, const char *base) : _vm(vm) {
+ _base = strdupcpy(base);
+ _slotCount = slotCount;
+}
+
+SlotFile::~SlotFile() {
+ delete[] _base;
+}
+
+const char *SlotFile::getBase() const {
+ return _base;
+}
+
+uint32 SlotFile::getSlotMax() const {
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ Common::InSaveFile *in;
+
+ // Find the last filled save slot and base the save file size calculate on that
+ for (int i = (_slotCount - 1); i >= 0; i--) {
+ char *slotFile = build(i);
+
+ if (!slotFile)
+ continue;
+
+ in = saveMan->openForLoading(slotFile);
+ delete[] slotFile;
+
+ if (in) {
+ delete in;
+ return i + 1;
+ }
+ }
+
+ return 0;
+}
+
+int32 SlotFile::tallyUpFiles(uint32 slotSize, uint32 indexSize) const {
+ uint32 maxSlot = getSlotMax();
+
+ if (maxSlot == 0)
+ return -1;
+
+ return ((maxSlot * slotSize) + indexSize);
+}
+
+void SlotFile::buildIndex(byte *buffer, SavePartInfo &info,
+ SaveConverter *converter) const {
+
+ uint32 descLength = info.getDescMaxLength();
+
+ // Iterate over all files
+ for (uint32 i = 0; i < _slotCount; i++, buffer += descLength) {
+ char *slotFile = build(i);
+
+ if (slotFile) {
+ char *desc = 0;
+
+ if (converter && (desc = converter->getDescription(slotFile)))
+ // Old style save
+ memcpy(buffer, desc, descLength);
+ else if (SaveReader::getInfo(slotFile, info))
+ // New style save
+ memcpy(buffer, info.getDesc(), descLength);
+ else
+ // No known format, fill with 0
+ memset(buffer, 0, descLength);
+
+ delete[] desc;
+
+ } else
+ // No valid slot, fill with 0
+ memset(buffer, 0, descLength);
+
+ delete[] slotFile;
+ }
+}
+
+bool SlotFile::exists(const char *name) const {
+ Common::InSaveFile *in = openRead(name);
+ bool result = (in != 0);
+ delete in;
+ return result;
+}
+
+bool SlotFile::exists(int slot) const {
+ Common::InSaveFile *in = openRead(slot);
+ bool result = (in != 0);
+ delete in;
+ return result;
+}
+
+bool SlotFile::exists() const {
+ Common::InSaveFile *in = openRead();
+ bool result = (in != 0);
+ delete in;
+ return result;
+}
+
+Common::InSaveFile *SlotFile::openRead(const char *name) const {
+ if (!name)
+ return 0;
+
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+
+ return saveMan->openForLoading(name);
+}
+
+Common::InSaveFile *SlotFile::openRead(int slot) const {
+ char *name = build(slot);
+ Common::InSaveFile *result = openRead(name);
+ delete[] name;
+ return result;
+}
+
+Common::InSaveFile *SlotFile::openRead() const {
+ char *name = build();
+ Common::InSaveFile *result = openRead(name);
+ delete[] name;
+ return result;
+}
+
+Common::OutSaveFile *SlotFile::openWrite(const char *name) const {
+ if (!name)
+ return 0;
+
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+
+ return saveMan->openForSaving(name);
+}
+
+Common::OutSaveFile *SlotFile::openWrite(int slot) const {
+ char *name = build(slot);
+ Common::OutSaveFile *result = openWrite(name);
+ delete[] name;
+ return result;
+}
+
+Common::OutSaveFile *SlotFile::openWrite() const {
+ char *name = build();
+ Common::OutSaveFile *result = openWrite(name);
+ delete[] name;
+ return result;
+}
+
+
+SlotFileIndexed::SlotFileIndexed(GobEngine *vm, uint32 slotCount,
+ const char *base, const char *extStub) : SlotFile(vm, slotCount, base) {
+
+ _ext = strdupcpy(extStub);
+}
+
+SlotFileIndexed::~SlotFileIndexed() {
+ delete[] _ext;
+}
+
+char *SlotFileIndexed::build(int slot) const {
+ if ((slot < 0) || (((uint32) slot) >= _slotCount))
+ return 0;
+
+ size_t len = strlen(_base) + strlen(_ext) + 4;
+
+ char *slotFile = new char[len];
+
+ snprintf(slotFile, len, "%s.%s%02d", _base, _ext, slot);
+
+ return slotFile;
+}
+
+char *SlotFileIndexed::build() const {
+ return 0;
+}
+
+
+SlotFileStatic::SlotFileStatic(GobEngine *vm, const char *base,
+ const char *ext) : SlotFile(vm, 1, base) {
+
+ _ext = strdupcat(".", ext);
+}
+
+SlotFileStatic::~SlotFileStatic() {
+ delete[] _ext;
+}
+
+int SlotFileStatic::getSlot(int32 offset) const {
+ return -1;
+}
+
+int SlotFileStatic::getSlotRemainder(int32 offset) const {
+ return -1;
+}
+
+char *SlotFileStatic::build(int slot) const {
+ return 0;
+}
+
+char *SlotFileStatic::build() const {
+ return strdupcat(_base, _ext);
+}
+
+
+SaveHandler::SaveHandler(GobEngine *vm) : _vm(vm) {
+}
+
+SaveHandler::~SaveHandler() {
+}
+
+uint32 SaveHandler::getVarSize(GobEngine *vm) {
+ // Sanity checks
+ if (!vm || !vm->_inter || !vm->_inter->_variables)
+ return 0;
+
+ return vm->_inter->_variables->getSize();
+}
+
+
+TempSpriteHandler::TempSpriteHandler(GobEngine *vm) : SaveHandler(vm) {
+ _sprite = 0;
+}
+
+TempSpriteHandler::~TempSpriteHandler() {
+ delete _sprite;
+}
+
+int32 TempSpriteHandler::getSize() {
+ if (!_sprite)
+ return -1;
+
+ return _sprite->getSize();
+}
+
+bool TempSpriteHandler::load(int16 dataVar, int32 size, int32 offset) {
+ // Sprite available?
+ if (!_sprite)
+ return false;
+
+ // Sprite requested?
+ if (!isSprite(size))
+ return false;
+
+ // Index sane?
+ int index = getIndex(size);
+ if ((index < 0) || (index >= SPRITES_COUNT))
+ return false;
+
+ SurfaceDesc *sprite = _vm->_draw->_spritesArray[index];
+
+ // Target sprite exists?
+ if (!sprite)
+ return false;
+
+ // Load the sprite
+ if (!_sprite->writeSprite(sprite))
+ return false;
+
+ // Handle palette
+ if (usesPalette(size)) {
+ if (!_sprite->writePalette((byte *) _vm->_global->_pPaletteDesc->vgaPal))
+ return false;
+
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+ }
+
+ if (index == 21) {
+ // We wrote into the backbuffer, blit
+ _vm->_draw->forceBlit();
+ _vm->_video->retrace();
+ } else if (index == 20)
+ // We wrote into the frontbuffer, retrace
+ _vm->_video->retrace();
+
+ return true;
+}
+
+bool TempSpriteHandler::save(int16 dataVar, int32 size, int32 offset) {
+ SurfaceDesc *sprite;
+
+ if (!createSprite(dataVar, size, offset, &sprite))
+ return false;
+
+ // Save the sprite
+ if (!_sprite->readSprite(sprite))
+ return false;
+
+ // Handle palette
+ if (usesPalette(size)) {
+ if (!_sprite->readPalette((const byte *) _vm->_global->_pPaletteDesc->vgaPal))
+ return false;
+ }
+
+ return true;
+}
+
+bool TempSpriteHandler::createSprite(int16 dataVar, int32 size,
+ int32 offset, SurfaceDesc **sprite) {
+
+ delete _sprite;
+ _sprite = 0;
+
+ // Sprite requested?
+ if (!isSprite(size))
+ return false;
+
+ // Index sane?
+ int index = getIndex(size);
+ if ((index < 0) || (index >= SPRITES_COUNT))
+ return false;
+
+ SurfaceDesc *sprt = _vm->_draw->_spritesArray[index];
+
+ // Sprite exists?
+ if (!sprt)
+ return false;
+
+ // Create a new temporary sprite
+ _sprite = new SavePartSprite(sprt->getWidth(), sprt->getHeight());
+
+ if (sprite)
+ *sprite = sprt;
+
+ return true;
+}
+
+// A negative size is the flag for using a sprite
+bool TempSpriteHandler::isSprite(int32 size) {
+ return (size < 0);
+}
+
+// Contruct the index
+int TempSpriteHandler::getIndex(int32 size) {
+ // Palette flag
+ if (size < -1000)
+ size += 1000;
+
+ return (-size - 1);
+}
+
+// A size smaller than -1000 indicates palette usage
+bool TempSpriteHandler::usesPalette(int32 size) {
+ return (size < -1000);
+}
+
+
+NotesHandler::File::File(GobEngine *vm, const char *base) :
+ SlotFileStatic(vm, base, "blo") {
+}
+
+NotesHandler::File::~File() {
+}
+
+NotesHandler::NotesHandler(uint32 notesSize, GobEngine *vm, const char *target) :
+ SaveHandler(vm) {
+
+ _notesSize = notesSize;
+
+ _file = new File(vm, target);
+
+ _notes = new SavePartVars(vm, _notesSize);
+}
+
+NotesHandler::~NotesHandler() {
+ delete _file;
+ delete _notes;
+}
+
+int32 NotesHandler::getSize() {
+ char *fileName = _file->build();
+
+ if (!fileName)
+ return -1;
+
+ Common::InSaveFile *saveFile;
+
+ SaveConverter_Notes converter(_vm, _notesSize, fileName);
+ if (converter.isOldSave(&saveFile)) {
+ // Old save, get the size olden-style
+
+ int32 size = saveFile->size();
+
+ delete saveFile;
+ return size;
+ }
+
+ SaveReader reader(1, 0, fileName);
+ SaveHeader header;
+
+ delete[] fileName;
+
+ if (!reader.load())
+ return -1;
+
+ if (!reader.readPartHeader(0, &header))
+ return -1;
+
+ // Return the part's size
+ return header.getSize();
+}
+
+bool NotesHandler::load(int16 dataVar, int32 size, int32 offset) {
+ if ((dataVar < 0) || (size < 0) || (offset < 0))
+ return false;
+
+ char *fileName = _file->build();
+
+ if (!fileName)
+ return false;
+
+ SaveReader *reader;
+
+ SaveConverter_Notes converter(_vm, _notesSize, fileName);
+ if (converter.isOldSave()) {
+ // Old save, plug the converter in
+ if (!converter.load())
+ return false;
+
+ reader = new SaveReader(1, 0, converter);
+
+ } else
+ // New save, load directly
+ reader = new SaveReader(1, 0, fileName);
+
+ SavePartVars vars(_vm, _notesSize);
+
+ delete[] fileName;
+
+ if (!reader->load()) {
+ delete reader;
+ return false;
+ }
+
+ if (!reader->readPart(0, &vars)) {
+ delete reader;
+ return false;
+ }
+
+ if (!vars.writeInto(dataVar, offset, size)) {
+ delete reader;
+ return false;
+ }
+
+ delete reader;
+ return true;
+}
+
+bool NotesHandler::save(int16 dataVar, int32 size, int32 offset) {
+ if ((dataVar < 0) || (size < 0) || (offset < 0))
+ return false;
+
+ char *fileName = _file->build();
+
+ if (!fileName)
+ return false;
+
+ SaveWriter writer(1, 0, fileName);
+ SavePartVars vars(_vm, _notesSize);
+
+ delete[] fileName;
+
+ if (!vars.readFrom(dataVar, offset, size))
+ return false;
+
+ return writer.writePart(0, &vars);
+}
+
+} // End of namespace Gob
Property changes on: scummvm/trunk/engines/gob/save/savehandler.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Rev Author URL Id
Added: svn:eol-style
+ native
Added: scummvm/trunk/engines/gob/save/savehandler.h
===================================================================
--- scummvm/trunk/engines/gob/save/savehandler.h (rev 0)
+++ scummvm/trunk/engines/gob/save/savehandler.h 2009-05-31 02:15:43 UTC (rev 41056)
@@ -0,0 +1,191 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program 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.
+
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GOB_SAVE_SAVEHANDLER_H
+#define GOB_SAVE_SAVEHANDLER_H
+
+#include "common/savefile.h"
+
+namespace Gob {
+
+class GobEngine;
+class SurfaceDesc;
+class SavePartInfo;
+class SavePartVars;
+class SavePartSprite;
+class SaveConverter;
+
+/** Slot file related class. */
+class SlotFile {
+public:
+ /** The constructor.
+ *
+ * @param slotCount Number of slots.
+ * @param base The file's base string.
+ */
+ SlotFile(GobEngine *vm, uint32 slotCount, const char *base);
+ virtual ~SlotFile();
+
+ /** Returns the base string. */
+ virtual const char *getBase() const;
+
+ /** Calculates which slot to use. */
+ virtual int getSlot(int32 offset) const = 0;
+ /** Calculates the slot remainder, for error checking. */
+ virtual int getSlotRemainder(int32 offset) const = 0;
+
+ /** Build the save file name. */
+ virtual char *build(int slot) const = 0;
+ /** Build the save file name. */
+ virtual char *build() const = 0;
+
+ /** Returns the highest filled slot number. */
+ virtual uint32 getSlotMax() const;
+
+ /** Returns the size of all existing slots + the index. */
+ virtual int32 tallyUpFiles(uint32 slotSize, uint32 indexSize) const;
+
+ /** Creates an index in buffer. */
+ virtual void buildIndex(byte *buffer, SavePartInfo &info,
+ SaveConverter *converter = 0) const;
+
+ virtual bool exists(const char *name) const;
+ virtual bool exists(int slot) const;
+ virtual bool exists() const;
+
+ virtual Common::InSaveFile *openRead(const char *name) const;
+ virtual Common::InSaveFile *openRead(int slot) const;
+ virtual Common::InSaveFile *openRead() const;
+
+ virtual Common::OutSaveFile *openWrite(const char *name) const;
+ virtual Common::OutSaveFile *openWrite(int slot) const;
+ virtual Common::OutSaveFile *openWrite() const;
+
+protected:
+ GobEngine *_vm;
+ char *_base;
+
+ uint32 _slotCount;
+};
+
+/** An indexed slot file ("foobar.s00", "foobar.s01", ...). */
+class SlotFileIndexed : public SlotFile {
+public:
+ SlotFileIndexed(GobEngine *vm, uint32 slotCount, const char *base,
+ const char *extStub);
+ ~SlotFileIndexed();
+
+ char *build(int slot) const;
+ char *build() const;
+
+protected:
+ char *_ext;
+};
+
+/** A static slot file ("foo.bar"). */
+class SlotFileStatic : public SlotFile {
+public:
+ SlotFileStatic(GobEngine *vm, const char *base, const char *ext);
+ ~SlotFileStatic();
+
+ int getSlot(int32 offset) const;
+ int getSlotRemainder(int32 offset) const;
+
+ char *build(int slot) const;
+ char *build() const;
+
+protected:
+ char *_ext;
+};
+
+/** A handler for a specific save file. */
+class SaveHandler {
+public:
+ SaveHandler(GobEngine *vm);
+ virtual ~SaveHandler();
+
+ /** Returns the file's (virtual) size. */
+ virtual int32 getSize() = 0;
+ /** Loads (parts of) the file. */
+ virtual bool load(int16 dataVar, int32 size, int32 offset) = 0;
+ /** Saves (parts of) the file. */
+ virtual bool save(int16 dataVar, int32 size, int32 offset) = 0;
+
+ static uint32 getVarSize(GobEngine *vm);
+
+protected:
+ GobEngine *_vm;
+};
+
+/** A handler for temporary sprites. */
+class TempSpriteHandler : public SaveHandler {
+public:
+ TempSpriteHandler(GobEngine *vm);
+ ~TempSpriteHandler();
+
+ int32 getSize();
+ bool load(int16 dataVar, int32 size, int32 offset);
+ bool save(int16 dataVar, int32 size, int32 offset);
+
+ /** Create a fitting sprite. */
+ bool createSprite(int16 dataVar, int32 size,
+ int32 offset, SurfaceDesc **sprite = 0);
+
+protected:
+ SavePartSprite *_sprite;
+
+ /** Determine whether using a sprite was requested. */
+ static bool isSprite(int32 size);
+ /** Determine which sprite is meant. */
+ static int getIndex(int32 size);
+ /** Determine whether the palette should be used too. */
+ static bool usesPalette(int32 size);
+};
+
+/** A handler for notes. */
+class NotesHandler : public SaveHandler {
+public:
+ NotesHandler(uint32 notesSize, GobEngine *vm, const char *target);
+ ~NotesHandler();
+
+ int32 getSize();
+ bool load(int16 dataVar, int32 size, int32 offset);
+ bool save(int16 dataVar, int32 size, int32 offset);
+
+private:
+ class File : public SlotFileStatic {
+ public:
+ File(GobEngine *vm, const char *base);
+ ~File();
+ };
+
+ uint32 _notesSize;
+ File *_file;
+ SavePartVars *_notes;
+};
+
+} // End of namespace Gob
+
+#endif // GOB_SAVE_SAVEHANDLER_H
Property changes on: scummvm/trunk/engines/gob/save/savehandler.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Rev Author URL Id
Added: svn:eol-style
+ native
Added: scummvm/trunk/engines/gob/save/saveload.cpp
===================================================================
--- scummvm/trunk/engines/gob/save/saveload.cpp (rev 0)
+++ scummvm/trunk/engines/gob/save/saveload.cpp 2009-05-31 02:15:43 UTC (rev 41056)
@@ -0,0 +1,135 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program 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.
+
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/endian.h"
+#include "common/savefile.h"
+
+#include "gob/gob.h"
+#include "gob/save/saveload.h"
+#include "gob/helper.h"
+#include "gob/global.h"
+#include "gob/video.h"
+#include "gob/draw.h"
+
+namespace Gob {
+
+SaveLoad::SaveLoad(GobEngine *vm, const char *targetName) : _vm(vm) {
+ _targetName = strdupcpy(targetName);
+}
+
+SaveLoad::~SaveLoad() {
+ delete[] _targetName;
+}
+
+const char *SaveLoad::stripPath(const char *fileName) {
+ const char *backSlash;
+ if ((backSlash = strrchr(fileName, '\\')))
+ return backSlash + 1;
+
+ return fileName;
+}
+
+int32 SaveLoad::getSize(const char *fileName) {
+ debugC(3, kDebugSaveLoad, "Requested size of save file \"%s\"", fileName);
+
+ SaveHandler *handler = getHandler(fileName);
+
+ if (!handler) {
+ warning("No save handler for \"%s\"", fileName);
+ return -1;
+ }
+
+ int32 size = handler->getSize();
+
+ debugC(4, kDebugSaveLoad, "Size is %d", size);
+
+ return size;
+}
+
+bool SaveLoad::load(const char *fileName, int16 dataVar, int32 size, int32 offset) {
+ debugC(3, kDebugSaveLoad, "Requested loading of save file \"%s\" - %d, %d, %d",
+ fileName, dataVar, size, offset);
+
+ SaveHandler *handler = getHandler(fileName);
+
+ if (!handler) {
+ warning("No save handler for \"%s\" (%d, %d, %d)", fileName, dataVar, size, offset);
+ return false;
+ }
+
+ if (!handler->load(dataVar, size, offset)) {
+ const char *desc = getDescription(fileName);
+
+ if (!desc)
+ desc = "Unkown";
+
+ warning("Could not load %s (\"%s\" (%d, %d, %d))",
+ desc, fileName, dataVar, size, offset);
+ return false;
+ }
+
+ debugC(3, kDebugSaveLoad, "Successfully loaded game");
+ return true;
+}
+
+bool SaveLoad::save(const char *fileName, int16 dataVar, int32 size, int32 offset) {
+ debugC(3, kDebugSaveLoad, "Requested saving of save file \"%s\" - %d, %d, %d",
+ fileName, dataVar, size, offset);
+
+ SaveHandler *handler = getHandler(fileName);
+
+ if (!handler) {
+ warning("No save handler for \"%s\" (%d, %d, %d)", fileName, dataVar, size, offset);
+ return false;
+ }
+
+ if (!handler->save(dataVar, size, offset)) {
+ const char *desc = getDescription(fileName);
+
+ if (!desc)
+ desc = "Unkown";
+
+ warning("Could not save %s (\"%s\" (%d, %d, %d))",
+ desc, fileName, dataVar, size, offset);
+ return false;
+ }
+
+ debugC(3, kDebugSaveLoad, "Successfully saved game");
+ return true;
+}
+
+SaveLoad::SaveMode SaveLoad::getSaveMode(const char *fileName) const {
+ return kSaveModeNone;
+}
+
+SaveHandler *SaveLoad::getHandler(const char *fileName) const {
+ return 0;
+}
+
+const char *SaveLoad::getDescription(const char *fileName) const {
+ return 0;
+}
+
+} // End of namespace Gob
Property changes on: scummvm/trunk/engines/gob/save/saveload.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Rev Author URL Id
Added: svn:eol-style
+ native
Added: scummvm/trunk/engines/gob/save/saveload.h
===================================================================
--- scummvm/trunk/engines/gob/save/saveload.h (rev 0)
+++ scummvm/trunk/engines/gob/save/saveload.h 2009-05-31 02:15:43 UTC (rev 41056)
@@ -0,0 +1,452 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program 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.
+
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GOB_SAVE_SAVELOAD_H
+#define GOB_SAVE_SAVELOAD_H
+
+#include "gob/save/savefile.h"
+#include "gob/save/savehandler.h"
+
+namespace Gob {
+
@@ Diff output truncated at 100000 characters. @@
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list