Added support for the global menu save/loading, and changed the savegame format to store the savegame name and thumbnail

svn-id: r39979
This commit is contained in:
Paul Gilbert 2009-04-18 10:16:08 +00:00
parent 0b2e06e4a4
commit 15252ad83c
10 changed files with 210 additions and 51 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -451,8 +451,8 @@ int16 Op_KillMenu(void) {
}
int16 Op_UserMenu(void) {
int oldValue = entrerMenuJoueur;
entrerMenuJoueur = popVar();
int oldValue = playerMenuEnabled;
playerMenuEnabled = popVar();
return oldValue;
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -131,7 +131,7 @@ bool animationStart;
int16 autoOvl;
int16 var39;
int16 entrerMenuJoueur;
int16 playerMenuEnabled = 0;
int16 var41;
int16 var42;
int16 var45;

View File

@ -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;