From 15252ad83c49c0246fabb24856c02fb6bb81ced5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 18 Apr 2009 10:16:08 +0000 Subject: Added support for the global menu save/loading, and changed the savegame format to store the savegame name and thumbnail svn-id: r39979 --- engines/cruise/cruise.cpp | 32 +++++++++++- engines/cruise/cruise.h | 11 ++-- engines/cruise/cruise_main.cpp | 14 +++-- engines/cruise/detection.cpp | 65 ++++++++++++++++++++++++ engines/cruise/function.cpp | 4 +- engines/cruise/menu.cpp | 4 +- engines/cruise/saveload.cpp | 113 ++++++++++++++++++++++++++++------------- engines/cruise/saveload.h | 14 ++++- engines/cruise/vars.cpp | 2 +- engines/cruise/vars.h | 2 +- 10 files changed, 210 insertions(+), 51 deletions(-) (limited to 'engines') diff --git a/engines/cruise/cruise.cpp b/engines/cruise/cruise.cpp index 283817d2a4..ed8cf5f47b 100644 --- a/engines/cruise/cruise.cpp +++ b/engines/cruise/cruise.cpp @@ -74,6 +74,13 @@ CruiseEngine::~CruiseEngine() { freeSystem(); } +bool CruiseEngine::hasFeature(EngineFeature f) const { + return + (f == kSupportsRTL) || + (f == kSupportsLoadingDuringRuntime) || + (f == kSupportsSavingDuringRuntime); +} + Common::Error CruiseEngine::run() { // Initialize backend initGraphics(320, 200, false); @@ -156,8 +163,8 @@ bool CruiseEngine::loadLanguageStrings() { return true; } -void CruiseEngine::pauseEngineIntern(bool pause) { - Engine::pauseEngineIntern(pause); +void CruiseEngine::pauseEngine(bool pause) { + Engine::pauseEngine(pause); if (pause) { // Draw the 'Paused' message @@ -174,5 +181,26 @@ void CruiseEngine::pauseEngineIntern(bool pause) { } } +Common::Error CruiseEngine::loadGameState(int slot) { + return loadSavegameData(slot); +} + +bool CruiseEngine::canLoadGameStateCurrently() { + return playerMenuEnabled != 0; +} + +Common::Error CruiseEngine::saveGameState(int slot, const char *desc) { + return saveSavegameData(slot, desc); +} + +bool CruiseEngine::canSaveGameStateCurrently() { + return (playerMenuEnabled != 0) && (userEnabled != 0); +} + +const char *CruiseEngine::getSavegameFile(int saveGameIdx) { + static char buffer[20]; + sprintf(buffer, "cruise.s%02d", saveGameIdx); + return buffer; +} } // End of namespace Cruise diff --git a/engines/cruise/cruise.h b/engines/cruise/cruise.h index 987d283df1..41d10f2b1d 100644 --- a/engines/cruise/cruise.h +++ b/engines/cruise/cruise.h @@ -30,6 +30,7 @@ #include "common/util.h" #include "engines/engine.h" +#include "engines/game.h" #include "cruise/cruise_main.h" #include "cruise/debugger.h" @@ -79,6 +80,7 @@ protected: public: CruiseEngine(OSystem * syst, const CRUISEGameDescription *gameDesc); virtual ~ CruiseEngine(); + virtual bool hasFeature(EngineFeature f) const; int getGameType() const; uint32 getFeatures() const; @@ -89,11 +91,14 @@ public: bool mt32() const { return _mt32; } bool adlib() const { return _adlib; } virtual GUI::Debugger *getDebugger() { return _debugger; } - virtual void pauseEngineIntern(bool pause); + virtual void pauseEngine(bool pause); const char *langString(LangStringId langId) { return _langStrings[(int)langId].c_str(); } - bool loadSaveDirectory(void); - void makeSystemMenu(void); + static const char *getSavegameFile(int saveGameIdx); + virtual Common::Error loadGameState(int slot); + virtual bool canLoadGameStateCurrently(); + virtual Common::Error saveGameState(int slot, const char *desc); + virtual bool canSaveGameStateCurrently(); const CRUISEGameDescription *_gameDescription; diff --git a/engines/cruise/cruise_main.cpp b/engines/cruise/cruise_main.cpp index 21e99948b8..91398f1e6b 100644 --- a/engines/cruise/cruise_main.cpp +++ b/engines/cruise/cruise_main.cpp @@ -23,6 +23,7 @@ * */ +#include "common/config-manager.h" #include "common/endian.h" #include "common/events.h" #include "common/system.h" // for g_system->getEventManager() @@ -34,6 +35,7 @@ namespace Cruise { +static int playerDontAskQuit; unsigned int timer = 0; gfxEntryStruct* linkedMsgList = NULL; @@ -1583,8 +1585,9 @@ void manageEvents() { currentMouseY = event.mouse.y; break; case Common::EVENT_QUIT: - g_system->quit(); - break; + case Common::EVENT_RTL: + playerDontAskQuit = 1; + return; case Common::EVENT_KEYUP: switch (event.kbd.keycode) { case Common::KEYCODE_ESCAPE: @@ -1724,7 +1727,7 @@ void CruiseEngine::mainLoop(void) { initAllData(); - int playerDontAskQuit = 1; + playerDontAskQuit = 0; int quitValue2 = 1; int quitValue = 0; @@ -1739,6 +1742,7 @@ void CruiseEngine::mainLoop(void) { currentTick = g_system->getMillis(); manageEvents(); + if (playerDontAskQuit) break; if (_vm->getDebugger()->isAttached()) _vm->getDebugger()->onFrame(); @@ -1753,6 +1757,8 @@ void CruiseEngine::mainLoop(void) { _vm->getDebugger()->onFrame(); } } + if (playerDontAskQuit) + break; lastTick = g_system->getMillis(); @@ -1763,6 +1769,8 @@ void CruiseEngine::mainLoop(void) { // readKeyboard(); playerDontAskQuit = processInput(); + if (playerDontAskQuit) + break; if (enableUser) { userEnabled = 1; diff --git a/engines/cruise/detection.cpp b/engines/cruise/detection.cpp index d467bf7710..791b6006fc 100644 --- a/engines/cruise/detection.cpp +++ b/engines/cruise/detection.cpp @@ -30,6 +30,7 @@ #include "engines/advancedDetector.h" #include "cruise/cruise.h" +#include "cruise/saveload.h" namespace Cruise { @@ -177,9 +178,72 @@ public: return "Cruise for a Corpse (C) Delphine Software"; } + virtual bool hasFeature(MetaEngineFeature f) const; + virtual int getMaximumSaveSlot() const { return 99; }; + virtual SaveStateList listSaves(const char *target) const; + virtual void removeSaveState(const char *target, int slot) const; + virtual SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const; virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; }; +bool CruiseMetaEngine::hasFeature(MetaEngineFeature f) const { + return + (f == kSupportsListSaves) || + (f == kSupportsDeleteSave) || + (f == kSavesSupportMetaInfo) || + (f == kSavesSupportThumbnail); +} + +SaveStateList CruiseMetaEngine::listSaves(const char *target) const { + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + Common::StringList filenames; + Common::String pattern("cruise.s??"); + + filenames = saveFileMan->listSavefiles(pattern.c_str()); + sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..) + + SaveStateList saveList; + for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { + // Obtain the last 2 digits of the filename, since they correspond to the save slot + int slotNum = atoi(file->c_str() + file->size() - 2); + + if (slotNum >= 0 && slotNum <= 99) { + Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str()); + if (in) { + Cruise::CruiseSavegameHeader header; + Cruise::readSavegameHeader(in, header); + saveList.push_back(SaveStateDescriptor(slotNum, header.saveName)); + if (header.thumbnail) delete header.thumbnail; + delete in; + } + } + } + + return saveList; +} + +void CruiseMetaEngine::removeSaveState(const char *target, int slot) const { + g_system->getSavefileManager()->removeSavefile(Cruise::CruiseEngine::getSavegameFile(slot)); +} + +SaveStateDescriptor CruiseMetaEngine::querySaveMetaInfos(const char *target, int slot) const { + Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading( + Cruise::CruiseEngine::getSavegameFile(slot)); + assert(f); + + Cruise::CruiseSavegameHeader header; + Cruise::readSavegameHeader(f, header); + delete f; + + // Create the return descriptor + SaveStateDescriptor desc(slot, header.saveName); + desc.setDeletableFlag(true); + desc.setWriteProtectedFlag(false); + desc.setThumbnail(header.thumbnail); + + return desc; +} + bool CruiseMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { const Cruise::CRUISEGameDescription *gd = (const Cruise::CRUISEGameDescription *)desc; if (gd) { @@ -188,6 +252,7 @@ bool CruiseMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGa return gd != 0; } + #if PLUGIN_ENABLED_DYNAMIC(CRUISE) REGISTER_PLUGIN_DYNAMIC(CRUISE, PLUGIN_TYPE_ENGINE, CruiseMetaEngine); #else diff --git a/engines/cruise/function.cpp b/engines/cruise/function.cpp index 2c87fa2599..3f65d61790 100644 --- a/engines/cruise/function.cpp +++ b/engines/cruise/function.cpp @@ -451,8 +451,8 @@ int16 Op_KillMenu(void) { } int16 Op_UserMenu(void) { - int oldValue = entrerMenuJoueur; - entrerMenuJoueur = popVar(); + int oldValue = playerMenuEnabled; + playerMenuEnabled = popVar(); return oldValue; } diff --git a/engines/cruise/menu.cpp b/engines/cruise/menu.cpp index 04cc3d3751..f3b9df49a9 100644 --- a/engines/cruise/menu.cpp +++ b/engines/cruise/menu.cpp @@ -205,7 +205,7 @@ int playerMenu(int menuX, int menuY) { int retourMenu; //int restartGame = 0; - if (entrerMenuJoueur && displayOn) { + if (playerMenuEnabled && displayOn) { if (remdo) { _vm->music().removeSong(); freeStuff2(); @@ -255,7 +255,7 @@ int playerMenu(int menuX, int menuY) { case 3: // select save drive break; case 4: // save - saveSavegameData(0); + saveSavegameData(0, "Default Save"); break; case 5: // load loadSavegameData(0); diff --git a/engines/cruise/saveload.cpp b/engines/cruise/saveload.cpp index 8d9b321955..da25e353b8 100644 --- a/engines/cruise/saveload.cpp +++ b/engines/cruise/saveload.cpp @@ -30,6 +30,9 @@ #include "common/savefile.h" #include "common/system.h" +#include "graphics/scaler.h" +#include "graphics/thumbnail.h" + namespace Cruise { struct overlayRestoreTemporary { @@ -41,6 +44,53 @@ struct overlayRestoreTemporary { overlayRestoreTemporary ovlRestoreData[90]; +bool readSavegameHeader(Common::InSaveFile *in, CruiseSavegameHeader &header) { + char saveIdentBuffer[6]; + header.thumbnail = NULL; + + // Validate the header Id + in->read(saveIdentBuffer, 6); + if (strcmp(saveIdentBuffer, "SVMCR")) + return false; + + header.version = in->readByte(); + if (header.version != CRUISE_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 = new Graphics::Surface(); + if (!Graphics::loadThumbnail(*in, *header.thumbnail)) { + delete header.thumbnail; + header.thumbnail = NULL; + return false; + } + + return true; +} + +void writeSavegameHeader(Common::OutSaveFile *out, CruiseSavegameHeader &header) { + // Write out a savegame header + char saveIdentBuffer[6]; + strcpy(saveIdentBuffer, "SVMCR"); + out->write(saveIdentBuffer, 6); + + out->writeByte(CRUISE_SAVEGAME_VERSION); + + // Write savegame name + out->write(header.saveName.c_str(), header.saveName.size() + 1); + + // Create a thumbnail and save it + Graphics::Surface *thumb = new Graphics::Surface(); + ::createThumbnail(thumb, globalScreen, 320, 200, workpal); + Graphics::saveThumbnail(*out, *thumb); + delete thumb; +} + static void syncPalette(Common::Serializer &s, uint8 *p) { // This is different from the original, where palette entries are 2 bytes each s.syncBytes(p, NBCOLORS * 3); @@ -92,7 +142,7 @@ static void syncBasicInfo(Common::Serializer &s) { s.syncAsSint16LE(var48); s.syncAsSint16LE(flagCt); s.syncAsSint16LE(var41); - s.syncAsSint16LE(entrerMenuJoueur); + s.syncAsSint16LE(playerMenuEnabled); } static void syncBackgroundTable(Common::Serializer &s) { @@ -716,68 +766,61 @@ void initVars(void) { menuDown = 0; buttonDown = 0; var41 = 0; - entrerMenuJoueur = 0; + playerMenuEnabled = 0; PCFadeFlag = 0; } -int saveSavegameData(int saveGameIdx) { - char buffer[256]; - - sprintf(buffer, "CR.%d", saveGameIdx); - +Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName) { + const char *filename = _vm->getSavegameFile(saveGameIdx); Common::SaveFileManager *saveMan = g_system->getSavefileManager(); - Common::OutSaveFile *f = saveMan->openForSaving(buffer); + Common::OutSaveFile *f = saveMan->openForSaving(filename); if (f == NULL) - return 0; + return Common::kNoGameDataFoundError; - // Write out a savegame header - char saveIdentBuffer[6]; - strcpy(saveIdentBuffer, "SAVPC"); - f->write(saveIdentBuffer, 6); + // Save the savegame header + CruiseSavegameHeader header; + header.saveName = saveName; + writeSavegameHeader(f, header); - if (!f->ioFailed()) { + if (f->ioFailed()) { + delete f; + saveMan->removeSavefile(filename); + return Common::kWritingFailed; + } else { + // Create the remainder of the savegame Common::Serializer s(NULL, f); - DoSync(s); f->finalize(); delete f; - return 1; - - } else { - delete f; - saveMan->removeSavefile(buffer); - return 0; + return Common::kNoError; } } -int loadSavegameData(int saveGameIdx) { - char buffer[256]; - char saveIdentBuffer[6]; +Common::Error loadSavegameData(int saveGameIdx) { int lowMemorySave; + Common::String saveName; cellStruct *currentcellHead; - sprintf(buffer, "CR.%d", saveGameIdx); - Common::SaveFileManager *saveMan = g_system->getSavefileManager(); - Common::InSaveFile *f = saveMan->openForLoading(buffer); + Common::InSaveFile *f = saveMan->openForLoading(_vm->getSavegameFile(saveGameIdx)); if (f == NULL) { printInfoBlackBox("Savegame not found..."); waitForPlayerInput(); - return -1; + return Common::kNoGameDataFoundError; } printInfoBlackBox("Loading in progress..."); - f->read(saveIdentBuffer, 6); - if (strcmp(saveIdentBuffer, "SAVPC")) { - delete f; - return -1; - } - initVars(); + // Skip over the savegame header + CruiseSavegameHeader header; + readSavegameHeader(f, header); + if (header.thumbnail) delete header.thumbnail; + + // Synchronise the remaining data of the savegame Common::Serializer s(f, NULL); DoSync(s); @@ -903,7 +946,7 @@ int loadSavegameData(int saveGameIdx) { mainDraw(1); flipScreen(); - return (0); + return Common::kNoError; } } // End of namespace Cruise diff --git a/engines/cruise/saveload.h b/engines/cruise/saveload.h index 11c8269b3c..96433bdee9 100644 --- a/engines/cruise/saveload.h +++ b/engines/cruise/saveload.h @@ -27,11 +27,21 @@ #define CRUISE_SAVELOAD_H #include "common/scummsys.h" +#include "graphics/surface.h" namespace Cruise { -int saveSavegameData(int saveGameIdx); -int loadSavegameData(int saveGameIdx); +#define CRUISE_SAVEGAME_VERSION 1 + +struct CruiseSavegameHeader { + uint8 version; + Common::String saveName; + Graphics::Surface *thumbnail; +}; + +Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName); +Common::Error loadSavegameData(int saveGameIdx); +bool readSavegameHeader(Common::InSaveFile *in, CruiseSavegameHeader &header); } // End of namespace Cruise diff --git a/engines/cruise/vars.cpp b/engines/cruise/vars.cpp index f3165f8cef..3ea591ed43 100644 --- a/engines/cruise/vars.cpp +++ b/engines/cruise/vars.cpp @@ -131,7 +131,7 @@ bool animationStart; int16 autoOvl; int16 var39; -int16 entrerMenuJoueur; +int16 playerMenuEnabled = 0; int16 var41; int16 var42; int16 var45; diff --git a/engines/cruise/vars.h b/engines/cruise/vars.h index a6d9e87613..cd0929e212 100644 --- a/engines/cruise/vars.h +++ b/engines/cruise/vars.h @@ -233,7 +233,7 @@ extern bool animationStart; extern int16 autoOvl; extern int16 var39; -extern int16 entrerMenuJoueur; +extern int16 playerMenuEnabled; extern int16 var39; extern int16 var41; extern int16 var42; -- cgit v1.2.3