scummvm/engines/gob/saveload.cpp
Sven Hesse 5327417c56 Style :P
svn-id: r30000
2007-12-26 01:19:16 +00:00

518 lines
11 KiB
C++

/* 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/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() {
if (_buffer) {
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);
_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
}
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<int>(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);
_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
}
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