AGI save games now contain thumbnails and creation date/time (visible from the GMM save/load screens)
svn-id: r34989
This commit is contained in:
parent
a859e2c1c9
commit
2b59700d2a
4 changed files with 142 additions and 11 deletions
|
@ -724,6 +724,8 @@ public:
|
|||
virtual void replayImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3,
|
||||
int16 p4, int16 p5, int16 p6, int16 p7) = 0;
|
||||
virtual void releaseImageStack() = 0;
|
||||
virtual int saveGame(const char *fileName, const char *saveName) = 0;
|
||||
virtual int loadGame(const char *fileName, bool checkId = true) = 0;
|
||||
|
||||
int _soundemu;
|
||||
|
||||
|
@ -738,6 +740,10 @@ public:
|
|||
uint16 getGameType() const;
|
||||
Common::Language getLanguage() const;
|
||||
Common::Platform getPlatform() const;
|
||||
Common::Error loadGameState(int slot);
|
||||
Common::Error saveGameState(int slot, const char *desc);
|
||||
bool canLoadGameStateCurrently();
|
||||
bool canSaveGameStateCurrently();
|
||||
};
|
||||
|
||||
class AgiEngine : public AgiBase {
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "common/advancedDetector.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/file.h"
|
||||
#include "graphics/thumbnail.h"
|
||||
|
||||
#include "agi/agi.h"
|
||||
#include "agi/preagi.h"
|
||||
|
@ -2127,7 +2128,8 @@ public:
|
|||
virtual SaveStateList listSaves(const char *target) const;
|
||||
virtual int getMaximumSaveSlot() const;
|
||||
virtual void removeSaveState(const char *target, int slot) const;
|
||||
|
||||
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
|
||||
|
||||
const Common::ADGameDescription *fallbackDetect(const Common::FSList &fslist) const;
|
||||
};
|
||||
|
||||
|
@ -2135,11 +2137,17 @@ bool AgiMetaEngine::hasFeature(MetaEngineFeature f) const {
|
|||
return
|
||||
(f == kSupportsListSaves) ||
|
||||
(f == kSupportsLoadingDuringStartup) ||
|
||||
(f == kSupportsDeleteSave);
|
||||
(f == kSupportsDeleteSave) ||
|
||||
(f == kSavesSupportMetaInfo) ||
|
||||
(f == kSavesSupportThumbnail) ||
|
||||
(f == kSavesSupportCreationDate);
|
||||
}
|
||||
|
||||
bool AgiBase::hasFeature(EngineFeature f) const {
|
||||
return (f == kSupportsRTL);
|
||||
return
|
||||
(f == kSupportsRTL) ||
|
||||
(f == kSupportsLoadingDuringRuntime) ||
|
||||
(f == kSupportsSavingDuringRuntime);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2197,13 +2205,67 @@ SaveStateList AgiMetaEngine::listSaves(const char *target) const {
|
|||
int AgiMetaEngine::getMaximumSaveSlot() const { return 999; }
|
||||
|
||||
void AgiMetaEngine::removeSaveState(const char *target, int slot) const {
|
||||
char extension[6];
|
||||
snprintf(extension, sizeof(extension), ".%03d", slot);
|
||||
char fileName[MAX_PATH];
|
||||
sprintf(fileName, "%s.%03d", target, slot);
|
||||
g_system->getSavefileManager()->removeSavefile(fileName);
|
||||
}
|
||||
|
||||
Common::String filename = target;
|
||||
filename += extension;
|
||||
SaveStateDescriptor AgiMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
|
||||
const uint32 AGIflag = MKID_BE('AGI:');
|
||||
char fileName[MAX_PATH];
|
||||
sprintf(fileName, "%s.%03d", target, slot);
|
||||
|
||||
g_system->getSavefileManager()->removeSavefile(filename.c_str());
|
||||
Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(fileName);
|
||||
|
||||
if (in) {
|
||||
if (in->readUint32BE() != AGIflag) {
|
||||
delete in;
|
||||
return SaveStateDescriptor();
|
||||
}
|
||||
|
||||
char name[32];
|
||||
in->read(name, 31);
|
||||
|
||||
SaveStateDescriptor desc(slot, name);
|
||||
|
||||
desc.setDeletableFlag(true);
|
||||
desc.setWriteProtectedFlag(false);
|
||||
|
||||
char saveVersion = in->readByte();
|
||||
if (saveVersion >= 4) {
|
||||
Graphics::Surface *thumbnail = new Graphics::Surface();
|
||||
assert(thumbnail);
|
||||
if (!Graphics::loadThumbnail(*in, *thumbnail)) {
|
||||
delete thumbnail;
|
||||
thumbnail = 0;
|
||||
}
|
||||
|
||||
desc.setThumbnail(thumbnail);
|
||||
|
||||
uint32 saveDate = in->readUint32BE();
|
||||
uint16 saveTime = in->readUint16BE();
|
||||
|
||||
int day = (saveDate >> 24) & 0xFF;
|
||||
int month = (saveDate >> 16) & 0xFF;
|
||||
int year = saveDate & 0xFFFF;
|
||||
|
||||
desc.setSaveDate(year, month, day);
|
||||
|
||||
int hour = (saveTime >> 8) & 0xFF;
|
||||
int minutes = saveTime & 0xFF;
|
||||
|
||||
desc.setSaveTime(hour, minutes);
|
||||
|
||||
// TODO: played time
|
||||
}
|
||||
|
||||
|
||||
delete in;
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
return SaveStateDescriptor();
|
||||
}
|
||||
|
||||
const Common::ADGameDescription *AgiMetaEngine::fallbackDetect(const Common::FSList &fslist) const {
|
||||
|
@ -2375,3 +2437,29 @@ const Common::ADGameDescription *AgiMetaEngine::fallbackDetect(const Common::FSL
|
|||
#else
|
||||
REGISTER_PLUGIN_STATIC(AGI, PLUGIN_TYPE_ENGINE, AgiMetaEngine);
|
||||
#endif
|
||||
|
||||
namespace Agi {
|
||||
|
||||
Common::Error AgiBase::loadGameState(int slot) {
|
||||
static char saveLoadSlot[12];
|
||||
sprintf(saveLoadSlot, "%s.%.3d", _targetName.c_str(), slot);
|
||||
loadGame(saveLoadSlot);
|
||||
return Common::kNoError; // TODO: return success/failure
|
||||
}
|
||||
|
||||
Common::Error AgiBase::saveGameState(int slot, const char *desc) {
|
||||
static char saveLoadSlot[12];
|
||||
sprintf(saveLoadSlot, "%s.%.3d", _targetName.c_str(), slot);
|
||||
saveGame(saveLoadSlot, desc);
|
||||
return Common::kNoError; // TODO: return success/failure
|
||||
}
|
||||
|
||||
bool AgiBase::canLoadGameStateCurrently() {
|
||||
return (!(getGameType() == GType_PreAGI) && getflag(fMenusWork));
|
||||
}
|
||||
|
||||
bool AgiBase::canSaveGameStateCurrently() {
|
||||
return (!(getGameType() == GType_PreAGI) && getflag(fMenusWork));
|
||||
}
|
||||
|
||||
} // End of namespace Agi
|
||||
|
|
|
@ -61,6 +61,8 @@ public:
|
|||
void replayImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3,
|
||||
int16 p4, int16 p5, int16 p6, int16 p7) {}
|
||||
void releaseImageStack() {}
|
||||
int saveGame(const char *fileName, const char *saveName) { return -1; }
|
||||
int loadGame(const char *fileName, bool checkId = true) { return -1; }
|
||||
|
||||
// Game
|
||||
Common::String getTargetName() { return _targetName; }
|
||||
|
|
|
@ -28,8 +28,10 @@
|
|||
* Multi-slots by Claudio Matsuoka <claudio@helllabs.org>
|
||||
*/
|
||||
|
||||
#include <time.h> // for extended infos
|
||||
|
||||
#include "common/file.h"
|
||||
#include "graphics/thumbnail.h"
|
||||
|
||||
#include "agi/agi.h"
|
||||
#include "agi/graphics.h"
|
||||
|
@ -37,13 +39,14 @@
|
|||
#include "agi/keyboard.h"
|
||||
#include "agi/menu.h"
|
||||
|
||||
#define SAVEGAME_VERSION 3
|
||||
#define SAVEGAME_VERSION 4
|
||||
|
||||
/*
|
||||
* Version 0 (Sarien): view table has 64 entries
|
||||
* Version 1 (Sarien): view table has 256 entries (needed in KQ3)
|
||||
* Version 2 (ScummVM): first ScummVM version
|
||||
* Version 3 (ScummVM): adding AGIPAL save/load support
|
||||
* Version 3 (ScummVM): added AGIPAL save/load support
|
||||
* Version 4 (ScummVM): added thumbnails and save creation date/time
|
||||
*/
|
||||
|
||||
namespace Agi {
|
||||
|
@ -70,6 +73,22 @@ int AgiEngine::saveGame(const char *fileName, const char *description) {
|
|||
out->writeByte(SAVEGAME_VERSION);
|
||||
debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing save game version (%d)", SAVEGAME_VERSION);
|
||||
|
||||
// Thumbnail
|
||||
Graphics::saveThumbnail(*out);
|
||||
|
||||
// Creation date/time
|
||||
tm curTime;
|
||||
_system->getTimeAndDate(curTime);
|
||||
|
||||
uint32 saveDate = (curTime.tm_mday & 0xFF) << 24 | ((curTime.tm_mon + 1) & 0xFF) << 16 | (curTime.tm_year + 1900) & 0xFFFF;
|
||||
uint16 saveTime = (curTime.tm_hour & 0xFF) << 8 | (curTime.tm_min) & 0xFF;
|
||||
|
||||
out->writeUint32BE(saveDate);
|
||||
debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing save date (%d)", saveDate);
|
||||
out->writeUint16BE(saveTime);
|
||||
debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing save time (%d)", saveTime);
|
||||
// TODO: played time
|
||||
|
||||
out->writeByte(_game.state);
|
||||
debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing game state (%d)", _game.state);
|
||||
|
||||
|
@ -250,9 +269,25 @@ int AgiEngine::loadGame(const char *fileName, bool checkId) {
|
|||
debugC(6, kDebugLevelMain | kDebugLevelSavegame, "Description is: %s", description);
|
||||
|
||||
saveVersion = in->readByte();
|
||||
if (saveVersion != SAVEGAME_VERSION)
|
||||
if (saveVersion < 2) // is the save game pre-ScummVM?
|
||||
warning("Old save game version (%d, current version is %d). Will try and read anyway, but don't be surprised if bad things happen", saveVersion, SAVEGAME_VERSION);
|
||||
|
||||
if (saveVersion < 3)
|
||||
warning("This save game contains no AGIPAL data, if the game is using the AGIPAL hack, it won't work correctly");
|
||||
|
||||
if (saveVersion >= 4) {
|
||||
// We don't need the thumbnail here, so just read it and discard it
|
||||
Graphics::Surface *thumbnail = new Graphics::Surface();
|
||||
assert(thumbnail);
|
||||
Graphics::loadThumbnail(*in, *thumbnail);
|
||||
delete thumbnail;
|
||||
thumbnail = 0;
|
||||
|
||||
in->readUint32BE(); // save date
|
||||
in->readUint16BE(); // save time
|
||||
// TODO: played time
|
||||
}
|
||||
|
||||
_game.state = in->readByte();
|
||||
|
||||
in->read(loadId, 8);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue