From bae0a6590a4ba843ef51f4cc67875c578863f5b2 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 26 Apr 2014 09:08:46 -0400 Subject: MADS: Implemented savegame header read/writes --- engines/mads/detection.cpp | 7 +++ engines/mads/game.cpp | 122 +++++++++++++++++++++++++++++++++++++++------ engines/mads/game.h | 36 +++++++++++++ engines/mads/mads.cpp | 8 +++ engines/mads/mads.h | 6 +++ 5 files changed, 164 insertions(+), 15 deletions(-) (limited to 'engines/mads') diff --git a/engines/mads/detection.cpp b/engines/mads/detection.cpp index 015859f827..b8e75b4393 100644 --- a/engines/mads/detection.cpp +++ b/engines/mads/detection.cpp @@ -31,6 +31,7 @@ #include "common/system.h" #include "graphics/colormasks.h" #include "graphics/surface.h" +#include "mads/game.h" #define MAX_SAVES 99 @@ -124,6 +125,7 @@ SaveStateList MADSMetaEngine::listSaves(const char *target) const { Common::StringArray filenames; Common::String saveDesc; Common::String pattern = Common::String::format("%s.0??", target); + MADS::MADSSavegameHeader header; filenames = saveFileMan->listSavefiles(pattern); sort(filenames.begin(), filenames.end()); // Sort to get the files in numerical order @@ -137,6 +139,11 @@ SaveStateList MADSMetaEngine::listSaves(const char *target) const { Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file); if (in) { + MADS::Game::readSavegameHeader(in, header); + saveList.push_back(SaveStateDescriptor(slot, header._saveName)); + + header._thumbnail->free(); + delete header._thumbnail; delete in; } } diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp index 9c124aa6a6..50c3ccd916 100644 --- a/engines/mads/game.cpp +++ b/engines/mads/game.cpp @@ -21,8 +21,12 @@ */ #include "common/scummsys.h" +#include "common/config-manager.h" #include "common/memstream.h" #include "common/serializer.h" +#include "graphics/palette.h" +#include "graphics/scaler.h" +#include "graphics/thumbnail.h" #include "mads/mads.h" #include "mads/compression.h" #include "mads/game.h" @@ -46,6 +50,7 @@ Game::Game(MADSEngine *vm): _vm(vm), _surface(nullptr), _objects(vm), _scene(vm), _screenObjects(vm), _player(vm) { _sectionNumber = _priorSectionNumber = 0; _difficulty = DIFFICULTY_HARD; + _loadGameSlot = -1; _serializer = nullptr; _statusFlag = 0; _sectionHandler = nullptr; @@ -81,22 +86,33 @@ Game::~Game() { void Game::run() { initialiseGlobals(); + // If requested, load a savegame instead of showing the intro + if (ConfMan.hasKey("save_slot")) { + int saveSlot = ConfMan.getInt("save_slot"); + if (saveSlot >= 0 && saveSlot <= 999) + _loadGameSlot = saveSlot; + } + _statusFlag = true; - int protectionResult = checkCopyProtection(); - switch (protectionResult) { - case PROTECTION_FAIL: - // Copy protection failed - _scene._nextSceneId = 804; - break; - case PROTECTION_ESCAPE: - // User escaped out of copy protection dialog - _vm->quitGame(); - break; - default: - // Copy protection check succeeded - _scene._nextSceneId = 103; - _scene._priorSceneId = 102; - break; + int protectionResult = -1; + + if (_loadGameSlot == -1) { + protectionResult = checkCopyProtection(); + switch (protectionResult) { + case PROTECTION_FAIL: + // Copy protection failed + _scene._nextSceneId = 804; + break; + case PROTECTION_ESCAPE: + // User escaped out of copy protection dialog + _vm->quitGame(); + break; + default: + // Copy protection check succeeded + _scene._nextSceneId = 103; + _scene._priorSceneId = 102; + break; + } } // Get the initial starting time for the first scene @@ -422,4 +438,80 @@ void Game::synchronize(Common::Serializer &s, bool phase1) { } } +void Game::loadGame(int slotNumber) { + +} + +void Game::saveGame(int slotNumber, const Common::String &saveName) { + +} + +const char *const SAVEGAME_STR = "MADS"; +#define SAVEGAME_STR_SIZE 4 + +bool Game::readSavegameHeader(Common::InSaveFile *in, MADSSavegameHeader &header) { + char saveIdentBuffer[SAVEGAME_STR_SIZE + 1]; + header._thumbnail = NULL; + + // Validate the header Id + in->read(saveIdentBuffer, SAVEGAME_STR_SIZE + 1); + if (strncmp(saveIdentBuffer, SAVEGAME_STR, SAVEGAME_STR_SIZE)) + return false; + + header._version = in->readByte(); + if (header._version > MADS_SAVEGAME_VERSION) + return false; + + // Read in the string + header._saveName.clear(); + char ch; + while ((ch = (char)in->readByte()) != '\0') header._saveName += ch; + + // Get the thumbnail + header._thumbnail = Graphics::loadThumbnail(*in); + if (!header._thumbnail) + return false; + + // Read in save date/time + header._year = in->readSint16LE(); + header._month = in->readSint16LE(); + header._day = in->readSint16LE(); + header._hour = in->readSint16LE(); + header._minute = in->readSint16LE(); + header._totalFrames = in->readUint32LE(); + + return true; +} + +void Game::writeSavegameHeader(Common::OutSaveFile *out, MADSSavegameHeader &header) { + // Write out a savegame header + out->write(SAVEGAME_STR, SAVEGAME_STR_SIZE + 1); + + out->writeByte(MADS_SAVEGAME_VERSION); + + // Write savegame name + out->write(header._saveName.c_str(), header._saveName.size() + 1); + + // Get the active palette + uint8 thumbPalette[256 * 3]; + g_system->getPaletteManager()->grabPalette(thumbPalette, 0, 256); + + // Create a thumbnail and save it + Graphics::Surface *thumb = new Graphics::Surface(); + ::createThumbnail(thumb, _vm->_screen.getData(), MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT, thumbPalette); + Graphics::saveThumbnail(*out, *thumb); + thumb->free(); + delete thumb; + + // Write out the save date/time + TimeDate td; + g_system->getTimeAndDate(td); + out->writeSint16LE(td.tm_year + 1900); + out->writeSint16LE(td.tm_mon + 1); + out->writeSint16LE(td.tm_mday); + out->writeSint16LE(td.tm_hour); + out->writeSint16LE(td.tm_min); + out->writeUint32LE(_vm->_events->getFrameCounter()); +} + } // End of namespace MADS diff --git a/engines/mads/game.h b/engines/mads/game.h index ad40fbdcc0..8334d94256 100644 --- a/engines/mads/game.h +++ b/engines/mads/game.h @@ -24,6 +24,7 @@ #define MADS_GAME_H #include "common/scummsys.h" +#include "common/savefile.h" #include "common/str-array.h" #include "common/serializer.h" #include "mads/scene.h" @@ -54,6 +55,17 @@ enum ProtectionResult { PROTECTION_SUCCEED = 0, PROTECTION_FAIL = 1, PROTECTION_ESCAPE = 2 }; +#define MADS_SAVEGAME_VERSION 1 + +struct MADSSavegameHeader { + uint8 _version; + Common::String _saveName; + Graphics::Surface *_thumbnail; + int _year, _month, _day; + int _hour, _minute; + int _totalFrames; +}; + class Game { private: /** @@ -78,6 +90,8 @@ protected: bool _quoteEmergency; bool _vocabEmergency; bool _anyEmergency; + int _loadGameSlot; + Common::String _saveName; Common::Serializer *_serializer; /** @@ -188,6 +202,28 @@ public: * Handle a keyboard event */ void handleKeypress(const Common::Event &event); + + /** + * Starts a savegame loading. + * @remarks Due to the way the engine is implemented, loading is done in two + * parts, the second part after the specific scene has been loaded + */ + void loadGame(int slotNumber); + + /** + * Save the current game + */ + void saveGame(int slotNumber, const Common::String &saveName); + + /** + * Write out a savegame header + */ + void writeSavegameHeader(Common::OutSaveFile *out, MADSSavegameHeader &header); + + /** + * Read in a savegame header + */ + static bool readSavegameHeader(Common::InSaveFile *in, MADSSavegameHeader &header); }; } // End of namespace MADS diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp index 6f57b1df60..1df41ad3fd 100644 --- a/engines/mads/mads.cpp +++ b/engines/mads/mads.cpp @@ -130,4 +130,12 @@ bool MADSEngine::canSaveGameStateCurrently() { && _dialogs->_pendingDialog == DIALOG_NONE; } +/** +* Support method that generates a savegame name +* @param slot Slot number +*/ +Common::String MADSEngine::generateSaveName(int slot) { + return Common::String::format("%s.%03d", _targetName.c_str(), slot); +} + } // End of namespace MADS diff --git a/engines/mads/mads.h b/engines/mads/mads.h index f13b3b9008..8a4b7f64d1 100644 --- a/engines/mads/mads.h +++ b/engines/mads/mads.h @@ -129,6 +129,12 @@ public: * Returns true if it is currently okay to save the game */ bool canSaveGameStateCurrently(); + + /** + * Support method that generates a savegame name + * @param slot Slot number + */ + Common::String generateSaveName(int slot); }; } // End of namespace MADS -- cgit v1.2.3