aboutsummaryrefslogtreecommitdiff
path: root/engines/gob/save/savehandler.cpp
diff options
context:
space:
mode:
authorSven Hesse2009-05-31 02:15:43 +0000
committerSven Hesse2009-05-31 02:15:43 +0000
commit896df6daf337bf83f27193918eb386321c4b0166 (patch)
treec124f8f102052cdd6207e2507d097aff4bc7f44e /engines/gob/save/savehandler.cpp
parentc938667d4b60005a926007376305f3da8621f7c7 (diff)
downloadscummvm-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.cpp503
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