diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/gob/save/savehandler.cpp | 2 | ||||
-rw-r--r-- | engines/gob/save/saveload.h | 79 | ||||
-rw-r--r-- | engines/gob/save/saveload_inca2.cpp | 328 |
3 files changed, 407 insertions, 2 deletions
diff --git a/engines/gob/save/savehandler.cpp b/engines/gob/save/savehandler.cpp index 8b7a661278..d447b0dbd6 100644 --- a/engines/gob/save/savehandler.cpp +++ b/engines/gob/save/savehandler.cpp @@ -340,6 +340,8 @@ bool TempSpriteHandler::isSprite(int32 size) { // Contruct the index int TempSpriteHandler::getIndex(int32 size) { // Palette flag + if (size < -3000) + size += 3000; if (size < -1000) size += 1000; diff --git a/engines/gob/save/saveload.h b/engines/gob/save/saveload.h index dd99bf466b..89beafd9fc 100644 --- a/engines/gob/save/saveload.h +++ b/engines/gob/save/saveload.h @@ -337,6 +337,9 @@ protected: /** Save/Load class for Inca 2. */ class SaveLoad_Inca2 : public SaveLoad { public: + static const uint32 kSlotCount = 40; + static const uint32 kPropsSize = 500; + SaveLoad_Inca2(GobEngine *vm, const char *targetName); virtual ~SaveLoad_Inca2(); @@ -361,10 +364,84 @@ protected: bool save(int16 dataVar, int32 size, int32 offset); }; + class ScreenshotHandler; + + /** Handles the save slots. */ + class GameHandler : public SaveHandler { + friend class SaveLoad_Inca2::ScreenshotHandler; + public: + + GameHandler(GobEngine *vm, const char *target); + ~GameHandler(); + + int32 getSize(); + bool load(int16 dataVar, int32 size, int32 offset); + bool save(int16 dataVar, int32 size, int32 offset); + + bool saveScreenshot(int slot, const SavePartSprite *screenshot); + bool loadScreenshot(int slot, SavePartSprite *screenshot); + + /** Slot file construction. */ + class File : public SlotFileIndexed { + public: + File(GobEngine *vm, const char *base); + File(const File &file); + ~File(); + + int getSlot(int32 offset) const; + int getSlotRemainder(int32 offset) const; + }; + + private: + + File *_slotFile; + + byte _props[kPropsSize]; + + SaveReader *_reader; + SaveWriter *_writer; + + void buildIndex(); + + bool createReader(int slot); + bool createWriter(int slot); + }; + + /** Handles the screenshots. */ + class ScreenshotHandler : public TempSpriteHandler { + public: + ScreenshotHandler(GobEngine *vm, GameHandler *gameHandler); + ~ScreenshotHandler(); + + int32 getSize(); + bool load(int16 dataVar, int32 size, int32 offset); + bool save(int16 dataVar, int32 size, int32 offset); + + private: + /** Slot file construction. */ + class File : public SaveLoad_Inca2::GameHandler::File { + public: + File(const SaveLoad_Inca2::GameHandler::File &file); + ~File(); + + int getSlot(int32 offset) const; + int getSlotRemainder(int32 offset) const; + + void buildIndex(byte *buffer) const; + }; + + File *_file; + GameHandler *_gameHandler; + + byte _index[80]; + }; + static SaveFile _saveFiles[]; - VoiceHandler *_voiceHandler; + VoiceHandler *_voiceHandler; TempSpriteHandler *_tempSpriteHandler; + GameHandler *_gameHandler; + ScreenshotHandler *_screenshotHandler; SaveHandler *getHandler(const char *fileName) const; const char *getDescription(const char *fileName) const; diff --git a/engines/gob/save/saveload_inca2.cpp b/engines/gob/save/saveload_inca2.cpp index 4577440ec8..e32c4fd25c 100644 --- a/engines/gob/save/saveload_inca2.cpp +++ b/engines/gob/save/saveload_inca2.cpp @@ -39,6 +39,328 @@ SaveLoad_Inca2::SaveFile SaveLoad_Inca2::_saveFiles[] = { }; +SaveLoad_Inca2::GameHandler::File::File(GobEngine *vm, const char *base) : + SlotFileIndexed(vm, SaveLoad_Inca2::kSlotCount, base, "s") { +} + +SaveLoad_Inca2::GameHandler::File::File(const File &file) : + SlotFileIndexed(file._vm, file._slotCount, file._base, file._ext) { +} + +SaveLoad_Inca2::GameHandler::File::~File() { +} + +int SaveLoad_Inca2::GameHandler::File::getSlot(int32 offset) const { + uint32 varSize = SaveHandler::getVarSize(_vm); + + if (varSize == 0) + return -1; + + return offset - kPropsSize; +} + +int SaveLoad_Inca2::GameHandler::File::getSlotRemainder(int32 offset) const { + return 0; +} + + +SaveLoad_Inca2::GameHandler::GameHandler(GobEngine *vm, const char *target) : + SaveHandler(vm) { + + _slotFile = new File(vm, target); + + memset(_props, 0x00, kPropsSize); + memset(_props, 0x20, 10); + + _props[43] = 0x01; + _props[79] = 0x03; + + buildIndex(); + + _writer = 0; + _reader = 0; +} + +SaveLoad_Inca2::GameHandler::~GameHandler() { + delete _slotFile; + delete _reader; + delete _writer; +} + +int32 SaveLoad_Inca2::GameHandler::getSize() { + return _slotFile->tallyUpFiles(1, kPropsSize); +} + +bool SaveLoad_Inca2::GameHandler::load(int16 dataVar, int32 size, int32 offset) { + if (((uint32) offset) < kPropsSize) { + // Global properties, like joker usage + + debugC(3, kDebugSaveLoad, "Loading global properties"); + + if (((uint32) (offset + size)) > kPropsSize) { + warning("Wrong global properties list size (%d, %d)", size, offset); + return false; + } + + if (((uint32) (offset + size)) >= kPropsSize) + buildIndex(); + + _vm->_inter->_variables->copyFrom(dataVar, _props + offset, size); + + } else { + int32 slot = offset - kPropsSize; + + if ((size != 1) || (slot < 0) || ((uint32)slot >= kSlotCount)) { + warning("Invalid loading procedure (%d, %d, %d)", dataVar, size, offset); + return false; + } + + WRITE_VARO_UINT8(dataVar, 0); + if (!createReader(slot)) + return true; + + SavePartInfo info(0, (uint32) _vm->getGameType(), 0, _vm->getEndianness(), 1); + SavePartVars vars(_vm, 1); + + if (!_reader->readPart(0, &info)) + return true; + if (!_reader->readPart(1, &vars)) + return true; + + // Read the save point number + if (!vars.writeInto(dataVar, 0, 1)) { + WRITE_VARO_UINT8(dataVar, 0); + return true; + } + } + + return true; +} + +bool SaveLoad_Inca2::GameHandler::save(int16 dataVar, int32 size, int32 offset) { + if (((uint32) offset) < kPropsSize) { + // Global properties, like joker usage + + debugC(3, kDebugSaveLoad, "Saving global properties"); + + if (((uint32) (offset + size)) > kPropsSize) { + warning("Wrong global properties list size (%d, %d)", size, offset); + return false; + } + + _vm->_inter->_variables->copyTo(dataVar, _props + offset, size); + + } else { + // Save point flag + + int32 slot = offset - kPropsSize; + + if ((size != 1) || (slot < 0) || ((uint32)slot >= kSlotCount)) { + warning("Invalid saving procedure (%d, %d, %d)", dataVar, size, offset); + return false; + } + + if (!createWriter(slot)) + return false; + + SavePartInfo info(0, (uint32) _vm->getGameType(), 0, _vm->getEndianness(), 1); + SavePartVars vars(_vm, 1); + + // Write the save point number + if (!vars.readFrom(dataVar, 0, 1)) + return false; + + if (!_writer->writePart(0, &info)) + return false; + if (!_writer->writePart(1, &vars)) + return false; + } + + return true; +} + +bool SaveLoad_Inca2::GameHandler::saveScreenshot(int slot, + const SavePartSprite *screenshot) { + + if (!createWriter(slot)) + return false; + + return _writer->writePart(2, screenshot); +} + +bool SaveLoad_Inca2::GameHandler::loadScreenshot(int slot, + SavePartSprite *screenshot) { + + if (!createReader(slot)) + return false; + + return _reader->readPart(2, screenshot); +} + +void SaveLoad_Inca2::GameHandler::buildIndex() { + _props[499] = _slotFile->getSlotMax(); +} + +bool SaveLoad_Inca2::GameHandler::createReader(int slot) { + // If slot < 0, just check if a reader exists + if (slot < 0) + return (_reader != 0); + + if (!_reader || (_reader->getSlot() != ((uint32) slot))) { + Common::String slotFile = _slotFile->build(slot); + + if (slotFile.empty()) + return false; + + delete _reader; + + _reader = new SaveReader(3, slot, slotFile); + + if (!_reader->load()) { + delete _reader; + _reader = 0; + return false; + } + } + + return true; +} + +bool SaveLoad_Inca2::GameHandler::createWriter(int slot) { + // If slot < 0, just check if a writer exists + if (slot < 0) + return (_writer != 0); + + if (!_writer || (_writer->getSlot() != ((uint32) slot))) { + Common::String slotFile = _slotFile->build(slot); + + if (slotFile.empty()) + return false; + + delete _writer; + _writer = new SaveWriter(3, slot, slotFile); + } + + return true; +} + + +SaveLoad_Inca2::ScreenshotHandler::File::File(const SaveLoad_Inca2::GameHandler::File &file) : SaveLoad_Inca2::GameHandler::File(file) { + +} + +SaveLoad_Inca2::ScreenshotHandler::File::~File() { +} + +int SaveLoad_Inca2::ScreenshotHandler::File::getSlot(int32 offset) const { + return (offset - 80) / 15168; +} + +int SaveLoad_Inca2::ScreenshotHandler::File::getSlotRemainder(int32 offset) const { + return (offset - 80) % 15168; +} + +void SaveLoad_Inca2::ScreenshotHandler::File::buildIndex(byte *buffer) const { + Common::SaveFileManager *saveMan = g_system->getSavefileManager(); + Common::InSaveFile *in; + + for (uint32 i = 0; i < 40; i++, buffer++) { + Common::String slotFile = build(i); + + if (!slotFile.empty() && ((in = saveMan->openForLoading(slotFile)))) { + delete in; + *buffer = 1; + } else + *buffer = 0; + } +} + + +SaveLoad_Inca2::ScreenshotHandler::ScreenshotHandler(GobEngine *vm, + GameHandler *gameHandler) : TempSpriteHandler(vm) { + + assert(gameHandler); + + _gameHandler = gameHandler; + + _file = new File(*_gameHandler->_slotFile); + + memset(_index, 0, 80); +} + +SaveLoad_Inca2::ScreenshotHandler::~ScreenshotHandler() { + delete _file; +} + +int32 SaveLoad_Inca2::ScreenshotHandler::getSize() { + return _file->tallyUpFiles(15168, 80); +} + +bool SaveLoad_Inca2::ScreenshotHandler::load(int16 dataVar, int32 size, int32 offset) { + if (offset < 80) { + // Screenshot index list + + if ((size + offset) > 80) { + warning("Wrong screenshot index offset (%d, %d)", size, offset); + return false; + } + + // Create/Fake the index + _file->buildIndex(_index + 40); + + _vm->_inter->_variables->copyFrom(dataVar, _index + offset, size); + + } else { + // Screenshot + + uint32 slot = _file->getSlot(offset); + int slotRem = _file->getSlotRemainder(offset); + + if ((slot >= kSlotCount) || (slotRem != 0)) { + warning("Invalid screenshot loading procedure (%d, %d, %d, %d, %d)", + dataVar, size, offset, slot, slotRem); + return false; + } + + if (!TempSpriteHandler::createSprite(dataVar, size, offset)) + return false; + + if (!_gameHandler->loadScreenshot(slot, _sprite)) + return false; + + if (!TempSpriteHandler::load(dataVar, size, offset)) + return false; + } + + return true; +} + +bool SaveLoad_Inca2::ScreenshotHandler::save(int16 dataVar, int32 size, int32 offset) { + if (offset < 80) { + // Index, we'll ignore that + + } else { + // Screenshot + + uint32 slot = _file->getSlot(offset); + int slotRem = _file->getSlotRemainder(offset); + + if ((slot >= kSlotCount) || (slotRem != 0)) { + warning("Invalid screenshot saving procedure (%d, %d, %d, %d, %d)", + dataVar, size, offset, slot, slotRem); + return false; + } + + if (!TempSpriteHandler::save(dataVar, size, offset)) + return false; + + return _gameHandler->saveScreenshot(slot, _sprite); + } + + return true; +} + + SaveLoad_Inca2::VoiceHandler::VoiceHandler(GobEngine *vm) : SaveHandler(vm) { } @@ -65,11 +387,15 @@ bool SaveLoad_Inca2::VoiceHandler::save(int16 dataVar, int32 size, int32 offset) SaveLoad_Inca2::SaveLoad_Inca2(GobEngine *vm, const char *targetName) : SaveLoad(vm) { - _tempSpriteHandler = new TempSpriteHandler(vm); _voiceHandler = new VoiceHandler(vm); + _tempSpriteHandler = new TempSpriteHandler(vm); + _gameHandler = new GameHandler(vm, targetName); + _screenshotHandler = new ScreenshotHandler(vm, _gameHandler); _saveFiles[1].handler = _voiceHandler; _saveFiles[2].handler = _tempSpriteHandler; + _saveFiles[3].handler = _gameHandler; + _saveFiles[4].handler = _screenshotHandler; } SaveLoad_Inca2::~SaveLoad_Inca2() { |