From dee8a04168fb0d0ccc58b73dd9fb8d0be9499b17 Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Sun, 8 Apr 2007 00:08:26 +0000 Subject: Restructured saving/loading. Should work for Gob3 now, too... svn-id: r26414 --- engines/gob/saveload.cpp | 511 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 511 insertions(+) create mode 100644 engines/gob/saveload.cpp (limited to 'engines/gob/saveload.cpp') 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 -- cgit v1.2.3