aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/gob/gob.cpp3
-rw-r--r--engines/gob/gob.h5
-rw-r--r--engines/gob/inter_v2.cpp31
-rw-r--r--engines/gob/module.mk1
-rw-r--r--engines/gob/saveload.cpp724
-rw-r--r--engines/gob/saveload.h364
-rw-r--r--engines/gob/saveload_v2.cpp403
-rw-r--r--engines/gob/saveload_v3.cpp677
-rw-r--r--engines/gob/saveload_v4.cpp80
-rw-r--r--engines/gob/video.h7
10 files changed, 1460 insertions, 835 deletions
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp
index ed2fe0fc15..41f268eba2 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -89,6 +89,7 @@ GobEngine::GobEngine(OSystem *syst) : Engine(syst) {
Common::addSpecialDebugLevel(kDebugParser, "Parser", "Parser debug level");
Common::addSpecialDebugLevel(kDebugGameFlow, "Gameflow", "Gameflow debug level");
Common::addSpecialDebugLevel(kDebugFileIO, "FileIO", "File Input/Output debug level");
+ Common::addSpecialDebugLevel(kDebugSaveLoad, "SaveLoad", "Saving/Loading debug level");
Common::addSpecialDebugLevel(kDebugGraphics, "Graphics", "Graphics debug level");
Common::addSpecialDebugLevel(kDebugCollisions, "Collisions", "Collisions debug level");
@@ -353,7 +354,7 @@ bool GobEngine::initGameParts() {
_map = new Map_v4(this);
_goblin = new Goblin_v4(this);
_scenery = new Scenery_v2(this);
- _saveLoad = new SaveLoad_v3(this, _targetName.c_str());
+ _saveLoad = new SaveLoad_v4(this, _targetName.c_str());
break;
default:
diff --git a/engines/gob/gob.h b/engines/gob/gob.h
index e1d75bd2a4..0a82bceed5 100644
--- a/engines/gob/gob.h
+++ b/engines/gob/gob.h
@@ -104,8 +104,9 @@ enum {
kDebugParser = 1 << 4,
kDebugGameFlow = 1 << 5,
kDebugFileIO = 1 << 6,
- kDebugGraphics = 1 << 7,
- kDebugCollisions = 1 << 8
+ kDebugSaveLoad = 1 << 7,
+ kDebugGraphics = 1 << 8,
+ kDebugCollisions = 1 << 9
};
inline char *strncpy0(char *dest, const char *src, size_t n) {
diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp
index 36f33e6553..6f261e9822 100644
--- a/engines/gob/inter_v2.cpp
+++ b/engines/gob/inter_v2.cpp
@@ -1911,7 +1911,7 @@ bool Inter_v2::o2_checkData(OpFuncParams &params) {
int16 handle;
int16 varOff;
int32 size;
- SaveType type;
+ SaveLoad::SaveMode mode;
evalExpr(0);
varOff = _vm->_parse->parseVarIndex();
@@ -1919,8 +1919,8 @@ bool Inter_v2::o2_checkData(OpFuncParams &params) {
size = -1;
handle = 1;
- type = _vm->_saveLoad->getSaveType(_vm->_global->_inter_resStr);
- if (type == kSaveNone) {
+ mode = _vm->_saveLoad->getSaveMode(_vm->_global->_inter_resStr);
+ if (mode == SaveLoad::kSaveModeNone) {
handle = _vm->_dataIO->openData(_vm->_global->_inter_resStr);
if (handle >= 0) {
@@ -1928,8 +1928,8 @@ bool Inter_v2::o2_checkData(OpFuncParams &params) {
size = _vm->_dataIO->getDataSize(_vm->_global->_inter_resStr);
} else
warning("File \"%s\" not found", _vm->_global->_inter_resStr);
- } else
- size = _vm->_saveLoad->getSize(type);
+ } else if (mode == SaveLoad::kSaveModeSave)
+ size = _vm->_saveLoad->getSize(_vm->_global->_inter_resStr);
if (size == -1)
handle = -1;
@@ -1950,7 +1950,7 @@ bool Inter_v2::o2_readData(OpFuncParams &params) {
int16 dataVar;
int16 handle;
byte *buf;
- SaveType type;
+ SaveLoad::SaveMode mode;
evalExpr(0);
dataVar = _vm->_parse->parseVarIndex();
@@ -1962,13 +1962,14 @@ bool Inter_v2::o2_readData(OpFuncParams &params) {
debugC(2, kDebugFileIO, "Read from file \"%s\" (%d, %d bytes at %d)",
_vm->_global->_inter_resStr, dataVar, size, offset);
- type = _vm->_saveLoad->getSaveType(_vm->_global->_inter_resStr);
- if (type != kSaveNone) {
+ mode = _vm->_saveLoad->getSaveMode(_vm->_global->_inter_resStr);
+ if (mode == SaveLoad::kSaveModeSave) {
WRITE_VAR(1, 1);
- if (_vm->_saveLoad->load(type, dataVar, size, offset))
+ if (_vm->_saveLoad->load(_vm->_global->_inter_resStr, dataVar, size, offset))
WRITE_VAR(1, 0);
return false;
- }
+ } else if (mode == SaveLoad::kSaveModeIgnore)
+ return false;
if (size < 0) {
warning("Attempted to read a raw sprite from file \"%s\"",
@@ -2021,7 +2022,7 @@ bool Inter_v2::o2_writeData(OpFuncParams &params) {
int32 offset;
int32 size;
int16 dataVar;
- SaveType type;
+ SaveLoad::SaveMode mode;
evalExpr(0);
dataVar = _vm->_parse->parseVarIndex();
@@ -2034,11 +2035,11 @@ bool Inter_v2::o2_writeData(OpFuncParams &params) {
WRITE_VAR(1, 1);
- type = _vm->_saveLoad->getSaveType(_vm->_global->_inter_resStr);
- if (type != kSaveNone) {
- if (_vm->_saveLoad->save(type, dataVar, size, offset))
+ mode = _vm->_saveLoad->getSaveMode(_vm->_global->_inter_resStr);
+ if (mode == SaveLoad::kSaveModeSave) {
+ if (_vm->_saveLoad->save(_vm->_global->_inter_resStr, dataVar, size, offset))
WRITE_VAR(1, 0);
- } else
+ } else if (mode == SaveLoad::kSaveModeNone)
warning("Attempted to write to file \"%s\"", _vm->_global->_inter_resStr);
return false;
diff --git a/engines/gob/module.mk b/engines/gob/module.mk
index 09664f15b4..c95391cedc 100644
--- a/engines/gob/module.mk
+++ b/engines/gob/module.mk
@@ -44,6 +44,7 @@ MODULE_OBJS := \
saveload.o \
saveload_v2.o \
saveload_v3.o \
+ saveload_v4.o \
scenery.o \
scenery_v1.o \
scenery_v2.o \
diff --git a/engines/gob/saveload.cpp b/engines/gob/saveload.cpp
index 717bc143a6..e0854151a0 100644
--- a/engines/gob/saveload.cpp
+++ b/engines/gob/saveload.cpp
@@ -24,456 +24,493 @@
*/
#include "common/endian.h"
-#include "common/file.h"
+#include "common/savefile.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;
+TempSprite::TempSprite() {
+ _sprite = 0;
+ _width = _height = 0;
+ _size = -1;
+ memset(_palette, 0, 768);
+}
- _stagesCount = 0;
- _buffer = 0;
+TempSprite::~TempSprite() {
+ delete[] _sprite;
+}
- _tempSprite = 0;
- memset(_tempPal, 0, 768);
- _tempSpriteSize = -1;
+int TempSprite::getSpriteIndex(int32 size) const {
+ if (size < -1000)
+ size += 1000;
- _saveFiles = new char*[5];
+ return -size - 1;
+}
- assert(_saveFiles);
+bool TempSprite::getSpritePalette(int32 size) const {
+ return size < -1000;
+}
- _saveFiles[0] = new char[strlen(targetName) + 5];
- _saveFiles[1] = 0;
- _saveFiles[2] = new char[strlen(targetName) + 5];
- _saveFiles[3] = _saveFiles[0];
- _saveFiles[4] = 0;
+bool TempSprite::getProperties(int16 dataVar, int32 size, int32 offset,
+ int &index, bool &palette) const {
- assert(_saveFiles[0] && _saveFiles[2]);
+ if (size >= 0) {
+ warning("Invalid index (%d)", size);
+ return false;
+ }
- sprintf(_saveFiles[0], "%s.s00", targetName);
- sprintf(_saveFiles[2], "%s.blo", targetName);
-}
+ index = getSpriteIndex(size);
+ palette = getSpritePalette(size);
-SaveLoad::~SaveLoad() {
- if (_buffer) {
- for (int i = 0; i < _stagesCount; i++)
- delete[] _buffer[i];
- delete[] _buffer;
+ if ((index < 0) || (index >= SPRITES_COUNT)) {
+ warning("Index out of range (%d)", index);
+ return false;
}
- delete _tempSprite;
+ return true;
+}
- delete[] _saveFiles[0];
- delete[] _saveFiles[2];
- delete[] _saveFiles;
+int32 TempSprite::getSize() const {
+ return _size;
}
-const char *SaveLoad::setCurSlot(int slot) {
- static char *slotBase = _saveFiles[0] + strlen(_saveFiles[0]) - 2;
+bool TempSprite::saveSprite(const SurfaceDesc &surfDesc) {
+ delete[] _sprite;
- if (_curSlot != slot) {
- _curSlot = slot;
+ _width = surfDesc.getWidth();
+ _height = surfDesc.getHeight();
+ _size = _width * _height;
+ _sprite = new byte[_size];
- if (_curSlot >= 0)
- snprintf(slotBase, 3, "%02d", slot);
- }
+ memcpy(_sprite, surfDesc.getVidMem(), _size);
- return _saveFiles[0];
+ return true;
}
-uint32 SaveLoad::read(Common::ReadStream &in, byte *buf,
- byte *sizes, uint32 count) {
- uint32 nRead;
+bool TempSprite::savePalette(const Video::Color *palette) {
+ memcpy((byte *) _palette, (byte *) palette, 768);
+ return true;
+}
- nRead = in.read(buf, count);
- if (nRead != count) {
- warning("Can't read data: requested %d, got %d", count, nRead);
- return 0;
+bool TempSprite::loadSprite(SurfaceDesc &surfDesc) {
+ if (!_sprite) {
+ warning("No sprite saved");
+ return false;
}
- nRead = in.read(sizes, count);
- if (nRead != count) {
- warning("Can't read data sizes: requested %d, got %d", count, nRead);
- return 0;
+ if (_size != (surfDesc.getWidth() * surfDesc.getHeight())) {
+ warning("Dimensions don't match (%dx%d - %dx%d",
+ _width, _height, surfDesc.getWidth(), surfDesc.getHeight());
+ return false;
}
- return count;
+ memcpy(surfDesc.getVidMem(), _sprite, _size);
+
+ return true;
}
-uint32 SaveLoad::write(Common::WriteStream &out, byte *buf,
- byte *sizes, uint32 count) {
- uint32 written;
+bool TempSprite::loadPalette(Video::Color *palette) {
+ memcpy((byte *) palette, (byte *) _palette, 768);
+ return true;
+}
- written = out.write(buf, count);
- if (written != count) {
- warning("Can't write data: requested %d, wrote %d", count, written);
- return 0;
+bool TempSprite::toBuffer(byte *buffer, int32 size, bool palette) const {
+
+ int32 haveSize = _size + (palette ? 768 : 0);
+ if (size != haveSize) {
+ warning("Sizes don't match (%d != %d)", size, haveSize);
+ return false;
}
- written = out.write(sizes, count);
- if (written != count) {
- warning("Can't write data: requested %d, wrote %d", count, written);
- return 0;
+ if (palette) {
+ memcpy(buffer, (byte *) _palette, 768);
+ buffer += 768;
}
- return count;
+ memcpy(buffer, _sprite, _size);
+
+ return true;
}
-bool SaveLoad::loadDataEndian(Common::ReadStream &in,
- int16 dataVar, uint32 size) {
+bool TempSprite::fromBuffer(const byte *buffer, int32 size, bool palette) {
+ if (palette) {
+ memcpy((byte *) _palette, buffer, 768);
+ buffer += 768;
+ size -= 768;
+ }
- bool retVal = false;
+ _size = size;
- byte *varBuf = new byte[size];
- byte *sizeBuf = new byte[size];
+ delete[] _sprite;
+ _sprite = new byte[_size];
- assert(varBuf && sizeBuf);
+ memcpy(_sprite, buffer, _size);
- 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;
- }
- }
+ return true;
+}
- delete[] varBuf;
- delete[] sizeBuf;
- return retVal;
+PlainSave::PlainSave() {
}
-bool SaveLoad::saveDataEndian(Common::WriteStream &out,
- int16 dataVar, uint32 size) {
+PlainSave::~PlainSave() {
+}
- bool retVal = false;
+bool PlainSave::save(int16 dataVar, int32 size, int32 offset, const char *name,
+ const byte *variables, const byte *variableSizes) const {
- byte *varBuf = new byte[size];
- byte *sizeBuf = new byte[size];
+ if ((size <= 0) || (offset != 0)) {
+ warning("Invalid size (%d) or offset (%d)", size, offset);
+ return false;
+ }
- assert(varBuf && sizeBuf);
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ Common::OutSaveFile *out = saveMan->openForSaving(name);
- memcpy(varBuf, _vm->_global->_inter_variables + dataVar, size);
- memcpy(sizeBuf, _vm->_global->_inter_variablesSizes + dataVar, size);
+ if (!out) {
+ warning("Can't open file \"%s\" for writing", name);
+ return false;
+ }
- if (toEndian(varBuf, sizeBuf, size))
- if (write(out, varBuf, sizeBuf, size) == size)
- retVal = true;
+ bool retVal;
+ retVal = SaveLoad::saveDataEndian(*out, dataVar, size, variables, variableSizes);
- delete[] varBuf;
- delete[] sizeBuf;
+ out->finalize();
+ if (out->ioFailed()) {
+ warning("Can't write to file \"%s\"", name);
+ retVal = false;
+ }
+ delete out;
return retVal;
}
-int32 SaveLoad::getSize(SaveType type) {
- switch (type) {
- case kSaveNone:
- return -1;
- break;
-
- case kSaveGame:
- return getSizeGame();
- break;
+bool PlainSave::load(int16 dataVar, int32 size, int32 offset, const char *name,
+ byte *variables, byte *variableSizes) const {
- case kSaveTempSprite:
- return getSizeTempSprite();
- break;
-
- case kSaveNotes:
- return getSizeNotes();
- break;
+ if ((size <= 0) || (offset != 0)) {
+ warning("Invalid size (%d) or offset (%d)", size, offset);
+ return false;
+ }
- case kSaveScreenshot:
- return getSizeScreenshot();
- break;
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ Common::InSaveFile *in = saveMan->openForLoading(name);
- case kSaveIgnore:
- return -1;
- break;
+ if (!in) {
+ warning("Can't open file \"%s\" for reading", name);
+ return false;
}
- return -1;
+ bool retVal = SaveLoad::loadDataEndian(*in, dataVar, size, variables, variableSizes);
+ delete in;
+ return retVal;
}
-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;
+StagedSave::StagedSave() {
+ _mode = kModeNone;
+ _name = 0;
+ _loaded = false;
+}
- case kSaveNotes:
- return loadNotes(dataVar, size, offset);
- break;
+StagedSave::~StagedSave() {
+ clear();
+}
- case kSaveScreenshot:
- return loadScreenshot(dataVar, size, offset);
- break;
+void StagedSave::addStage(int32 size, bool endianed) {
+ int32 offset = 0;
- case kSaveIgnore:
- return true;
- break;
- }
+ if (!_stages.empty())
+ offset = _stages[_stages.size() - 1].offset +
+ _stages[_stages.size() - 1].size;
- return false;
+ Stage stage(size, offset, endianed);
+ _stages.push_back(stage);
}
-bool SaveLoad::save(SaveType type, int16 dataVar, int32 size, int32 offset) {
- switch (type) {
- case kSaveNone:
- return false;
- break;
+int StagedSave::findStage(int16 dataVar, int32 size, int32 offset) const {
+ for (uint i = 0; i < _stages.size(); i++)
+ if ((_stages[i].size == size) &&
+ (_stages[i].offset == offset))
+ return i;
+
+ return -1;
+}
- case kSaveGame:
- return saveGame(dataVar, size, offset);
- break;
+bool StagedSave::allSaved() const {
+ for (uint i = 0; i < _stages.size(); i++)
+ if (!_stages[i].bufVar)
+ return false;
- case kSaveTempSprite:
- return saveTempSprite(dataVar, size, offset);
- break;
+ return true;
+}
- case kSaveNotes:
- return saveNotes(dataVar, size, offset);
- break;
+uint32 StagedSave::getSize() const {
+ uint32 size = 0;
- case kSaveScreenshot:
- return saveScreenshot(dataVar, size, offset);
- break;
+ for (uint i = 0; i < _stages.size(); i++) {
+ if (_stages[i].endianed)
+ size += 2 * _stages[i].size;
+ else
+ size += _stages[i].size;
+ }
+
+ return size;
+}
- case kSaveIgnore:
- return true;
- break;
+void StagedSave::clear() {
+ for (uint i = 0; i < _stages.size(); i++) {
+ delete[] _stages[i].bufVar;
+ delete[] _stages[i].bufVarSizes;
+ _stages[i].bufVar = 0;
+ _stages[i].bufVarSizes = 0;
}
- return false;
+ delete[] _name;
+ _name = 0;
+
+ _mode = kModeNone;
+ _loaded = false;
}
-int32 SaveLoad::getSizeTempSprite() {
- return _tempSpriteSize;
+void StagedSave::assertMode(Mode mode, const char *name) {
+ if ((_mode != mode) || ((name[0] != '\0') && strcmp(_name, name))) {
+ clear();
+ _mode = mode;
+ _name = new char[strlen(name) + 1];
+ strcpy(_name, name);
+ }
}
-bool SaveLoad::loadTempSprite(int16 dataVar, int32 size, int32 offset) {
- int index;
- bool readPal;
+bool StagedSave::save(int16 dataVar, int32 size, int32 offset, const char *name,
+ const byte *variables, const byte *variableSizes) {
- if (size >= 0) {
- warning("Invalid attempt at loading from the temporary sprite");
+ if ((dataVar < 0) || (size <= 0) || (offset < 0)) {
+ warning("Invalid dataVar (%d), size (%d) or offset (%d)", dataVar, size, offset);
return false;
}
- index = getSpriteIndex(size);
- readPal = getSpritePalette(size);
+ int stage = findStage(dataVar, size, offset);
+ if (stage == -1) {
+ warning("Invalid saving procedure");
+ return false;
+ }
- if ((index < 0) || (index >= SPRITES_COUNT)) {
- warning("Index out of range while loading from the temporary "
- "sprite (%d)", index);
+ if (!variables || (_stages[stage].endianed && !variableSizes)) {
+ warning("Missing data");
return false;
}
- return loadTempSprite(index, readPal);
-}
+ assertMode(kModeSave, name);
-bool SaveLoad::saveTempSprite(int16 dataVar, int32 size, int32 offset) {
- int index;
- bool readPal;
+ _stages[stage].bufVar = new byte[size];
+ memcpy(_stages[stage].bufVar, variables + dataVar, size);
- if (size >= 0) {
- warning("Invalid attempt at saving to the temporary sprite");
- return false;
+ if (_stages[stage].endianed) {
+ _stages[stage].bufVarSizes = new byte[size];
+ memcpy(_stages[stage].bufVarSizes, variableSizes + dataVar, size);
}
- 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;
+ if (allSaved()) {
+ bool result = write();
+ clear();
+ return result;
}
- return saveTempSprite(index, readPal);
+ return true;
}
-bool SaveLoad::loadTempSprite(uint32 index, bool palette) {
- SurfaceDesc *sprite;
+bool StagedSave::load(int16 dataVar, int32 size, int32 offset, const char *name,
+ byte *variables, byte *variableSizes) {
- 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);
+ if ((dataVar < 0) || (size <= 0) || (offset < 0)) {
+ warning("Invalid dataVar (%d), size (%d) or offset (%d)", dataVar, size, offset);
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());
+ int stage = findStage(dataVar, size, offset);
+ if (stage == -1) {
+ warning("Invalid loading procedure");
return false;
}
- _vm->_video->drawSprite(_tempSprite, sprite, 0, 0,
- sprite->getWidth() - 1, sprite->getHeight() - 1, 0, 0, 0);
+ assertMode(kModeLoad, name);
- if (index == 21) {
- _vm->_draw->forceBlit();
- _vm->_video->retrace();
+ if (!_loaded) {
+ if (!read()) {
+ clear();
+ return false;
+ }
}
+ if (variables)
+ memcpy(variables + dataVar, _stages[stage].bufVar, size);
+ if (_stages[stage].endianed && variableSizes)
+ memcpy(variableSizes + dataVar, _stages[stage].bufVarSizes, size);
+
return true;
}
-bool SaveLoad::saveTempSprite(uint32 index, bool palette) {
- SurfaceDesc *sprite = _vm->_draw->_spritesArray[index];
+bool StagedSave::write() const {
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ Common::OutSaveFile *out = saveMan->openForSaving(_name);
- if (!sprite) {
- warning("Couldn't save to the temporary sprite: "
- "No such sprite %d", index);
+ if (!out) {
+ warning("Can't open file \"%s\" for writing", _name);
return false;
}
- delete _tempSprite;
- _tempSprite = _vm->_video->initSurfDesc(_vm->_global->_videoMode,
- sprite->getWidth(), sprite->getHeight(), 0);
+ bool result = true;
+ for (uint i = 0; (i < _stages.size()) && result; i++) {
+ if (!_stages[i].endianed) {
- _vm->_video->drawSprite(sprite, _tempSprite, 0, 0,
- sprite->getWidth() - 1, sprite->getHeight() - 1, 0, 0, 0);
+ uint32 written = out->write(_stages[i].bufVar, _stages[i].size);
- _tempSpriteSize = _vm->_draw->getSpriteRectSize(index);
+ result = (written == ((uint32) _stages[i].size));
+ if (!result)
+ warning("Can't write data: requested %d, wrote %d", _stages[i].size, written);
- if (palette) {
- memcpy((char *) _tempPal,
- (char *) _vm->_global->_pPaletteDesc->vgaPal, 768);
- _tempSpriteSize += 768;
+ } else
+ result = SaveLoad::saveDataEndian(*out, 0, _stages[i].size,
+ _stages[i].bufVar, _stages[i].bufVarSizes);
}
- return true;
+ if (result) {
+ out->finalize();
+ if (out->ioFailed()) {
+ warning("Can't write to file \"%s\"", _name);
+ result = false;
+ }
+ }
+
+ delete out;
+ return result;
}
-bool SaveLoad::loadSprite(Common::ReadStream &in, int32 size) {
- SurfaceDesc *sprite;
- byte *buf;
- int nRead;
- int index;
- bool readPal;
+bool StagedSave::read() {
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ Common::InSaveFile *in = saveMan->openForLoading(_name);
- if (size >= 0) {
- warning("Invalid attempt at loading a sprite");
+ if (!in) {
+ warning("Can't open file \"%s\" for reading", _name);
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);
+ uint32 saveSize = getSize();
+ if (in->size() != saveSize) {
+ warning("Wrong size (%d != %d)", in->size(), saveSize);
return false;
}
- size = _vm->_draw->getSpriteRectSize(index);
- sprite = _vm->_draw->_spritesArray[index];
+ bool result = true;
+ for (uint i = 0; ((i < _stages.size()) && result); i++) {
+ _stages[i].bufVar = new byte[_stages[i].size];
- if (!sprite) {
- warning("Couldn't load sprite: No such sprite %d", index);
- return false;
- }
+ if (!_stages[i].endianed) {
- buf = new byte[MAX<int>(768, size)];
- assert(buf);
+ uint32 nRead = in->read(_stages[i].bufVar, _stages[i].size);
- 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;
- }
+ result = (nRead == ((uint32) _stages[i].size));
+ if (!result)
+ warning("Can't read data: requested %d, got %d", _stages[i].size, nRead);
- memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal,
- (char *) buf, 768);
- _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
- }
+ } else {
+ _stages[i].bufVarSizes = new byte[_stages[i].size];
- nRead = in.read(buf, size);
- if (nRead != size) {
- warning("Couldn't read sprite data: requested %d, got %d", size, nRead);
- delete[] buf;
- return false;
+ result = SaveLoad::loadDataEndian(*in, 0, _stages[i].size,
+ _stages[i].bufVar, _stages[i].bufVarSizes);
+ }
}
- memcpy((char *) sprite->getVidMem(), buf, size);
+ if (result)
+ _loaded = true;
- delete[] buf;
- return true;
+ delete in;
+ return result;
}
-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;
- }
+SaveLoad::SaveLoad(GobEngine *vm, const char *targetName) : _vm(vm) {
- index = getSpriteIndex(size);
- readPal = getSpritePalette(size);
+ _targetName = new char[strlen(targetName) + 1];
+ strcpy(_targetName, targetName);
+}
- if ((index < 0) || (index >= SPRITES_COUNT)) {
- warning("Index out of range while saving a sprite (%d)",
- index);
- return false;
- }
+SaveLoad::~SaveLoad() {
+ delete[] _targetName;
+}
+
+int32 SaveLoad::getSize(const char *fileName) {
+ int type;
+
+ type = getSaveType(stripPath(fileName));
+ if (type == -1)
+ return -1;
+
+ debugC(3, kDebugSaveLoad, "Requested size of save file \"%s\" (type %d)",
+ fileName, type);
+
+ return getSizeVersioned(type);
+}
- size = _vm->_draw->getSpriteRectSize(index);
- sprite = _vm->_draw->_spritesArray[index];
+bool SaveLoad::load(const char *fileName, int16 dataVar, int32 size, int32 offset) {
+ int type;
- if (!sprite) {
- warning("Couldn't save sprite: No such sprite %d", index);
+ type = getSaveType(stripPath(fileName));
+ if (type == -1)
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;
- }
- }
+ debugC(3, kDebugSaveLoad, "Requested loading of save file \"%s\" (type %d) - %d, %d, %d",
+ fileName, type, dataVar, size, offset);
- written = out.write((char *) sprite->getVidMem(), size);
- if (written != size) {
- warning("Couldn't write a sprite: requested %d, wrote %d",
- size, written);
+ return loadVersioned(type, dataVar, size, offset);
+}
+
+bool SaveLoad::save(const char *fileName, int16 dataVar, int32 size, int32 offset) {
+ int type;
+
+ type = getSaveType(stripPath(fileName));
+ if (type == -1)
return false;
- }
- return true;
+ debugC(3, kDebugSaveLoad, "Requested saving of save file \"%s\" (type %d) - %d, %d, %d",
+ fileName, type, dataVar, size, offset);
+
+ return saveVersioned(type, dataVar, size, offset);
+}
+
+const char *SaveLoad::stripPath(const char *fileName) {
+ const char *backSlash;
+ if ((backSlash = strrchr(fileName, '\\')))
+ return backSlash + 1;
+
+ return fileName;
+}
+
+char *SaveLoad::setCurrentSlot(char *destName, int slot) {
+ char *slotBase = destName + strlen(destName) - 2;
+
+ snprintf(slotBase, 3, "%02d", slot);
+
+ return destName;
+}
+
+void SaveLoad::buildIndex(byte *buffer, char *name, int n, int32 size, int32 offset) {
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ Common::InSaveFile *in;
+
+ for (int i = 0; i < n; i++, buffer += size) {
+ in = saveMan->openForLoading(setCurrentSlot(name, i));
+ if (in) {
+ in->seek(offset);
+ in->read(buffer, size);
+ delete in;
+ } else
+ memset(buffer, 0, size);
+ }
}
bool SaveLoad::fromEndian(byte *buf, const byte *sizes, uint32 count) {
@@ -514,4 +551,89 @@ bool SaveLoad::toEndian(byte *buf, const byte *sizes, uint32 count) {
return true;
}
+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,
+ const byte *buf, const 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, byte *variables, byte *variableSizes) {
+
+ 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(variables + dataVar, varBuf, size);
+ memcpy(variableSizes + dataVar, sizeBuf, size);
+ retVal = true;
+ }
+ }
+
+ delete[] varBuf;
+ delete[] sizeBuf;
+
+ return retVal;
+}
+
+bool SaveLoad::saveDataEndian(Common::WriteStream &out,
+ int16 dataVar, uint32 size, const byte *variables, const byte *variableSizes) {
+
+ bool retVal = false;
+
+ byte *varBuf = new byte[size];
+ byte *sizeBuf = new byte[size];
+
+ assert(varBuf && sizeBuf);
+
+ memcpy(varBuf, variables + dataVar, size);
+ memcpy(sizeBuf, variableSizes + dataVar, size);
+
+ if (toEndian(varBuf, sizeBuf, size))
+ if (write(out, varBuf, sizeBuf, size) == size)
+ retVal = true;
+
+ delete[] varBuf;
+ delete[] sizeBuf;
+
+ return retVal;
+}
+
} // End of namespace Gob
diff --git a/engines/gob/saveload.h b/engines/gob/saveload.h
index bf1e4c01a8..9b032cc73f 100644
--- a/engines/gob/saveload.h
+++ b/engines/gob/saveload.h
@@ -26,143 +26,317 @@
#ifndef GOB_SAVELOAD_H
#define GOB_SAVELOAD_H
+#include "common/array.h"
#include "common/stream.h"
#include "gob/video.h"
namespace Gob {
-enum SaveType {
- kSaveNone = -1,
- kSaveGame,
- kSaveTempSprite,
- kSaveNotes,
- kSaveScreenshot,
- kSaveIgnore
+class TempSprite {
+public:
+ TempSprite();
+ ~TempSprite();
+
+ bool getProperties(int16 dataVar, int32 size, int32 offset,
+ int &index, bool &palette) const;
+
+ int32 getSize() const;
+
+ bool saveSprite(const SurfaceDesc &surfDesc);
+ bool savePalette(const Video::Color *palette);
+ bool loadSprite(SurfaceDesc &surfDesc);
+ bool loadPalette(Video::Color *palette);
+
+ bool toBuffer(byte *buffer, int32 size, bool palette) const;
+ bool fromBuffer(const byte *buffer, int32 size, bool palette);
+
+private:
+ byte *_sprite;
+ int16 _width;
+ int16 _height;
+ int32 _size;
+ Video::Color _palette[256];
+
+ int getSpriteIndex(int32 size) const;
+ bool getSpritePalette(int32 size) const;
};
-class SaveLoad {
+class PlainSave {
+public:
+ PlainSave();
+ ~PlainSave();
+
+ bool save(int16 dataVar, int32 size, int32 offset, const char *name,
+ const byte *variables, const byte *variableSizes) const;
+ bool load(int16 dataVar, int32 size, int32 offset, const char *name,
+ byte *variables, byte *variableSizes) const;
+};
+
+class StagedSave {
public:
- int32 getSize(SaveType type);
- bool load(SaveType type, int16 dataVar, int32 size, int32 offset);
- bool save(SaveType type, int16 dataVar, int32 size, int32 offset);
+ StagedSave();
+ ~StagedSave();
+
+ void addStage(int32 size, bool endianed = true);
+
+ bool save(int16 dataVar, int32 size, int32 offset, const char *name,
+ const byte *variables, const byte *variableSizes);
+ bool load(int16 dataVar, int32 size, int32 offset, const char *name,
+ byte *variables, byte *variableSizes);
+
+private:
+ struct Stage {
+ byte *bufVar;
+ byte *bufVarSizes;
+ int32 size;
+ int32 offset;
+ bool endianed;
+
+ Stage(int32 s = 0, int32 off = 0, bool end = true) :
+ bufVar(0), bufVarSizes(0), size(s), offset(off), endianed(end) {}
+ };
+
+ enum Mode {
+ kModeNone,
+ kModeSave,
+ kModeLoad
+ };
+
+ Common::Array<Stage> _stages;
+ enum Mode _mode;
+ char *_name;
+
+ bool _loaded;
- virtual SaveType getSaveType(const char *fileName) = 0;
+ int findStage(int16 dataVar, int32 size, int32 offset) const;
+ bool allSaved() const;
+
+ uint32 getSize() const;
+
+ void clear();
+ void assertMode(Mode mode, const char *name);
+
+ bool write() const;
+ bool read();
+};
+
+class SaveLoad {
+public:
+ enum SaveMode {
+ kSaveModeNone,
+ kSaveModeIgnore,
+ kSaveModeSave
+ };
SaveLoad(GobEngine *vm, const char *targetName);
virtual ~SaveLoad();
-protected:
- int _curSlot;
- char **_saveFiles;
+ virtual SaveMode getSaveMode(const char *fileName) = 0;
+
+ int32 getSize(const char *fileName);
+ bool load(const char *fileName, int16 dataVar, int32 size, int32 offset);
+ bool save(const char *fileName, int16 dataVar, int32 size, int32 offset);
+
+ char *setCurrentSlot(char *destName, int slot);
+ void buildIndex(byte *buffer, char *name, int n, int32 size, int32 offset = 0);
- int _stagesCount;
- byte **_buffer;
+ static const char *stripPath(const char *fileName);
- // While using the notepad or changing the font, the original executable
- // temporarily dumps Draw::_backSurface to a file. Since that's not really
- // a nice thing to do, we work around it.
- SurfaceDesc *_tempSprite;
- Video::Color _tempPal[256];
- int32 _tempSpriteSize;
+ static bool fromEndian(byte *buf, const byte *sizes, uint32 count);
+ static bool toEndian(byte *buf, const byte *sizes, uint32 count);
+ static uint32 read(Common::ReadStream &in,
+ byte *buf, byte *sizes, uint32 count);
+ static uint32 write(Common::WriteStream &out,
+ const byte *buf, const byte *sizes, uint32 count);
+ static bool loadDataEndian(Common::ReadStream &in,
+ int16 dataVar, uint32 size, byte *variables, byte *variableSizes);
+ static bool saveDataEndian(Common::WriteStream &out,
+ int16 dataVar, uint32 size, const byte *variables, const byte *variableSizes);
+
+protected:
GobEngine *_vm;
- int getSpriteIndex(int32 size) {
- if (size < -1000)
- size += 1000;
-
- return -size - 1;
- }
- bool getSpritePalette(int32 size) {
- return size < -1000;
- }
-
- const char *setCurSlot(int slot);
- bool fromEndian(byte *buf, const byte *sizes, uint32 count);
- bool toEndian(byte *buf, const byte *sizes, uint32 count);
- uint32 read(Common::ReadStream &in, byte *buf,
- byte *sizes, uint32 count);
- uint32 write(Common::WriteStream &out, byte *buf,
- byte *sizes, uint32 count);
-
- bool loadDataEndian(Common::ReadStream &in, int16 dataVar, uint32 size);
- bool saveDataEndian(Common::WriteStream &out, int16 dataVar, uint32 size);
-
- bool loadTempSprite(uint32 index, bool palette);
- bool saveTempSprite(uint32 index, bool palette);
- bool loadSprite(Common::ReadStream &in, int32 size);
- bool saveSprite(Common::WriteStream &out, int32 size);
-
- int32 getSizeTempSprite();
- bool loadTempSprite(int16 dataVar, int32 size, int32 offset);
- bool saveTempSprite(int16 dataVar, int32 size, int32 offset);
-
- virtual uint32 getSaveGameSize() = 0;
-
- virtual int32 getSizeGame() = 0;
- virtual int32 getSizeNotes() = 0;
- virtual int32 getSizeScreenshot() = 0;
- virtual bool loadGame(int16 dataVar, int32 size, int32 offset) = 0;
- virtual bool loadNotes(int16 dataVar, int32 size, int32 offset) = 0;
- virtual bool loadScreenshot(int16 dataVar, int32 size, int32 offset) = 0;
- virtual bool saveGame(int16 dataVar, int32 size, int32 offset) = 0;
- virtual bool saveNotes(int16 dataVar, int32 size, int32 offset) = 0;
- virtual bool saveScreenshot(int16 dataVar, int32 size, int32 offset) = 0;
+ char *_targetName;
+
+ virtual int getSaveType(const char *fileName) = 0;
+
+ virtual int32 getSizeVersioned(int type) = 0;
+ virtual bool loadVersioned(int type, int16 dataVar, int32 size, int32 offset) = 0;
+ virtual bool saveVersioned(int type, int16 dataVar, int32 size, int32 offset) = 0;
};
class SaveLoad_v2 : public SaveLoad {
public:
- virtual SaveType getSaveType(const char *fileName);
+ enum SaveType {
+ kSaveGame,
+ kSaveTempSprite,
+ kSaveNotes
+ };
SaveLoad_v2(GobEngine *vm, const char *targetName);
- virtual ~SaveLoad_v2() {}
+ virtual ~SaveLoad_v2();
+
+ virtual SaveMode getSaveMode(const char *fileName);
protected:
- virtual uint32 getSaveGameSize();
-
- virtual int32 getSizeGame();
- virtual int32 getSizeNotes();
- virtual int32 getSizeScreenshot();
- virtual bool loadGame(int16 dataVar, int32 size, int32 offset);
- virtual bool loadNotes(int16 dataVar, int32 size, int32 offset);
- virtual bool loadScreenshot(int16 dataVar, int32 size, int32 offset);
- virtual bool saveGame(int16 dataVar, int32 size, int32 offset);
- virtual bool saveNotes(int16 dataVar, int32 size, int32 offset);
- virtual bool saveScreenshot(int16 dataVar, int32 size, int32 offset);
-
- void initBuffer();
+ struct SaveFile {
+ const char *sourceName;
+ char *destName;
+ SaveMode mode;
+ SaveType type;
+ };
+
+ static SaveFile _saveFiles[];
+
+ int32 _varSize;
+
+ TempSprite _tmpSprite;
+ PlainSave _notes;
+ StagedSave _save;
+
+ byte _indexBuffer[600];
+ bool _hasIndex;
+
+ virtual int getSaveType(const char *fileName);
+
+ virtual int32 getSizeVersioned(int type);
+ virtual bool loadVersioned(int type, int16 dataVar, int32 size, int32 offset);
+ virtual bool saveVersioned(int type, int16 dataVar, int32 size, int32 offset);
+
+ int getSlot(int32 offset) const;
+ int getSlotRemainder(int32 offset) const;
+
+ int32 getSizeGame(SaveFile &saveFile);
+ int32 getSizeTempSprite(SaveFile &saveFile);
+ int32 getSizeNotes(SaveFile &saveFile);
+
+ bool loadGame(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool loadTempSprite(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool loadNotes(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+
+ bool saveGame(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool saveTempSprite(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool saveNotes(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+
+ void assertInited();
};
-class SaveLoad_v3 : public SaveLoad_v2 {
-public:
- virtual SaveType getSaveType(const char *fileName);
+enum SaveType {
+ kSaveNone = -1,
+ kSaveGame,
+ kSaveTempSprite,
+ kSaveNotes,
+ kSaveScreenshot,
+ kSaveIgnore
+};
- SaveLoad_v3(GobEngine *vm, const char *targetName, uint32 screenshotSize = 19968,
+class SaveLoad_v3 : public SaveLoad {
+public:
+ enum SaveType {
+ kSaveNone,
+ kSaveGame,
+ kSaveTempSprite,
+ kSaveNotes,
+ kSaveScreenshot
+ };
+
+ SaveLoad_v3(GobEngine *vm, const char *targetName,
+ uint32 screenshotSize = 19968,
int32 indexOffset = 40, int32 screenshotOffset = 80);
- virtual ~SaveLoad_v3() {}
+ virtual ~SaveLoad_v3();
+
+ virtual SaveMode getSaveMode(const char *fileName);
protected:
+ struct SaveFile {
+ const char *sourceName;
+ char *destName;
+ SaveMode mode;
+ SaveType type;
+ int slot;
+ };
+
bool _useScreenshots;
bool _firstSizeGame;
- int8 _saveSlot;
uint32 _screenshotSize;
int32 _indexOffset;
int32 _screenshotOffset;
- virtual uint32 getSaveGameSize();
+ static SaveFile _saveFiles[];
+
+ int32 _varSize;
+
+ TempSprite _screenshot;
+ TempSprite _tmpSprite;
+ PlainSave _notes;
+ StagedSave _save;
+
+ byte _propBuffer[1000];
+ byte _indexBuffer[1200];
+ bool _hasIndex;
+
+ virtual int getSaveType(const char *fileName);
+
+ virtual int32 getSizeVersioned(int type);
+ virtual bool loadVersioned(int type, int16 dataVar, int32 size, int32 offset);
+ virtual bool saveVersioned(int type, int16 dataVar, int32 size, int32 offset);
+
+ int getSlot(int32 offset) const;
+ int getSlotRemainder(int32 offset) const;
+
+ int32 getSizeGame(SaveFile &saveFile);
+ int32 getSizeTempSprite(SaveFile &saveFile);
+ int32 getSizeNotes(SaveFile &saveFile);
+ int32 getSizeScreenshot(SaveFile &saveFile);
+
+ bool loadGame(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool loadTempSprite(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool loadNotes(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool loadScreenshot(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+
+ bool saveGame(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool saveTempSprite(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool saveNotes(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool saveScreenshot(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+
+ void assertInited();
+
+ void buildScreenshotIndex(byte *buffer, char *name, int n);
+};
+
+class SaveLoad_v4 : public SaveLoad {
+public:
+ enum SaveType {
+ kSaveNone
+ };
+
+ SaveLoad_v4(GobEngine *vm, const char *targetName);
+ virtual ~SaveLoad_v4();
+
+ virtual SaveMode getSaveMode(const char *fileName);
+
+protected:
+ struct SaveFile {
+ const char *sourceName;
+ char *destName;
+ SaveMode mode;
+ SaveType type;
+ };
+
+ static SaveFile _saveFiles[];
+
+ int32 _varSize;
+
+ virtual int getSaveType(const char *fileName);
- virtual int32 getSizeGame();
- virtual int32 getSizeScreenshot();
- virtual bool loadGame(int16 dataVar, int32 size, int32 offset);
- virtual bool loadScreenshot(int16 dataVar, int32 size, int32 offset);
- virtual bool saveGame(int16 dataVar, int32 size, int32 offset);
- virtual bool saveNotes(int16 dataVar, int32 size, int32 offset);
- virtual bool saveScreenshot(int16 dataVar, int32 size, int32 offset);
+ virtual int32 getSizeVersioned(int type);
+ virtual bool loadVersioned(int type, int16 dataVar, int32 size, int32 offset);
+ virtual bool saveVersioned(int type, int16 dataVar, int32 size, int32 offset);
- bool saveGame(int32 screenshotSize);
- void initBuffer();
+ void assertInited();
};
} // End of namespace Gob
diff --git a/engines/gob/saveload_v2.cpp b/engines/gob/saveload_v2.cpp
index ab7211b216..2754646198 100644
--- a/engines/gob/saveload_v2.cpp
+++ b/engines/gob/saveload_v2.cpp
@@ -24,273 +24,346 @@
*/
#include "common/endian.h"
-#include "common/file.h"
+#include "common/savefile.h"
#include "gob/gob.h"
#include "gob/saveload.h"
#include "gob/global.h"
#include "gob/game.h"
+#include "gob/draw.h"
namespace Gob {
+SaveLoad_v2::SaveFile SaveLoad_v2::_saveFiles[] = {
+ { "cat.inf", 0, kSaveModeSave, kSaveGame},
+ { "cat.cat", 0, kSaveModeSave, kSaveGame},
+ { "save.inf", 0, kSaveModeSave, kSaveTempSprite},
+ { "bloc.inf", 0, kSaveModeSave, kSaveNotes}
+};
+
SaveLoad_v2::SaveLoad_v2(GobEngine *vm, const char *targetName) :
- SaveLoad(vm, targetName) {
+ SaveLoad(vm, targetName) {
+
+ _saveFiles[0].destName = new char[strlen(targetName) + 5];
+ _saveFiles[1].destName = _saveFiles[0].destName;
+ _saveFiles[2].destName = 0;
+ _saveFiles[3].destName = new char[strlen(targetName) + 5];
- _stagesCount = 1;
+ sprintf(_saveFiles[0].destName, "%s.s00", targetName);
+ sprintf(_saveFiles[3].destName, "%s.blo", targetName);
+
+ _varSize = 0;
+ _hasIndex = false;
}
-SaveType SaveLoad_v2::getSaveType(const char *fileName) {
- const char *backSlash;
- if ((backSlash = strrchr(fileName, '\\')))
- fileName = backSlash + 1;
-
- if (!scumm_stricmp(fileName, "cat.inf"))
- return kSaveGame;
- if (!scumm_stricmp(fileName, "cat.cat"))
- return kSaveGame;
- if (!scumm_stricmp(fileName, "save.inf"))
- return kSaveTempSprite;
- if (!scumm_stricmp(fileName, "bloc.inf"))
- return kSaveNotes;
-
- return kSaveNone;
+SaveLoad_v2::~SaveLoad_v2() {
+ delete[] _saveFiles[0].destName;
+ delete[] _saveFiles[3].destName;
}
-uint32 SaveLoad_v2::getSaveGameSize() {
- return 80 + (READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4) * 2;
+SaveLoad::SaveMode SaveLoad_v2::getSaveMode(const char *fileName) {
+ for (int i = 0; i < ARRAYSIZE(_saveFiles); i++)
+ if (!scumm_stricmp(fileName, _saveFiles[i].sourceName))
+ return _saveFiles[i].mode;
+
+ return kSaveModeNone;
}
-int32 SaveLoad_v2::getSizeNotes() {
- Common::SaveFileManager *saveMan = g_system->getSavefileManager();
- Common::InSaveFile *in;
- int32 size = -1;
+int SaveLoad_v2::getSaveType(const char *fileName) {
+ for (int i = 0; i < ARRAYSIZE(_saveFiles); i++)
+ if (!scumm_stricmp(fileName, _saveFiles[i].sourceName))
+ return i;
- in = saveMan->openForLoading(_saveFiles[(int) kSaveNotes]);
- if (in) {
- size = in->size();
- delete in;
+ return -1;
+}
+
+int32 SaveLoad_v2::getSizeVersioned(int type) {
+ assertInited();
+
+ switch (_saveFiles[type].type) {
+ case kSaveGame:
+ return getSizeGame(_saveFiles[type]);
+ case kSaveTempSprite:
+ return getSizeTempSprite(_saveFiles[type]);
+ case kSaveNotes:
+ return getSizeNotes(_saveFiles[type]);
}
- return size;
+ return -1;
}
-int32 SaveLoad_v2::getSizeGame() {
+bool SaveLoad_v2::loadVersioned(int type, int16 dataVar, int32 size, int32 offset) {
+ assertInited();
+
+ switch (_saveFiles[type].type) {
+ case kSaveGame:
+ if (loadGame(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While loading from slot %d", getSlot(offset));
+ break;
+
+ case kSaveTempSprite:
+ if(loadTempSprite(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While loading the temporary sprite");
+ break;
+
+ case kSaveNotes:
+ if (loadNotes(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While loading the notes");
+ break;
+ }
+
+ return false;
+}
+
+bool SaveLoad_v2::saveVersioned(int type, int16 dataVar, int32 size, int32 offset) {
+ assertInited();
+
+ switch (_saveFiles[type].type) {
+ case kSaveGame:
+ if (saveGame(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While saving to slot %d", getSlot(offset));
+ break;
+
+ case kSaveTempSprite:
+ if(saveTempSprite(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While saving the temporary sprite");
+ break;
+
+ case kSaveNotes:
+ if (saveNotes(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While saving the notes");
+ break;
+ }
+
+ return false;
+}
+
+int SaveLoad_v2::getSlot(int32 offset) const {
+ return ((offset - 600) / _varSize);
+}
+
+int SaveLoad_v2::getSlotRemainder(int32 offset) const {
+ return ((offset - 600) % _varSize);
+}
+
+int32 SaveLoad_v2::getSizeGame(SaveFile &saveFile) {
Common::SaveFileManager *saveMan = g_system->getSavefileManager();
Common::InSaveFile *in;
for (int i = 14; i >= 0; i--) {
- in = saveMan->openForLoading(setCurSlot(i));
+ in = saveMan->openForLoading(setCurrentSlot(saveFile.destName, i));
if (in) {
delete in;
- return (i + 1) * READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) *
- 4 + 600;
+ return (i + 1) * _varSize + 600;
}
}
return -1;
}
-int32 SaveLoad_v2::getSizeScreenshot() {
- return -1;
+int32 SaveLoad_v2::getSizeTempSprite(SaveFile &saveFile) {
+ return _tmpSprite.getSize();
}
-bool SaveLoad_v2::loadGame(int16 dataVar, int32 size, int32 offset) {
+int32 SaveLoad_v2::getSizeNotes(SaveFile &saveFile) {
Common::SaveFileManager *saveMan = g_system->getSavefileManager();
Common::InSaveFile *in;
- int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
+ int32 size = -1;
+
+ in = saveMan->openForLoading(saveFile.destName);
+ if (in) {
+ size = in->size();
+ delete in;
+ }
+
+ return size;
+}
+
+bool SaveLoad_v2::loadGame(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
if (size == 0) {
dataVar = 0;
- size = varSize;
+ size = _varSize;
}
- int slot = (offset - 600) / varSize;
- int slotR = (offset - 600) % varSize;
-
- if ((offset == 0) && (size == 600)) {
+ if (offset == 0) {
+ debugC(3, kDebugSaveLoad, "Loading save index");
- byte *varBuf = _vm->_global->_inter_variables + dataVar;
- for (int i = 0; i < 15; i++, varBuf += 40) {
- in = saveMan->openForLoading(setCurSlot(i));
- if (in) {
- in->read(varBuf, 40);
- delete in;
- } else
- memset(varBuf, 0, 40);
+ if (size != 600) {
+ warning("Requested index has wrong size (%d)", size);
+ return false;
}
+
+ SaveLoad::buildIndex(_vm->_global->_inter_variables + dataVar,
+ saveFile.destName, 15, 40);
memset(_vm->_global->_inter_variablesSizes + dataVar, 0, 600);
- return true;
- } else if ((offset > 0) && (slot < 15) &&
- (slotR == 0) && (size == varSize)) {
+ } else {
+ int slot = getSlot(offset);
+ int slotRem = getSlotRemainder(offset);
+
+ debugC(2, kDebugSaveLoad, "Loading from slot %d", slot);
- in = saveMan->openForLoading(setCurSlot(slot));
- if (!in) {
- warning("Can't open file for slot %d", slot);
+ SaveLoad::setCurrentSlot(saveFile.destName, slot);
+
+ if ((slot >= 15) || (slotRem != 0)) {
+ warning("Invalid loading procedure (%d, %d, %d, %d, %d)",
+ dataVar, size, offset, slot, slotRem);
return false;
}
- uint32 sGameSize = getSaveGameSize();
- uint32 fSize = in->size();
- if (fSize != sGameSize) {
- warning("Can't load from slot %d: Wrong size (%d, %d)", slot,
- fSize, sGameSize);
- delete in;
+ if (!_save.load(dataVar, size, 40, saveFile.destName,
+ _vm->_global->_inter_variables, _vm->_global->_inter_variablesSizes))
return false;
- }
+ }
- in->seek(80);
- if (loadDataEndian(*in, dataVar, size)) {
- delete in;
- debugC(1, kDebugFileIO, "Loading from slot %d", slot);
- return true;
- }
- delete in;
+ return true;
+}
- } else
- warning("Invalid loading procedure (%d, %d, %d, %d)",
- offset, size, slot, slotR);
+bool SaveLoad_v2::loadTempSprite(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
- return false;
-}
+ debugC(3, kDebugSaveLoad, "Loading from the temporary sprite");
-bool SaveLoad_v2::loadNotes(int16 dataVar, int32 size, int32 offset) {
- bool retVal;
+ int index;
+ bool palette;
- if ((size <= 0) || (offset != 0)) {
- warning("Invalid attempt at loading the notes (%d, %d)", size, offset);
+ if (!_tmpSprite.getProperties(dataVar, size, offset, index, palette))
return false;
- }
-
- Common::SaveFileManager *saveMan = g_system->getSavefileManager();
- char *sName = _saveFiles[(int) kSaveNotes];
- Common::InSaveFile *in = saveMan->openForLoading(sName);
- if (!in) {
- warning("Can't open file \"%s\" for reading", sName);
+ if (!_tmpSprite.loadSprite(*_vm->_draw->_spritesArray[index]))
return false;
+
+ if (palette) {
+ if (!_tmpSprite.loadPalette(_vm->_global->_pPaletteDesc->vgaPal))
+ return false;
+
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
}
- retVal = loadDataEndian(*in, dataVar, size);
- delete in;
- return retVal;
-}
+ if (index == 21) {
+ _vm->_draw->forceBlit();
+ _vm->_video->retrace();
+ }
-bool SaveLoad_v2::loadScreenshot(int16 dataVar, int32 size, int32 offset) {
- return false;
+ return true;
}
-bool SaveLoad_v2::saveGame(int16 dataVar, int32 size, int32 offset) {
- int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
+bool SaveLoad_v2::loadNotes(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
+
+ debugC(2, kDebugSaveLoad, "Loading the notes");
+
+ return _notes.load(dataVar, size, offset, saveFile.destName,
+ _vm->_global->_inter_variables, _vm->_global->_inter_variablesSizes);
+}
- initBuffer();
+bool SaveLoad_v2::saveGame(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
if (size == 0) {
dataVar = 0;
- size = varSize;
+ size = _varSize;
}
- int slot = (offset - 600) / varSize;
- int slotR = (offset - 600) % varSize;
+ if (offset == 0) {
+ debugC(3, kDebugSaveLoad, "Saving save index");
- if ((offset == 0) && (size == 600)) {
+ if (size != 600) {
+ warning("Requested index has wrong size (%d)", size);
+ return false;
+ }
- delete[] _buffer[0];
- _buffer[0] = new byte[1200];
- assert(_buffer[0]);
+ memcpy(_indexBuffer, _vm->_global->_inter_variables + dataVar, 600);
+ _hasIndex = true;
- memcpy(_buffer[0], _vm->_global->_inter_variables + dataVar, 600);
- memset(_buffer[0] + 600, 0, 600);
+ } else {
+ int slot = getSlot(offset);
+ int slotRem = getSlotRemainder(offset);
- return true;
+ debugC(2, kDebugSaveLoad, "Saving to slot %d", slot);
- } else if ((offset > 0) && (slot < 15) &&
- (slotR == 0) && (size == varSize)) {
+ SaveLoad::setCurrentSlot(saveFile.destName, slot);
- if (!_buffer[0]) {
- warning("Tried to save without writing the index first");
+ if ((slot >= 15) || (slotRem != 0)) {
+ warning("Invalid saving procedure (%d, %d, %d, %d, %d)",
+ dataVar, size, offset, slot, slotRem);
return false;
}
- Common::SaveFileManager *saveMan = g_system->getSavefileManager();
- Common::OutSaveFile *out;
-
- out = saveMan->openForSaving(setCurSlot(slot));
- if (!out) {
- warning("Can't open file for slot %d for writing", slot);
- delete[] _buffer[0];
- _buffer[0] = 0;
+ if (!_hasIndex) {
+ warning("No index written yet");
return false;
}
- bool retVal = false;
+ _hasIndex = false;
- if (out->write(_buffer[0] + slot * 40, 40) == 40)
- if (out->write(_buffer[0] + 600 + slot * 40, 40) == 40)
- if (saveDataEndian(*out, dataVar, size)) {
- out->finalize();
- if (!out->ioFailed())
- retVal = true;
- }
-
- if (!retVal)
- warning("Can't save to slot %d", slot);
- else
- debugC(1, kDebugFileIO, "Saved to slot %d", slot);
-
- delete[] _buffer[0];
- _buffer[0] = 0;
- delete out;
+ byte sizes[40];
+ memset(sizes, 0, 40);
+ if(!_save.save(0, 40, 0, saveFile.destName, _indexBuffer + (slot * 40), sizes))
+ return false;
- return retVal;
+ if (!_save.save(dataVar, size, 40, saveFile.destName,
+ _vm->_global->_inter_variables, _vm->_global->_inter_variablesSizes))
+ return false;
- } else
- warning("Invalid saving procedure (%d, %d, %d, %d)",
- offset, size, slot, slotR);
+ }
- return false;
+ return true;
}
-bool SaveLoad_v2::saveNotes(int16 dataVar, int32 size, int32 offset) {
- bool retVal;
+bool SaveLoad_v2::saveTempSprite(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
- if ((size <= 0) || (offset != 0)) {
- warning("Invalid attempt at saving the notes (%d, %d)", size, offset);
- return false;
- }
+ debugC(3, kDebugSaveLoad, "Saving to the temporary sprite");
- Common::SaveFileManager *saveMan = g_system->getSavefileManager();
- char *sName = _saveFiles[(int) kSaveNotes];
+ int index;
+ bool palette;
- Common::OutSaveFile *out = saveMan->openForSaving(sName);
- if (!out) {
- warning("Can't open file \"%s\" for writing", sName);
+ if (!_tmpSprite.getProperties(dataVar, size, offset, index, palette))
return false;
- }
- retVal = saveDataEndian(*out, dataVar, size);
+ if (!_tmpSprite.saveSprite(*_vm->_draw->_spritesArray[index]))
+ return false;
- out->finalize();
- if (out->ioFailed()) {
- warning("Can't save notes");
- retVal = false;
- }
+ if (palette)
+ if (!_tmpSprite.savePalette(_vm->_global->_pPaletteDesc->vgaPal))
+ return false;
- delete out;
- return retVal;
+ return true;
}
-bool SaveLoad_v2::saveScreenshot(int16 dataVar, int32 size, int32 offset) {
+bool SaveLoad_v2::saveNotes(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
+
+ debugC(2, kDebugSaveLoad, "Saving the notes");
+
+ return _notes.save(dataVar, size, offset, saveFile.destName,
+ _vm->_global->_inter_variables, _vm->_global->_inter_variablesSizes);
return false;
}
-void SaveLoad_v2::initBuffer() {
- if (_buffer)
+void SaveLoad_v2::assertInited() {
+ if (_varSize > 0)
return;
- _buffer = new byte*[_stagesCount];
- assert(_buffer);
- _buffer[0] = 0;
+ _varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
+
+ _save.addStage(40);
+ _save.addStage(_varSize);
}
} // End of namespace Gob
diff --git a/engines/gob/saveload_v3.cpp b/engines/gob/saveload_v3.cpp
index 4a4036fded..ae8d160eb2 100644
--- a/engines/gob/saveload_v3.cpp
+++ b/engines/gob/saveload_v3.cpp
@@ -24,62 +24,178 @@
*/
#include "common/endian.h"
-#include "common/file.h"
+#include "common/savefile.h"
#include "gob/gob.h"
#include "gob/saveload.h"
#include "gob/global.h"
#include "gob/game.h"
+#include "gob/draw.h"
namespace Gob {
+SaveLoad_v3::SaveFile SaveLoad_v3::_saveFiles[] = {
+ { "cat.inf", 0, kSaveModeSave, kSaveGame, -1},
+ { "ima.inf", 0, kSaveModeSave, kSaveScreenshot, -1},
+ { "intro.$$$", 0, kSaveModeSave, kSaveTempSprite, -1},
+ { "bloc.inf", 0, kSaveModeSave, kSaveNotes, -1},
+ { "prot", 0, kSaveModeIgnore, kSaveNone, -1},
+ { "config", 0, kSaveModeIgnore, kSaveNone, -1},
+};
+
SaveLoad_v3::SaveLoad_v3(GobEngine *vm, const char *targetName,
uint32 screenshotSize, int32 indexOffset, int32 screenshotOffset) :
- SaveLoad_v2(vm, targetName) {
+ SaveLoad(vm, targetName) {
_screenshotSize = screenshotSize;
_indexOffset = indexOffset;
_screenshotOffset = screenshotOffset;
- _saveSlot = -1;
- _stagesCount = 3;
-
_useScreenshots = false;
_firstSizeGame = true;
+
+ _saveFiles[0].destName = new char[strlen(targetName) + 5];
+ _saveFiles[1].destName = _saveFiles[0].destName;
+ _saveFiles[2].destName = 0;
+ _saveFiles[3].destName = new char[strlen(targetName) + 5];
+ _saveFiles[4].destName = 0;
+ _saveFiles[5].destName = 0;
+
+ sprintf(_saveFiles[0].destName, "%s.s00", targetName);
+ sprintf(_saveFiles[3].destName, "%s.blo", targetName);
+
+ _varSize = 0;
+ _hasIndex = false;
+ memset(_propBuffer, 0, 1000);
}
-SaveType SaveLoad_v3::getSaveType(const char *fileName) {
- const char *backSlash;
- if ((backSlash = strrchr(fileName, '\\')))
- fileName = backSlash + 1;
-
- if (!scumm_stricmp(fileName, "cat.inf"))
- return kSaveGame;
- if (!scumm_stricmp(fileName, "ima.inf"))
- return kSaveScreenshot;
- if (!scumm_stricmp(fileName, "intro.$$$"))
- return kSaveTempSprite;
- if (!scumm_stricmp(fileName, "bloc.inf"))
- return kSaveNotes;
- if (!scumm_stricmp(fileName, "prot"))
- return kSaveIgnore;
- if (!scumm_stricmp(fileName, "config"))
- return kSaveIgnore;
-
- return kSaveNone;
+SaveLoad_v3::~SaveLoad_v3() {
+ delete[] _saveFiles[0].destName;
+ delete[] _saveFiles[3].destName;
}
-uint32 SaveLoad_v3::getSaveGameSize() {
- uint32 size;
+SaveLoad::SaveMode SaveLoad_v3::getSaveMode(const char *fileName) {
+ for (int i = 0; i < ARRAYSIZE(_saveFiles); i++)
+ if (!scumm_stricmp(fileName, _saveFiles[i].sourceName))
+ return _saveFiles[i].mode;
- size = 1040 + (READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4) * 2;
- if (_useScreenshots)
- size += _screenshotSize;
+ return kSaveModeNone;
+}
- return size;
+int SaveLoad_v3::getSaveType(const char *fileName) {
+ for (int i = 0; i < ARRAYSIZE(_saveFiles); i++)
+ if (!scumm_stricmp(fileName, _saveFiles[i].sourceName))
+ return i;
+
+ return -1;
+}
+
+int32 SaveLoad_v3::getSizeVersioned(int type) {
+ assertInited();
+
+ switch (_saveFiles[type].type) {
+ case kSaveGame:
+ return getSizeGame(_saveFiles[type]);
+ case kSaveTempSprite:
+ return getSizeTempSprite(_saveFiles[type]);
+ case kSaveNotes:
+ return getSizeNotes(_saveFiles[type]);
+ case kSaveScreenshot:
+ return getSizeScreenshot(_saveFiles[type]);
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+bool SaveLoad_v3::loadVersioned(int type, int16 dataVar, int32 size, int32 offset) {
+ assertInited();
+
+ switch (_saveFiles[type].type) {
+ case kSaveGame:
+ if (loadGame(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While loading from slot %d", getSlot(offset));
+ break;
+
+ case kSaveTempSprite:
+ if(loadTempSprite(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While loading the temporary sprite");
+ break;
+
+ case kSaveNotes:
+ if (loadNotes(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While loading the notes");
+ break;
+
+ case kSaveScreenshot:
+ if (loadScreenshot(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While loading a screenshot");
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+bool SaveLoad_v3::saveVersioned(int type, int16 dataVar, int32 size, int32 offset) {
+ assertInited();
+
+ switch (_saveFiles[type].type) {
+ case kSaveGame:
+ if (saveGame(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While saving to slot %d", getSlot(offset));
+ break;
+
+ case kSaveTempSprite:
+ if(saveTempSprite(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While saving the temporary sprite");
+ break;
+
+ case kSaveNotes:
+ if (saveNotes(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While saving the notes");
+ break;
+
+ case kSaveScreenshot:
+ if (saveScreenshot(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While saving a screenshot");
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+int SaveLoad_v3::getSlot(int32 offset) const {
+ return ((offset - 1700) / _varSize);
}
-int32 SaveLoad_v3::getSizeGame() {
+int SaveLoad_v3::getSlotRemainder(int32 offset) const {
+ return ((offset - 1700) % _varSize);
+}
+
+int32 SaveLoad_v3::getSizeGame(SaveFile &saveFile) {
if (_firstSizeGame) {
_firstSizeGame = false;
return -1;
@@ -89,358 +205,413 @@ int32 SaveLoad_v3::getSizeGame() {
Common::InSaveFile *in;
int32 size = -1;
- int slot = _curSlot;
+ int slot = saveFile.slot;
for (int i = 29; i >= 0; i--) {
- in = saveMan->openForLoading(setCurSlot(i));
+ in = saveMan->openForLoading(setCurrentSlot(saveFile.destName, i));
if (in) {
delete in;
- size = (i + 1) * READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) *
- 4 + 1700;
+ size = (i + 1) * _varSize + 1700;
break;
}
}
- setCurSlot(slot);
+ setCurrentSlot(saveFile.destName, slot);
return size;
}
-int32 SaveLoad_v3::getSizeScreenshot() {
+int32 SaveLoad_v3::getSizeTempSprite(SaveFile &saveFile) {
+ return _tmpSprite.getSize();
+}
+
+int32 SaveLoad_v3::getSizeNotes(SaveFile &saveFile) {
Common::SaveFileManager *saveMan = g_system->getSavefileManager();
Common::InSaveFile *in;
int32 size = -1;
- _useScreenshots = true;
- int slot = _curSlot;
+ in = saveMan->openForLoading(saveFile.destName);
+ if (in) {
+ size = in->size();
+ delete in;
+ }
+
+ return size;
+}
+
+int32 SaveLoad_v3::getSizeScreenshot(SaveFile &saveFile) {
+ if (!_useScreenshots) {
+ _useScreenshots = true;
+ _save.addStage(_screenshotSize, false);
+ }
+
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ Common::InSaveFile *in;
+ int32 size = -1;
+
+ int slot = saveFile.slot;
for (int i = 29; i >= 0; i--) {
- in = saveMan->openForLoading(setCurSlot(i));
+ in = saveMan->openForLoading(setCurrentSlot(saveFile.destName, i));
if (in) {
delete in;
size = (i + 1) * _screenshotSize + _screenshotOffset;
break;
}
}
- setCurSlot(slot);
+ setCurrentSlot(saveFile.destName, slot);
return size;
}
-bool SaveLoad_v3::loadGame(int16 dataVar, int32 size, int32 offset) {
- int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
- Common::SaveFileManager *saveMan = g_system->getSavefileManager();
- Common::InSaveFile *in;
+bool SaveLoad_v3::loadGame(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
- int slot = (offset - 1700) / varSize;
- int slotR = (offset - 1700) % varSize;
+ if (size == 0) {
+ dataVar = 0;
+ size = _varSize;
+ }
- initBuffer();
+ if (offset < 500) {
+ debugC(3, kDebugSaveLoad, "Loading global properties");
- if ((size > 0) && (offset < 500) && ((size + offset) <= 500)) {
+ if ((size + offset) > 500) {
+ warning("Wrong global properties list size (%d, %d)", size, offset);
+ return false;
+ }
memcpy(_vm->_global->_inter_variables + dataVar,
- _buffer[0] + offset, size);
+ _propBuffer + offset, size);
memcpy(_vm->_global->_inter_variablesSizes + dataVar,
- _buffer[0] + offset + 500, size);
- return true;
+ _propBuffer + offset + 500, size);
- } else if ((size == 1200) && (offset == 500)) {
+ } else if (offset == 500) {
+ debugC(3, kDebugSaveLoad, "Loading save index");
- memset(_buffer[1], 0, 1200);
-
- slot = _curSlot;
- for (int i = 0; i < 30; i++) {
- in = saveMan->openForLoading(setCurSlot(i));
- if (in) {
- in->seek(1000);
- in->read(_buffer[1] + i * 40, 40);
- delete in;
- }
+ if (size != 1200) {
+ warning("Requested index has wrong size (%d)", size);
+ return false;
}
- setCurSlot(slot);
- memcpy(_vm->_global->_inter_variables + dataVar, _buffer[1], 1200);
+ int slot = saveFile.slot;
+
+ SaveLoad::buildIndex(_vm->_global->_inter_variables + dataVar,
+ saveFile.destName, 30, 40, 1000);
memset(_vm->_global->_inter_variablesSizes + dataVar, 0, 1200);
- return true;
- } else if ((offset > 0) && (slot < 30) &&
- (slotR == 0) && (size == 0)) {
+ setCurrentSlot(saveFile.destName, slot);
+
+ } else {
+ saveFile.slot = getSlot(offset);
+ int slotRem = getSlotRemainder(offset);
- in = saveMan->openForLoading(setCurSlot(slot));
- if (!in) {
- warning("Can't open file for slot %d", slot);
+ debugC(2, kDebugSaveLoad, "Loading from slot %d", saveFile.slot);
+
+ SaveLoad::setCurrentSlot(saveFile.destName, saveFile.slot);
+
+ if ((saveFile.slot < 0) || (saveFile.slot >= 30) || (slotRem != 0)) {
+ warning("Invalid loading procedure (%d, %d, %d, %d, %d)",
+ dataVar, size, offset, saveFile.slot, slotRem);
return false;
}
- uint32 sGameSize = getSaveGameSize();
- uint32 fSize = in->size();
- if (fSize != sGameSize) {
- warning("Can't load from slot %d: Wrong size (%d, %d)", slot,
- fSize, sGameSize);
- delete in;
+ if (!_save.load(dataVar, size, 540, saveFile.destName,
+ _vm->_global->_inter_variables, _vm->_global->_inter_variablesSizes))
return false;
- }
+ }
- byte varBuf[500], sizeBuf[500];
- if (read(*in, varBuf, sizeBuf, 500) == 500) {
- if (fromEndian(varBuf, sizeBuf, 500)) {
- memcpy(_buffer[0], varBuf, 500);
- memcpy(_buffer[0] + 500, sizeBuf, 500);
- in->seek(1040);
- if (loadDataEndian(*in, 0, varSize)) {
- delete in;
- debugC(1, kDebugFileIO, "Loading from slot %d", slot);
- return true;
- }
- }
- }
- delete in;
+ return true;
+}
- } else
- warning("Invalid loading procedure (%d, %d, %d, %d)",
- offset, size, slot, slotR);
+bool SaveLoad_v3::loadTempSprite(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
- return false;
+ debugC(3, kDebugSaveLoad, "Loading from the temporary sprite");
+
+ int index;
+ bool palette;
+
+ if (!_tmpSprite.getProperties(dataVar, size, offset, index, palette))
+ return false;
+
+ if (!_tmpSprite.loadSprite(*_vm->_draw->_spritesArray[index]))
+ return false;
+
+ if (palette) {
+ if (!_tmpSprite.loadPalette(_vm->_global->_pPaletteDesc->vgaPal))
+ return false;
+
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+ }
+
+ if (index == 21) {
+ _vm->_draw->forceBlit();
+ _vm->_video->retrace();
+ }
+
+ return true;
}
-bool SaveLoad_v3::loadScreenshot(int16 dataVar, int32 size, int32 offset) {
- Common::SaveFileManager *saveMan = g_system->getSavefileManager();
- Common::InSaveFile *in;
+bool SaveLoad_v3::loadNotes(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
- int slot = (offset - _screenshotOffset) / _screenshotSize;
- int slotR = (offset - _screenshotOffset) % _screenshotSize;
+ debugC(2, kDebugSaveLoad, "Loading the notes");
- _useScreenshots = true;
- if ((size == 40) && (offset == _indexOffset)) {
- char buf[40];
+ return _notes.load(dataVar, size, offset, saveFile.destName,
+ _vm->_global->_inter_variables, _vm->_global->_inter_variablesSizes);
+}
- memset(buf, 0, 40);
+bool SaveLoad_v3::loadScreenshot(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
- slot = _curSlot;
- for (int i = 0; i < 30; i++) {
- in = saveMan->openForLoading(setCurSlot(i));
- if (in) {
- delete in;
- buf[i] = 1;
- }
+ debugC(3, kDebugSaveLoad, "Loading a screenshot");
+
+ if (!_useScreenshots) {
+ _useScreenshots = true;
+ _save.addStage(_screenshotSize, false);
+ }
+
+ if (offset == _indexOffset) {
+ if (size != 40) {
+ warning("Requested index has wrong size (%d)", size);
+ return false;
}
- setCurSlot(slot);
- memcpy(_vm->_global->_inter_variables + dataVar, buf, 40);
+ byte buffer[40];
+ memset(buffer, 0, 40);
+
+ int slot = saveFile.slot;
+ buildScreenshotIndex(buffer, saveFile.destName, 30);
+ setCurrentSlot(saveFile.destName, slot);
+
+ memcpy(_vm->_global->_inter_variables + dataVar, buffer, 40);
memset(_vm->_global->_inter_variablesSizes + dataVar, 0, 40);
- return true;
- } else if ((offset > 0) && (slot < 30) &&
- (slotR == 0) && (size < 0)) {
+ } else {
+ saveFile.slot = (offset - _screenshotOffset) / _screenshotSize;
+ int slotRem = (offset - _screenshotOffset) % _screenshotSize;
- int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
+ SaveLoad::setCurrentSlot(saveFile.destName, saveFile.slot);
- in = saveMan->openForLoading(setCurSlot(slot));
- if (!in) {
- warning("Can't open file for slot %d", slot);
+ if ((saveFile.slot < 0) || (saveFile.slot >= 30) || (slotRem != 0)) {
+ warning("Invalid loading procedure (%d, %d, %d, %d, %d)",
+ dataVar, size, offset, saveFile.slot, slotRem);
return false;
}
- uint32 sGameSize = getSaveGameSize();
- uint32 fSize = in->size();
- if (fSize != sGameSize) {
- warning("Can't load screenshot from slot %d: Wrong size (%d, %d)",
- slot, fSize, sGameSize);
- delete in;
+ byte *buffer = new byte[_screenshotSize];
+
+ if (!_save.load(0, _screenshotSize, _varSize + 540, saveFile.destName, buffer, 0)) {
+ delete[] buffer;
return false;
}
- in->seek(1040 + varSize * 2);
+ int index;
+ bool palette;
- bool success = loadSprite(*in, size);
- delete in;
- return success;
+ if (!_screenshot.getProperties(dataVar, size, offset, index, palette)) {
+ delete[] buffer;
+ return false;
+ }
- } else
- warning("Invalid attempt at loading a screenshot (%d, %d, %d, %d)",
- offset, size, slot, slotR);
+ if (!_screenshot.fromBuffer(buffer, _screenshotSize, palette)) {
+ delete[] buffer;
+ return false;
+ }
- return false;
+ if (!_screenshot.loadSprite(*_vm->_draw->_spritesArray[index])) {
+ delete[] buffer;
+ return false;
+ }
+
+ if (palette) {
+ if (!_screenshot.loadPalette(_vm->_global->_pPaletteDesc->vgaPal)) {
+ delete[] buffer;
+ return false;
+ }
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+ }
+
+ delete[] buffer;
+ }
+
+ return true;
}
-bool SaveLoad_v3::saveGame(int16 dataVar, int32 size, int32 offset) {
- int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
+bool SaveLoad_v3::saveGame(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
- int slot = (offset - 1700) / varSize;
- int slotR = (offset - 1700) % varSize;
+ if (size == 0) {
+ dataVar = 0;
+ size = _varSize;
+ }
- initBuffer();
+ if (offset < 500) {
+ debugC(3, kDebugSaveLoad, "Loading global properties");
- if ((size > 0) && (offset < 500) && ((size + offset) <= 500)) {
+ if ((size + offset) > 500) {
+ warning("Wrong global properties list size (%d, %d)", size, offset);
+ return false;
+ }
- memcpy(_buffer[0] + offset,
+ memcpy(_propBuffer + offset,
_vm->_global->_inter_variables + dataVar, size);
- memcpy(_buffer[0] + offset + 500,
+ memcpy(_propBuffer + offset + 500,
_vm->_global->_inter_variablesSizes + dataVar, size);
- return true;
-
- } else if ((size > 0) && (offset >= 500) && (offset < 1700) &&
- ((size + offset) <= 1700)) {
+ } else if (offset == 500) {
+ debugC(3, kDebugSaveLoad, "Saving save index");
- memcpy(_buffer[1] + offset - 500,
- _vm->_global->_inter_variables + dataVar, size);
+ if (size != 1200) {
+ warning("Requested index has wrong size (%d)", size);
+ return false;
+ }
- return true;
+ memcpy(_indexBuffer, _vm->_global->_inter_variables + dataVar, size);
+ _hasIndex = true;
- } else if ((offset > 0) && (slot < 30) &&
- (slotR == 0) && (size == 0)) {
+ } else {
+ saveFile.slot = getSlot(offset);
+ int slotRem = getSlotRemainder(offset);
- _saveSlot = -1;
+ debugC(2, kDebugSaveLoad, "Saving to slot %d", saveFile.slot);
- delete _buffer[2];
- _buffer[2] = new byte[varSize * 2];
- assert(_buffer[2]);
+ SaveLoad::setCurrentSlot(saveFile.destName, saveFile.slot);
- memcpy(_buffer[2], _vm->_global->_inter_variables, varSize);
- memcpy(_buffer[2] + varSize,
- _vm->_global->_inter_variablesSizes, varSize);
+ if ((saveFile.slot < 0) || (saveFile.slot >= 30) || (slotRem != 0)) {
+ warning("Invalid saving procedure (%d, %d, %d, %d, %d)",
+ dataVar, size, offset, saveFile.slot, slotRem);
+ return false;
+ }
- if (!toEndian(_buffer[2], _buffer[2] + varSize, varSize)) {
- delete _buffer[2];
- _buffer[2] = 0;
+ if (!_hasIndex) {
+ warning("No index written yet");
return false;
}
- _saveSlot = slot;
+ _hasIndex = false;
- if (!_useScreenshots)
- return saveGame(0);
+ if(!_save.save(0, 500, 0, saveFile.destName, _propBuffer, _propBuffer + 500))
+ return false;
- return true;
+ if(!_save.save(0, 40, 500, saveFile.destName, _indexBuffer + (saveFile.slot * 40), 0))
+ return false;
- } else
- warning("Invalid saving procedure (%d, %d, %d, %d)",
- offset, size, slot, slotR);
+ if (!_save.save(dataVar, size, 540, saveFile.destName,
+ _vm->_global->_inter_variables, _vm->_global->_inter_variablesSizes))
+ return false;
- return false;
-}
+ }
-bool SaveLoad_v3::saveNotes(int16 dataVar, int32 size, int32 offset) {
- return SaveLoad_v2::saveNotes(dataVar, size - 160, offset);
+ return true;
}
-bool SaveLoad_v3::saveScreenshot(int16 dataVar, int32 size, int32 offset) {
- int slot = (offset - _screenshotOffset) / _screenshotSize;
- int slotR = (offset - _screenshotOffset) % _screenshotSize;
+bool SaveLoad_v3::saveTempSprite(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
- _useScreenshots = true;
+ debugC(3, kDebugSaveLoad, "Saving to the temporary sprite");
- if ((offset < _screenshotOffset) && (size > 0)) {
+ int index;
+ bool palette;
- return true;
+ if (!_tmpSprite.getProperties(dataVar, size, offset, index, palette))
+ return false;
- } else if ((offset > 0) && (slot < 30) &&
- (slotR == 0) && (size < 0)) {
+ if (!_tmpSprite.saveSprite(*_vm->_draw->_spritesArray[index]))
+ return false;
+
+ if (palette)
+ if (!_tmpSprite.savePalette(_vm->_global->_pPaletteDesc->vgaPal))
+ return false;
+
+ return true;
+}
- return saveGame(size);
+bool SaveLoad_v3::saveNotes(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
- } else
- warning("Invalid attempt at saving a screenshot (%d, %d, %d, %d)",
- offset, size, slot, slotR);
+ debugC(2, kDebugSaveLoad, "Saving the notes");
+ return _notes.save(dataVar, size - 160, offset, saveFile.destName,
+ _vm->_global->_inter_variables, _vm->_global->_inter_variablesSizes);
return false;
}
-bool SaveLoad_v3::saveGame(int32 screenshotSize) {
- int8 slot = _saveSlot;
-
- _saveSlot = -1;
+bool SaveLoad_v3::saveScreenshot(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
- initBuffer();
+ debugC(3, kDebugSaveLoad, "Saving a screenshot");
- if ((slot < 0) || (slot > 29)) {
- warning("Can't save to slot %d: Out of range", slot);
- delete[] _buffer[2];
- _buffer[2] = 0;
- return false;
+ if (!_useScreenshots) {
+ _useScreenshots = true;
+ _save.addStage(_screenshotSize, false);
}
- if (!_buffer[2]) {
- warning("Can't save to slot %d: No data", slot);
- return false;
- }
+ if (offset >= _screenshotOffset) {
- Common::SaveFileManager *saveMan = g_system->getSavefileManager();
- Common::OutSaveFile *out;
+ saveFile.slot = (offset - _screenshotOffset) / _screenshotSize;
+ int slotRem = (offset - _screenshotOffset) % _screenshotSize;
- out = saveMan->openForSaving(setCurSlot(slot));
- if (!out) {
- warning("Can't open file for slot %d for writing", slot);
- delete[] _buffer[2];
- _buffer[2] = 0;
- return false;
- }
+ setCurrentSlot(saveFile.destName, saveFile.slot);
+
+ if ((saveFile.slot < 0) || (saveFile.slot >= 30) || (slotRem != 0)) {
+ warning("Invalid saving procedure (%d, %d, %d, %d, %d)",
+ dataVar, size, offset, saveFile.slot, slotRem);
+ return false;
+ }
- int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
- byte varBuf[500], sizeBuf[500];
+ int index;
+ bool palette;
- memcpy(varBuf, _buffer[0], 500);
- memcpy(sizeBuf, _buffer[0] + 500, 500);
+ if (!_screenshot.getProperties(dataVar, size, offset, index, palette))
+ return false;
- bool retVal = false;
- if (toEndian(varBuf, sizeBuf, 500))
- if (write(*out, varBuf, sizeBuf, 500) == 500)
- if (out->write(_buffer[1] + slot * 40, 40) == 40)
- if (out->write(_buffer[2], varSize * 2) == ((uint32) (varSize * 2))) {
- out->flush();
- if (!out->ioFailed())
- retVal = true;
- }
+ if (!_screenshot.saveSprite(*_vm->_draw->_spritesArray[index]))
+ return false;
- delete[] _buffer[2];
- _buffer[2] = 0;
+ if (palette)
+ if (!_screenshot.savePalette(_vm->_global->_pPaletteDesc->vgaPal))
+ return false;
- if (!retVal) {
- warning("Can't save to slot %d", slot);
- delete out;
- return false;
- }
+
+ byte *buffer = new byte[_screenshotSize];
- if (_useScreenshots) {
- if (screenshotSize >= 0) {
- warning("Can't save to slot %d: Screenshot expected", slot);
- delete out;
+ if (!_screenshot.toBuffer(buffer, _screenshotSize, palette)) {
+ delete[] buffer;
return false;
}
- if (!saveSprite(*out, screenshotSize)) {
- delete out;
+ if (!_save.save(0, _screenshotSize, _varSize + 540, saveFile.destName, buffer, 0)) {
+ delete[] buffer;
return false;
}
- }
- out->finalize();
- if (out->ioFailed()) {
- warning("Can't save to slot %d", slot);
- delete out;
- return false;
+ delete[] buffer;
}
- debugC(1, kDebugFileIO, "Saved to slot %d", slot);
- delete out;
return true;
}
-void SaveLoad_v3::initBuffer() {
- if (_buffer)
+void SaveLoad_v3::assertInited() {
+ if (_varSize > 0)
return;
- _buffer = new byte*[_stagesCount];
-
- assert(_buffer);
+ _varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
- _buffer[0] = new byte[1000];
- _buffer[1] = new byte[1200];
- _buffer[2] = 0;
+ _save.addStage(500);
+ _save.addStage(40, false);
+ _save.addStage(_varSize);
+}
- assert(_buffer[0] && _buffer[1]);
+void SaveLoad_v3::buildScreenshotIndex(byte *buffer, char *name, int n) {
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ Common::InSaveFile *in;
- memset(_buffer[0], 0, 1000);
- memset(_buffer[1], 0, 1200);
+ memset(buffer, 0, n);
+ for (int i = 0; i < n; i++) {
+ in = saveMan->openForLoading(setCurrentSlot(name, i));
+ if (in) {
+ delete in;
+ buffer[i] = 1;
+ }
+ }
}
} // End of namespace Gob
diff --git a/engines/gob/saveload_v4.cpp b/engines/gob/saveload_v4.cpp
new file mode 100644
index 0000000000..2235b4834e
--- /dev/null
+++ b/engines/gob/saveload_v4.cpp
@@ -0,0 +1,80 @@
+/* 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/saveload.h"
+#include "gob/game.h"
+
+namespace Gob {
+
+SaveLoad_v4::SaveFile SaveLoad_v4::_saveFiles[] = {
+ { "", 0, kSaveModeNone, kSaveNone }
+};
+
+SaveLoad_v4::SaveLoad_v4(GobEngine *vm, const char *targetName) :
+ SaveLoad(vm, targetName) {
+
+ _varSize = 0;
+}
+
+SaveLoad_v4::~SaveLoad_v4() {
+}
+
+SaveLoad::SaveMode SaveLoad_v4::getSaveMode(const char *fileName) {
+ return kSaveModeNone;
+}
+
+int SaveLoad_v4::getSaveType(const char *fileName) {
+ return -1;
+}
+
+int32 SaveLoad_v4::getSizeVersioned(int type) {
+ assertInited();
+
+ return -1;
+}
+
+bool SaveLoad_v4::loadVersioned(int type, int16 dataVar, int32 size, int32 offset) {
+ assertInited();
+
+ return false;
+}
+
+bool SaveLoad_v4::saveVersioned(int type, int16 dataVar, int32 size, int32 offset) {
+ assertInited();
+
+ return false;
+}
+
+void SaveLoad_v4::assertInited() {
+ if (_varSize > 0)
+ return;
+
+ _varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/video.h b/engines/gob/video.h
index 4a585d8857..1ab513205b 100644
--- a/engines/gob/video.h
+++ b/engines/gob/video.h
@@ -37,10 +37,11 @@ class SurfaceDesc : public ReferenceCounter<SurfaceDesc> {
public:
int16 _vidMode;
- int16 getWidth() { return _width; }
- int16 getHeight() { return _height; }
+ int16 getWidth() const { return _width; }
+ int16 getHeight() const { return _height; }
byte *getVidMem() { return _vidMem; }
- bool hasOwnVidMem() { return _ownVidMem; }
+ const byte *getVidMem() const { return _vidMem; }
+ bool hasOwnVidMem() const { return _ownVidMem; }
void setVidMem(byte *vidMem);
void resize(int16 width, int16 height);