diff options
author | Sven Hesse | 2008-05-10 20:59:43 +0000 |
---|---|---|
committer | Sven Hesse | 2008-05-10 20:59:43 +0000 |
commit | 257aaa3ced14645d4410a272e89cafb7282836ac (patch) | |
tree | bfe6be04b32b7d40d3096fa2e14f49625a7f8b25 /engines | |
parent | b2defd0eac9401ffeea91ef0154650e108ffc179 (diff) | |
download | scummvm-rg350-257aaa3ced14645d4410a272e89cafb7282836ac.tar.gz scummvm-rg350-257aaa3ced14645d4410a272e89cafb7282836ac.tar.bz2 scummvm-rg350-257aaa3ced14645d4410a272e89cafb7282836ac.zip |
Restructured saving/loading and added a stub for Woodruff
svn-id: r31989
Diffstat (limited to 'engines')
-rw-r--r-- | engines/gob/gob.cpp | 3 | ||||
-rw-r--r-- | engines/gob/gob.h | 5 | ||||
-rw-r--r-- | engines/gob/inter_v2.cpp | 31 | ||||
-rw-r--r-- | engines/gob/module.mk | 1 | ||||
-rw-r--r-- | engines/gob/saveload.cpp | 724 | ||||
-rw-r--r-- | engines/gob/saveload.h | 364 | ||||
-rw-r--r-- | engines/gob/saveload_v2.cpp | 403 | ||||
-rw-r--r-- | engines/gob/saveload_v3.cpp | 677 | ||||
-rw-r--r-- | engines/gob/saveload_v4.cpp | 80 | ||||
-rw-r--r-- | engines/gob/video.h | 7 |
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 ¶ms) { 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 ¶ms) { 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 ¶ms) { 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 ¶ms) { 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 ¶ms) { 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 ¶ms) { 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 ¶ms) { 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); |