aboutsummaryrefslogtreecommitdiff
path: root/engines/supernova2/supernova2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/supernova2/supernova2.cpp')
-rw-r--r--engines/supernova2/supernova2.cpp181
1 files changed, 177 insertions, 4 deletions
diff --git a/engines/supernova2/supernova2.cpp b/engines/supernova2/supernova2.cpp
index 10c87ecc9e..5572ac2d56 100644
--- a/engines/supernova2/supernova2.cpp
+++ b/engines/supernova2/supernova2.cpp
@@ -133,7 +133,14 @@ void Supernova2Engine::init() {
_gm = new GameManager(this);
_screen = new Screen(this, _resMan);
_console = new Console(this, _gm);
+
setTotalPlayTime(0);
+
+ int saveSlot = ConfMan.getInt("save_slot");
+ if (saveSlot >= 0) {
+ if (loadGameState(saveSlot).getCode() != Common::kNoError)
+ error("Failed to load save game from slot %i", saveSlot);
+ }
}
bool Supernova2Engine::hasFeature(EngineFeature f) const {
@@ -236,6 +243,14 @@ bool Supernova2Engine::setCurrentImage(int filenumber) {
return _screen->setCurrentImage(filenumber);
}
+void Supernova2Engine::saveScreen(int x, int y, int width, int height) {
+ _screen->saveScreen(x, y, width, height);
+}
+
+void Supernova2Engine::saveScreen(const GuiElement &guiElement) {
+ _screen->saveScreen(guiElement);
+}
+
void Supernova2Engine::restoreScreen() {
_screen->restoreScreen();
}
@@ -299,6 +314,13 @@ void Supernova2Engine::renderText(StringId stringId, int x, int y, byte color) {
_screen->renderText(stringId, x, y, color);
}
+void Supernova2Engine::renderBox(int x, int y, int width, int height, byte color) {
+ _screen->renderBox(x, y, width, height, color);
+}
+
+void Supernova2Engine::renderBox(const GuiElement &guiElement) {
+ _screen->renderBox(guiElement);
+}
void Supernova2Engine::paletteBrightness() {
_screen->paletteBrightness();
@@ -430,12 +452,163 @@ void Supernova2Engine::setColor63(byte value) {
return quit;
}*/
-void Supernova2Engine::renderBox(int x, int y, int width, int height, byte color) {
- _screen->renderBox(x, y, width, height, color);
+bool Supernova2Engine::canLoadGameStateCurrently() {
+ return _allowLoadGame;
}
-void Supernova2Engine::renderBox(const GuiElement &guiElement) {
- _screen->renderBox(guiElement);
+Common::Error Supernova2Engine::loadGameState(int slot) {
+ return (loadGame(slot) ? Common::kNoError : Common::kReadingFailed);
+}
+
+bool Supernova2Engine::canSaveGameStateCurrently() {
+ // Do not allow saving when either _allowSaveGame, _animationEnabled or _guiEnabled is false
+ return _allowSaveGame && _gm->_animationEnabled && _gm->_guiEnabled;
+}
+
+Common::Error Supernova2Engine::saveGameState(int slot, const Common::String &desc) {
+ return (saveGame(slot, desc) ? Common::kNoError : Common::kWritingFailed);
+}
+
+bool Supernova2Engine::serialize(Common::WriteStream *out) {
+ if (!_gm->serialize(out))
+ return false;
+ out->writeByte(_screen->getGuiBrightness());
+ out->writeByte(_screen->getViewportBrightness());
+ return true;
+}
+
+bool Supernova2Engine::deserialize(Common::ReadStream *in, int version) {
+ if (!_gm->deserialize(in, version))
+ return false;
+ if (version >= 5) {
+ _screen->setGuiBrightness(in->readByte());
+ _screen->setViewportBrightness(in->readByte());
+ } else {
+ _screen->setGuiBrightness(255);
+ _screen->setViewportBrightness(255);
+ }
+ return true;
+}
+
+bool Supernova2Engine::loadGame(int slot) {
+ if (slot < 0)
+ return false;
+
+ // Make sure no message is displayed as this would otherwise delay the
+ // switch to the new location until a mouse click.
+ removeMessage();
+
+ if (slot == kSleepAutosaveSlot) {
+ if (_sleepAutoSave != nullptr && deserialize(_sleepAutoSave, _sleepAuoSaveVersion)) {
+ // We no longer need the sleep autosave
+ delete _sleepAutoSave;
+ _sleepAutoSave = nullptr;
+ return true;
+ }
+ // Old version used to save it literally in the kSleepAutosaveSlot, so
+ // continue to try to load it from there.
+ }
+
+ Common::String filename = Common::String::format("ms2_save.%03d", slot);
+ Common::InSaveFile *savefile = _saveFileMan->openForLoading(filename);
+ if (!savefile)
+ return false;
+
+ uint saveHeader = savefile->readUint32LE();
+ if (saveHeader != SAVEGAME_HEADER) {
+ warning("No header found in '%s'", filename.c_str());
+ delete savefile;
+ return false; //Common::kUnknownError
+ }
+
+ byte saveVersion = savefile->readByte();
+ if (saveVersion > SAVEGAME_VERSION) {
+ warning("Save game version %i not supported", saveVersion);
+ delete savefile;
+ return false; //Common::kUnknownError;
+ }
+
+ int descriptionSize = savefile->readSint16LE();
+ savefile->skip(descriptionSize);
+ savefile->skip(6);
+ setTotalPlayTime(savefile->readUint32LE() * 1000);
+ Graphics::skipThumbnail(*savefile);
+ if (!deserialize(savefile, saveVersion)) {
+ delete savefile;
+ return false;
+ };
+
+ // With version 9 onward the sleep auto-save is save at the end of a normal save.
+ delete _sleepAutoSave;
+ _sleepAutoSave = nullptr;
+ if (saveVersion >= 9) {
+ _sleepAuoSaveVersion = saveVersion;
+ byte hasAutoSave = savefile->readByte();
+ if (hasAutoSave) {
+ _sleepAutoSave = new Common::MemoryReadWriteStream(DisposeAfterUse::YES);
+ uint nb;
+ char buf[4096];
+ while ((nb = savefile->read(buf, 4096)) > 0)
+ _sleepAutoSave->write(buf, nb);
+ }
+ }
+
+ delete savefile;
+
+ return true;
+}
+
+bool Supernova2Engine::saveGame(int slot, const Common::String &description) {
+ if (slot < 0)
+ return false;
+
+ if (slot == kSleepAutosaveSlot) {
+ delete _sleepAutoSave;
+ _sleepAutoSave = new Common::MemoryReadWriteStream(DisposeAfterUse::YES);
+ _sleepAuoSaveVersion = SAVEGAME_VERSION;
+ serialize(_sleepAutoSave);
+ return true;
+ }
+
+ Common::String filename = Common::String::format("ms2_save.%03d", slot);
+ Common::OutSaveFile *savefile = _saveFileMan->openForSaving(filename);
+ if (!savefile)
+ return false;
+
+ savefile->writeUint32LE(SAVEGAME_HEADER);
+ savefile->writeByte(SAVEGAME_VERSION);
+
+ TimeDate currentDate;
+ _system->getTimeAndDate(currentDate);
+ uint32 saveDate = (currentDate.tm_mday & 0xFF) << 24 | ((currentDate.tm_mon + 1) & 0xFF) << 16 | ((currentDate.tm_year + 1900) & 0xFFFF);
+ uint16 saveTime = (currentDate.tm_hour & 0xFF) << 8 | ((currentDate.tm_min) & 0xFF);
+
+ savefile->writeSint16LE(description.size() + 1);
+ savefile->write(description.c_str(), description.size() + 1);
+ savefile->writeUint32LE(saveDate);
+ savefile->writeUint16LE(saveTime);
+ savefile->writeUint32LE(getTotalPlayTime() / 1000);
+ Graphics::saveThumbnail(*savefile);
+ serialize(savefile);
+
+ if (_sleepAutoSave == nullptr)
+ savefile->writeByte(0);
+ else {
+ savefile->writeByte(1);
+ savefile->write(_sleepAutoSave->getData(), _sleepAutoSave->size());
+ }
+
+ savefile->finalize();
+ delete savefile;
+
+ return true;
+}
+
+void Supernova2Engine::errorTempSave(bool saving) {
+ GUIErrorMessage(saving
+ ? "Failed to save temporary game state. Make sure your save game directory is set in ScummVM and that you can write to it."
+ : "Failed to load temporary game state.");
+ error("Unrecoverable error");
}
}