diff options
author | Sven Hesse | 2009-05-31 02:15:43 +0000 |
---|---|---|
committer | Sven Hesse | 2009-05-31 02:15:43 +0000 |
commit | 896df6daf337bf83f27193918eb386321c4b0166 (patch) | |
tree | c124f8f102052cdd6207e2507d097aff4bc7f44e /engines/gob/save/savehandler.cpp | |
parent | c938667d4b60005a926007376305f3da8621f7c7 (diff) | |
download | scummvm-rg350-896df6daf337bf83f27193918eb386321c4b0166.tar.gz scummvm-rg350-896df6daf337bf83f27193918eb386321c4b0166.tar.bz2 scummvm-rg350-896df6daf337bf83f27193918eb386321c4b0166.zip |
- 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
svn-id: r41056
Diffstat (limited to 'engines/gob/save/savehandler.cpp')
-rw-r--r-- | engines/gob/save/savehandler.cpp | 503 |
1 files changed, 503 insertions, 0 deletions
diff --git a/engines/gob/save/savehandler.cpp b/engines/gob/save/savehandler.cpp new file mode 100644 index 0000000000..744b839653 --- /dev/null +++ b/engines/gob/save/savehandler.cpp @@ -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 |