Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

saveload.cpp

/* 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: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-0-11-1/engines/gob/saveload.cpp $
 * $Id: saveload.cpp 30944 2008-02-23 22:50:18Z sev $
 *
 */

#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

Generated by  Doxygen 1.6.0   Back to index