diff options
author | Walter van Niftrik | 2016-02-29 00:32:47 +0100 |
---|---|---|
committer | Walter van Niftrik | 2016-03-09 10:03:13 +0100 |
commit | e3d13d06ee32fa1cb3663c0e9c46f356f08b5c9b (patch) | |
tree | 59e48469221f5a583dea2e66fc0c471d4c1316a7 | |
parent | 727469d4a7ad9ba516538009efdac3834a6daccd (diff) | |
download | scummvm-rg350-e3d13d06ee32fa1cb3663c0e9c46f356f08b5c9b.tar.gz scummvm-rg350-e3d13d06ee32fa1cb3663c0e9c46f356f08b5c9b.tar.bz2 scummvm-rg350-e3d13d06ee32fa1cb3663c0e9c46f356f08b5c9b.zip |
ADL: Add save game support
-rw-r--r-- | engines/adl/adl.cpp | 118 | ||||
-rw-r--r-- | engines/adl/adl.h | 6 | ||||
-rw-r--r-- | engines/adl/hires1.h | 1 |
3 files changed, 123 insertions, 2 deletions
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp index 24a18d62ac..9c86b3a022 100644 --- a/engines/adl/adl.cpp +++ b/engines/adl/adl.cpp @@ -28,6 +28,7 @@ #include "common/system.h" #include "common/events.h" #include "common/stream.h" +#include "common/savefile.h" #include "engines/util.h" @@ -261,18 +262,21 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) { ++offset; break; case IDO_ACT_SAVE: - warning("Save game not implemented"); + saveState(0); ++offset; break; case IDO_ACT_LOAD: - warning("Load game not implemented"); + loadState(0); ++offset; + // Original engine continues processing here (?) break; case IDO_ACT_RESTART: { _display->printString(_strings[IDI_STR_PLAY_AGAIN]); Common::String input = _display->inputString(); if (input.size() == 0 || input[0] != APPLECHAR('N')) { _isRestarting = true; + _display->clear(0x00); + _display->decodeFrameBuffer(); restartGame(); return; } @@ -451,6 +455,116 @@ void AdlEngine::showRoom() { printMessage(_state.rooms[_state.room].description, false); } +bool AdlEngine::saveState(uint slot) { + Common::String fileName = Common::String::format("%s.s%02d", _targetName.c_str(), slot); + Common::OutSaveFile *outFile = getSaveFileManager()->openForSaving(fileName); + + if (!outFile) { + warning("Failed to open file '%s'", fileName.c_str()); + return false; + } + + outFile->writeUint32BE(getTag()); + outFile->writeByte(SAVEGAME_VERSION); + + outFile->writeByte(_state.room); + outFile->writeByte(_state.moves); + outFile->writeByte(_state.isDark); + + outFile->writeUint32BE(_state.rooms.size()); + for (uint i = 0; i < _state.rooms.size(); ++i) { + outFile->writeByte(_state.rooms[i].picture); + outFile->writeByte(_state.rooms[i].curPicture); + } + + outFile->writeUint32BE(_state.items.size()); + for (uint i = 0; i < _state.items.size(); ++i) { + outFile->writeByte(_state.items[i].room); + outFile->writeByte(_state.items[i].picture); + outFile->writeByte(_state.items[i].position.x); + outFile->writeByte(_state.items[i].position.y); + outFile->writeByte(_state.items[i].state); + } + + outFile->writeUint32BE(_state.vars.size()); + for (uint i = 0; i < _state.vars.size(); ++i) + outFile->writeByte(_state.vars[i]); + + outFile->finalize(); + + if (outFile->err()) { + delete outFile; + warning("Failed to save game '%s'", fileName.c_str()); + return false; + } + + delete outFile; + return true; +} + +bool AdlEngine::loadState(uint slot) { + Common::String fileName = Common::String::format("%s.s%02d", _targetName.c_str(), slot); + Common::InSaveFile *inFile = getSaveFileManager()->openForLoading(fileName); + + if (!inFile) { + warning("Failed to open file '%s'", fileName.c_str()); + return false; + } + + if (inFile->readUint32BE() != getTag()) { + warning("No header found in '%s'", fileName.c_str()); + delete inFile; + return false; + } + + byte saveVersion = inFile->readByte(); + if (saveVersion != SAVEGAME_VERSION) { + warning("Save game version %i not supported", saveVersion); + delete inFile; + return false; + } + + initState(); + + _state.room = inFile->readByte(); + _state.moves = inFile->readByte(); + _state.isDark = inFile->readByte(); + + uint32 size = inFile->readUint32BE(); + if (size != _state.rooms.size()) + error("Room count mismatch (expected %i; found %i)", _state.rooms.size(), size); + + for (uint i = 0; i < size; ++i) { + _state.rooms[i].picture = inFile->readByte(); + _state.rooms[i].curPicture = inFile->readByte(); + } + + size = inFile->readUint32BE(); + if (size != _state.items.size()) + error("Item count mismatch (expected %i; found %i)", _state.items.size(), size); + + for (uint i = 0; i < size; ++i) { + _state.items[i].room = inFile->readByte(); + _state.items[i].picture = inFile->readByte(); + _state.items[i].position.x = inFile->readByte(); + _state.items[i].position.y = inFile->readByte(); + _state.items[i].state = inFile->readByte(); + } + + size = inFile->readUint32BE(); + if (size != _state.vars.size()) + error("Variable count mismatch (expected %i; found %i)", _state.vars.size(), size); + + for (uint i = 0; i < size; ++i) + _state.vars[i] = inFile->readByte(); + + if (inFile->err() || inFile->eos()) + error("Failed to load game '%s'", fileName.c_str()); + + delete inFile; + return true; +} + AdlEngine *AdlEngine::create(GameType type, OSystem *syst, const AdlGameDescription *gd) { switch(type) { case kGameTypeHires1: diff --git a/engines/adl/adl.h b/engines/adl/adl.h index 8b0aa45937..abb62ee8b2 100644 --- a/engines/adl/adl.h +++ b/engines/adl/adl.h @@ -37,6 +37,8 @@ class SeekableReadStream; namespace Adl { +#define SAVEGAME_VERSION 0 + class Display; class Parser; class Console; @@ -178,6 +180,7 @@ protected: virtual void initState() = 0; virtual void restartGame() = 0; virtual uint getEngineMessage(EngineMessage msg) = 0; + virtual uint32 getTag() = 0; Common::String readString(Common::ReadStream &stream, byte until = 0); void printStrings(Common::SeekableReadStream &stream, int count = 1); virtual void printMessage(uint idx, bool wait = true); @@ -211,6 +214,9 @@ protected: private: void printEngineMessage(EngineMessage); + bool saveState(uint slot); + bool loadState(uint slot); + Common::String getTargetName() { return _targetName; } }; AdlEngine *HiRes1Engine__create(OSystem *syst, const AdlGameDescription *gd); diff --git a/engines/adl/hires1.h b/engines/adl/hires1.h index a378dc9423..ab26b2c87d 100644 --- a/engines/adl/hires1.h +++ b/engines/adl/hires1.h @@ -52,6 +52,7 @@ private: void restartGame(); void printMessage(uint idx, bool wait = true); uint getEngineMessage(EngineMessage msg); + uint32 getTag() { return MKTAG('H', 'R', 'A', '1'); } void initState(); void runIntro(); |