aboutsummaryrefslogtreecommitdiff
path: root/engines/gob/saveload.cpp
diff options
context:
space:
mode:
authorSven Hesse2007-04-08 00:08:26 +0000
committerSven Hesse2007-04-08 00:08:26 +0000
commitdee8a04168fb0d0ccc58b73dd9fb8d0be9499b17 (patch)
treef4e97855cff99a56b6ae703f7734242969f4785c /engines/gob/saveload.cpp
parent614ae1c08cae7d5c9b6f4ecddfa6050c41aa433f (diff)
downloadscummvm-rg350-dee8a04168fb0d0ccc58b73dd9fb8d0be9499b17.tar.gz
scummvm-rg350-dee8a04168fb0d0ccc58b73dd9fb8d0be9499b17.tar.bz2
scummvm-rg350-dee8a04168fb0d0ccc58b73dd9fb8d0be9499b17.zip
Restructured saving/loading. Should work for Gob3 now, too...
svn-id: r26414
Diffstat (limited to 'engines/gob/saveload.cpp')
-rw-r--r--engines/gob/saveload.cpp511
1 files changed, 511 insertions, 0 deletions
diff --git a/engines/gob/saveload.cpp b/engines/gob/saveload.cpp
new file mode 100644
index 0000000000..e4b14639b1
--- /dev/null
+++ b/engines/gob/saveload.cpp
@@ -0,0 +1,511 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2004 Ivan Dubrov
+ * Copyright (C) 2004-2006 The ScummVM project
+ *
+ * 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/stdafx.h"
+#include "common/endian.h"
+#include "common/file.h"
+
+#include "gob/gob.h"
+#include "gob/saveload.h"
+#include "gob/global.h"
+#include "gob/draw.h"
+#include "gob/video.h"
+
+namespace Gob {
+
+SaveLoad::SaveLoad(GobEngine *vm, const char *targetName) : _vm(vm) {
+ _curSlot = -1;
+
+ _stagesCount = 0;
+ _buffer = 0;
+
+ _tempSprite = 0;
+ memset(_tempPal, 0, 768);
+ _tempSpriteSize = -1;
+
+ _saveFiles = new char*[5];
+
+ assert(_saveFiles);
+
+ _saveFiles[0] = new char[strlen(targetName) + 5];
+ _saveFiles[1] = 0;
+ _saveFiles[2] = new char[strlen(targetName) + 5];
+ _saveFiles[3] = _saveFiles[0];
+ _saveFiles[4] = 0;
+
+ assert(_saveFiles[0] && _saveFiles[2]);
+
+ sprintf(_saveFiles[0], "%s.s00", targetName);
+ sprintf(_saveFiles[2], "%s.blo", targetName);
+}
+
+SaveLoad::~SaveLoad() {
+ for (int i = 0; i < _stagesCount; i++)
+ delete[] _buffer[i];
+ delete[] _buffer;
+
+ delete _tempSprite;
+
+ delete[] _saveFiles[0];
+ delete[] _saveFiles[2];
+ delete[] _saveFiles;
+}
+
+const char *SaveLoad::setCurSlot(int slot) {
+ static char *slotBase = _saveFiles[0] + strlen(_saveFiles[0]) - 2;
+
+ if (_curSlot != slot) {
+ _curSlot = slot;
+
+ if (_curSlot >= 0)
+ snprintf(slotBase, 3, "%02d", slot);
+ }
+
+ return _saveFiles[0];
+}
+
+uint32 SaveLoad::read(Common::ReadStream &in, byte *buf,
+ byte *sizes, uint32 count) {
+ uint32 nRead;
+
+ nRead = in.read(buf, count);
+ if (nRead != count) {
+ warning("Can't read data: requested %d, got %d", count, nRead);
+ return 0;
+ }
+
+ nRead = in.read(sizes, count);
+ if (nRead != count) {
+ warning("Can't read data sizes: requested %d, got %d", count, nRead);
+ return 0;
+ }
+
+ return count;
+}
+
+uint32 SaveLoad::write(Common::WriteStream &out, byte *buf,
+ byte *sizes, uint32 count) {
+ uint32 written;
+
+ written = out.write(buf, count);
+ if (written != count) {
+ warning("Can't write data: requested %d, wrote %d", count, written);
+ return 0;
+ }
+
+ written = out.write(sizes, count);
+ if (written != count) {
+ warning("Can't write data: requested %d, wrote %d", count, written);
+ return 0;
+ }
+
+ return count;
+}
+
+bool SaveLoad::loadDataEndian(Common::ReadStream &in,
+ int16 dataVar, uint32 size) {
+
+ bool retVal = false;
+
+ byte *varBuf = new byte[size];
+ byte *sizeBuf = new byte[size];
+
+ assert(varBuf && sizeBuf);
+
+ if (read(in, varBuf, sizeBuf, size) == size) {
+ if (fromEndian(varBuf, sizeBuf, size)) {
+ memcpy(_vm->_global->_inter_variables + dataVar, varBuf, size);
+ memcpy(_vm->_global->_inter_variablesSizes + dataVar, sizeBuf, size);
+ retVal = true;
+ }
+ }
+
+ delete[] varBuf;
+ delete[] sizeBuf;
+
+ return retVal;
+}
+
+bool SaveLoad::saveDataEndian(Common::WriteStream &out,
+ int16 dataVar, uint32 size) {
+
+ bool retVal = false;
+
+ byte *varBuf = new byte[size];
+ byte *sizeBuf = new byte[size];
+
+ assert(varBuf && sizeBuf);
+
+ memcpy(varBuf, _vm->_global->_inter_variables + dataVar, size);
+ memcpy(sizeBuf, _vm->_global->_inter_variablesSizes + dataVar, size);
+
+ if (toEndian(varBuf, sizeBuf, size))
+ if (write(out, varBuf, sizeBuf, size) == size)
+ retVal = true;
+
+ delete[] varBuf;
+ delete[] sizeBuf;
+
+ return retVal;
+}
+
+int32 SaveLoad::getSize(SaveType type) {
+ switch(type) {
+ case kSaveNone:
+ return -1;
+ break;
+
+ case kSaveGame:
+ return getSizeGame();
+ break;
+
+ case kSaveTempSprite:
+ return getSizeTempSprite();
+ break;
+
+ case kSaveNotes:
+ return getSizeNotes();
+ break;
+
+ case kSaveScreenshot:
+ return getSizeScreenshot();
+ break;
+
+ case kSaveIgnore:
+ return -1;
+ break;
+ }
+
+ return -1;
+}
+
+bool SaveLoad::load(SaveType type, int16 dataVar, int32 size, int32 offset) {
+ switch(type) {
+ case kSaveNone:
+ return false;
+ break;
+
+ case kSaveGame:
+ return loadGame(dataVar, size, offset);
+ break;
+
+ case kSaveTempSprite:
+ return loadTempSprite(dataVar, size, offset);
+ break;
+
+ case kSaveNotes:
+ return loadNotes(dataVar, size, offset);
+ break;
+
+ case kSaveScreenshot:
+ return loadScreenshot(dataVar, size, offset);
+ break;
+
+ case kSaveIgnore:
+ return true;
+ break;
+ }
+
+ return false;
+}
+
+bool SaveLoad::save(SaveType type, int16 dataVar, int32 size, int32 offset) {
+ switch(type) {
+ case kSaveNone:
+ return false;
+ break;
+
+ case kSaveGame:
+ return saveGame(dataVar, size, offset);
+ break;
+
+ case kSaveTempSprite:
+ return saveTempSprite(dataVar, size, offset);
+ break;
+
+ case kSaveNotes:
+ return saveNotes(dataVar, size, offset);
+ break;
+
+ case kSaveScreenshot:
+ return saveScreenshot(dataVar, size, offset);
+ break;
+
+ case kSaveIgnore:
+ return true;
+ break;
+ }
+
+ return false;
+}
+
+int32 SaveLoad::getSizeTempSprite() {
+ return _tempSpriteSize;
+}
+
+bool SaveLoad::loadTempSprite(int16 dataVar, int32 size, int32 offset) {
+ int index;
+ bool readPal;
+
+ if (size >= 0) {
+ warning("Invalid attempt at loading from the temporary sprite");
+ return false;
+ }
+
+ index = getSpriteIndex(size);
+ readPal = getSpritePalette(size);
+
+ if ((index < 0) || (index >= SPRITES_COUNT)) {
+ warning("Index out of range while loading from the temporary "
+ "sprite (%d)", index);
+ return false;
+ }
+
+ return loadTempSprite(index, readPal);
+}
+
+bool SaveLoad::saveTempSprite(int16 dataVar, int32 size, int32 offset) {
+ int index;
+ bool readPal;
+
+ if (size >= 0) {
+ warning("Invalid attempt at saving to the temporary sprite");
+ return false;
+ }
+
+ index = getSpriteIndex(size);
+ readPal = getSpritePalette(size);
+
+ if ((index < 0) || (index >= SPRITES_COUNT)) {
+ warning("Index out of range while saving to the temporary sprite (%d)",
+ index);
+ return false;
+ }
+
+ return saveTempSprite(index, readPal);
+}
+
+bool SaveLoad::loadTempSprite(uint32 index, bool palette) {
+ SurfaceDesc *sprite;
+
+ if (palette)
+ memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal,
+ (char *) _tempPal, 768);
+
+ sprite = _vm->_draw->_spritesArray[index];
+
+ if (!sprite) {
+ warning("Couldn't load from the temporary sprite: "
+ "No such sprite %d", index);
+ return false;
+ }
+
+ if ((sprite->getWidth() != _tempSprite->getWidth()) ||
+ (sprite->getHeight() != _tempSprite->getHeight())) {
+ warning("Resolution doesn't match while loading from the "
+ "temporary sprite (%d: %dx%d vs. %dx%d)", index,
+ sprite->getWidth(), sprite->getHeight(),
+ _tempSprite->getWidth(), _tempSprite->getHeight());
+ return false;
+ }
+
+ _vm->_video->drawSprite(_tempSprite, sprite, 0, 0,
+ sprite->getWidth() - 1, sprite->getHeight() - 1, 0, 0, 0);
+
+ if (index == 21) {
+ _vm->_draw->forceBlit();
+ _vm->_video->retrace();
+ }
+
+ return true;
+}
+
+bool SaveLoad::saveTempSprite(uint32 index, bool palette) {
+ SurfaceDesc *sprite = _vm->_draw->_spritesArray[index];
+
+ if (!sprite) {
+ warning("Couldn't save to the temporary sprite: "
+ "No such sprite %d", index);
+ return false;
+ }
+
+ delete _tempSprite;
+ _tempSprite = _vm->_video->initSurfDesc(_vm->_global->_videoMode,
+ sprite->getWidth(), sprite->getHeight(), 0);
+
+ _vm->_video->drawSprite(sprite, _tempSprite, 0, 0,
+ sprite->getWidth() - 1, sprite->getHeight() - 1, 0, 0, 0);
+
+ _tempSpriteSize = _vm->_draw->getSpriteRectSize(index);
+
+ if (palette) {
+ memcpy((char *) _tempPal,
+ (char *) _vm->_global->_pPaletteDesc->vgaPal, 768);
+ _tempSpriteSize += 768;
+ }
+
+ return true;
+}
+
+bool SaveLoad::loadSprite(Common::ReadStream &in, int32 size) {
+ SurfaceDesc *sprite;
+ byte *buf;
+ int nRead;
+ int index;
+ bool readPal;
+
+ if (size >= 0) {
+ warning("Invalid attempt at loading a sprite");
+ return false;
+ }
+
+ index = getSpriteIndex(size);
+ readPal = getSpritePalette(size);
+
+ if ((index < 0) || (index >= SPRITES_COUNT)) {
+ warning("Index out of range while loading a sprite (%d)",
+ index);
+ return false;
+ }
+
+ size = _vm->_draw->getSpriteRectSize(index);
+ sprite = _vm->_draw->_spritesArray[index];
+
+ if (!sprite) {
+ warning("Couldn't load sprite: No such sprite %d", index);
+ return false;
+ }
+
+ buf = new byte[MAX(768, size)];
+ assert(buf);
+
+ if (readPal) {
+ nRead = in.read(buf, 768);
+ if (nRead != 768) {
+ warning("Couldn't read a palette: requested 768, got %d", nRead);
+ delete[] buf;
+ return false;
+ }
+
+ memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal,
+ (char *) buf, 768);
+ }
+
+ nRead = in.read(buf, size);
+ if (nRead != size) {
+ warning("Couldn't read sprite data: requested %d, got %d", size, nRead);
+ delete[] buf;
+ return false;
+ }
+
+ memcpy((char *) sprite->getVidMem(), buf, size);
+
+ delete[] buf;
+ return true;
+}
+
+bool SaveLoad::saveSprite(Common::WriteStream &out, int32 size) {
+ SurfaceDesc *sprite;
+ int written;
+ int index;
+ bool readPal;
+
+ if (size >= 0) {
+ warning("Invalid attempt at saving a sprite");
+ return false;
+ }
+
+ index = getSpriteIndex(size);
+ readPal = getSpritePalette(size);
+
+ if ((index < 0) || (index >= SPRITES_COUNT)) {
+ warning("Index out of range while saving a sprite (%d)",
+ index);
+ return false;
+ }
+
+ size = _vm->_draw->getSpriteRectSize(index);
+ sprite = _vm->_draw->_spritesArray[index];
+
+ if (!sprite) {
+ warning("Couldn't save sprite: No such sprite %d", index);
+ return false;
+ }
+
+ if (readPal) {
+ written = out.write((char *) _vm->_global->_pPaletteDesc->vgaPal, 768);
+ if (written != 768) {
+ warning("Couldn't write a palette: requested 768, wrote %d", written);
+ return false;
+ }
+ }
+
+ written = out.write((char *) sprite->getVidMem(), size);
+ if (written != size) {
+ warning("Couldn't write a sprite: requested %d, wrote %d",
+ size, written);
+ return false;
+ }
+
+ return true;
+}
+
+bool SaveLoad::fromEndian(byte *buf, const byte *sizes, uint32 count) {
+ while (count-- > 0) {
+ if (*sizes == 3)
+ *((uint32 *) buf) = READ_LE_UINT32(buf);
+ else if (*sizes == 1)
+ *((uint16 *) buf) = READ_LE_UINT16(buf);
+ else if (*sizes != 0) {
+ warning("SaveLoad::fromEndian(): Corrupted variables sizes");
+ return false;
+ }
+
+ count -= *sizes;
+ buf += *sizes + 1;
+ sizes += *sizes + 1;
+ }
+
+ return true;
+}
+
+bool SaveLoad::toEndian(byte *buf, const byte *sizes, uint32 count) {
+ while (count-- > 0) {
+ if (*sizes == 3)
+ WRITE_LE_UINT32(buf, *((uint32 *) buf));
+ else if (*sizes == 1)
+ WRITE_LE_UINT16(buf, *((uint16 *) buf));
+ else if (*sizes != 0) {
+ warning("SaveLoad::toEndian(): Corrupted variables sizes");
+ return false;
+ }
+
+ count -= *sizes;
+ buf += *sizes + 1;
+ sizes += *sizes + 1;
+ }
+
+ return true;
+}
+
+} // End of namespace Gob