ASYLUM: implement saving/loading via the GMM

This commit is contained in:
alxpnv 2021-09-16 15:47:25 +03:00
parent 1dcf364a00
commit 0d1e2da0b0
5 changed files with 176 additions and 97 deletions

View file

@ -113,10 +113,6 @@ AsylumEngine::~AsylumEngine() {
_gameDescription = NULL;
}
bool AsylumEngine::hasFeature(EngineFeature f) const {
return (f == kSupportsReturnToLauncher);
}
Common::Error AsylumEngine::run() {
// Initialize the graphics
initGraphics(640, 480);
@ -641,6 +637,34 @@ void AsylumEngine::checkAchievements() {
}
}
//////////////////////////////////////////////////////////////////////////
// Save/Load
//////////////////////////////////////////////////////////////////////////
bool AsylumEngine::canLoadGameStateCurrently() {
return _handler == _scene || _handler == _menu;
}
bool AsylumEngine::canSaveGameStateCurrently() {
return _handler == _scene;
}
Common::Error AsylumEngine::loadGameState(int slot) {
savegame()->loadList();
savegame()->setIndex(slot);
startGame(savegame()->getScenePack(), AsylumEngine::kStartGameLoad);
return Common::kNoError;
}
Common::Error AsylumEngine::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
savegame()->loadList();
savegame()->setIndex(slot);
savegame()->setName(slot, desc);
savegame()->save(true);
return Common::kNoError;
}
//////////////////////////////////////////////////////////////////////////
// Misc
//////////////////////////////////////////////////////////////////////////

View file

@ -194,6 +194,12 @@ public:
bool isAltDemo() { return Common::File::exists("asylum.dat"); }
Common::Language getLanguage() { return _gameDescription->language; }
// Save/Load
bool canLoadGameStateCurrently();
Common::Error loadGameState(int slot);
bool canSaveGameStateCurrently();
Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false);
private:
const ADGameDescription *_gameDescription;

View file

@ -20,15 +20,19 @@
*
*/
#include "engines/advancedDetector.h"
#include "base/plugins.h"
#include "backends/keymapper/action.h"
#include "backends/keymapper/keymap.h"
#include "common/achievements.h"
#include "common/savefile.h"
#include "common/translation.h"
#include "engines/advancedDetector.h"
#include "asylum/system/savegame.h"
#include "asylum/asylum.h"
#include "asylum/shared.h"
@ -42,14 +46,50 @@ public:
return "Sanitarium (c) ASC Games";
}
bool hasFeature(MetaEngineFeature f) const override;
int getMaximumSaveSlot() const override { return 25; }
SaveStateList listSaves(const char *target) const override;
Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const override;
Common::KeymapArray initKeymaps(const char *target) const override;
const Common::AchievementDescriptionList *getAchievementDescriptionList() const override;
};
bool AsylumMetaEngine::hasFeature(MetaEngineFeature f) const {
return false;
bool Asylum::AsylumEngine::hasFeature(EngineFeature f) const {
return
(f == kSupportsReturnToLauncher) ||
(f == kSupportsLoadingDuringRuntime) ||
(f == kSupportsSavingDuringRuntime);
}
SaveStateList AsylumMetaEngine::listSaves(const char *target) const {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
Common::StringArray filenames;
Common::String pattern(getSavegameFilePattern(target));
filenames = saveFileMan->listSavefiles(pattern);
SaveStateList saveList;
for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
// Obtain the last 3 digits of the filename, since they correspond to the save slot
int slotNum = atoi(file->c_str() + file->size() - 3);
if (slotNum >= 0 && slotNum <= getMaximumSaveSlot()) {
SaveStateDescriptor desc = querySaveMetaInfos(target, slotNum);
if (desc.getSaveSlot() == -1) {
Common::InSaveFile *in(saveFileMan->openForLoading(*file));
if (in && in->size()) {
(void)(uint32)Asylum::Savegame::read(in, "Chapter");
desc.setSaveSlot(slotNum);
desc.setDescription(Asylum::Savegame::read(in, 45, "Game Name"));
}
}
saveList.push_back(desc);
}
}
// Sort saves based on slot number.
Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
Common::Error AsylumMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {

View file

@ -45,8 +45,6 @@ namespace Asylum {
#define SAVEGAME_VERSION_SIZE 11
#define SAVEGAME_NAME_SIZE 45
#define SAVEGAME_NAME "asylum"
#define SAVEGAME_QUICKSLOT 24
#define SAVEGAME_MOVIES "asylum.movies"
@ -134,11 +132,11 @@ bool Savegame::quickLoad() {
return true;
}
void Savegame::save() {
void Savegame::save(bool appendExtended) {
// Original creates a folder to hold saved games and checks for disk space, we can skip that
getCursor()->hide();
if (saveData(getFilename(_index), _names[_index], getWorld()->chapter)) {
if (saveData(getFilename(_index), _names[_index], getWorld()->chapter, appendExtended)) {
_savegames[_index] = true;
getMenu()->setDword455C78(true);
@ -216,7 +214,7 @@ Common::String Savegame::getFilename(uint32 index) const {
if (index > SAVEGAME_COUNT - 1)
error("[Savegame::getFilename] Invalid savegame index (was:%d, valid: [0-24])", index);
return Common::String::format("%s%02d.sav", SAVEGAME_NAME, index);
return _vm->getSaveStateName(index);
}
bool Savegame::isSavegamePresent(Common::String filename) const {
@ -296,7 +294,7 @@ bool Savegame::loadData(Common::String filename) {
return true;
}
bool Savegame::saveData(Common::String filename, Common::String name, ChapterIndex chapter) {
bool Savegame::saveData(Common::String filename, Common::String name, ChapterIndex chapter, bool appendExtended) {
Common::OutSaveFile *file = g_system->getSavefileManager()->openForSaving(filename);
if (!file)
return false;
@ -315,12 +313,17 @@ bool Savegame::saveData(Common::String filename, Common::String name, ChapterInd
write(file, _vm->getTick(), "Time");
if (appendExtended)
_vm->getMetaEngine()->appendExtendedSaveToStream(file, _vm->getTotalPlayTime() / 1000, name, false);
else
file->writeUint32LE(0);
delete file;
return true;
}
void Savegame::seek(Common::InSaveFile *file, uint32 offset, Common::String description) const {
void Savegame::seek(Common::InSaveFile *file, uint32 offset, Common::String description) {
debugC(kDebugLevelSavegame, "[Savegame] Seeking to offset: %s", description.c_str());
if (offset == 0)
@ -337,7 +340,7 @@ void Savegame::seek(Common::InSaveFile *file, uint32 offset, Common::String desc
}
}
uint32 Savegame::read(Common::InSaveFile *file, Common::String description) const {
uint32 Savegame::read(Common::InSaveFile *file, Common::String description) {
debugC(kDebugLevelSavegame, "[Savegame] Reading %s", description.c_str());
uint32 size = file->readUint32LE();
@ -349,7 +352,7 @@ uint32 Savegame::read(Common::InSaveFile *file, Common::String description) cons
return file->readUint32LE();
}
Common::String Savegame::read(Common::InSaveFile *file, uint32 strLength, Common::String description) const {
Common::String Savegame::read(Common::InSaveFile *file, uint32 strLength, Common::String description) {
debugC(kDebugLevelSavegame, "[Savegame] Reading %s (of length %d)", description.c_str(), strLength);
/*uint32 size =*/ file->readUint32LE();
@ -369,7 +372,7 @@ Common::String Savegame::read(Common::InSaveFile *file, uint32 strLength, Common
return ret;
}
void Savegame::read(Common::InSaveFile *file, Common::Serializable *data, uint32 size, uint32 count, Common::String description) const {
void Savegame::read(Common::InSaveFile *file, Common::Serializable *data, uint32 size, uint32 count, Common::String description) {
debugC(kDebugLevelSavegame, "[Savegame] Reading %s (%d block(s) of size %d)", description.c_str(), size, count);
uint32 fileSize = file->readUint32LE();
@ -387,7 +390,7 @@ void Savegame::read(Common::InSaveFile *file, Common::Serializable *data, uint32
data->saveLoadWithSerializer(ser);
}
void Savegame::write(Common::OutSaveFile *file, uint32 val, Common::String description) const {
void Savegame::write(Common::OutSaveFile *file, uint32 val, Common::String description) {
debugC(kDebugLevelSavegame, "[Savegame] Writing %s: %d", description.c_str(), val);
file->writeUint32LE(4);
@ -396,7 +399,7 @@ void Savegame::write(Common::OutSaveFile *file, uint32 val, Common::String descr
file->writeUint32LE(val);
}
void Savegame::write(Common::OutSaveFile *file, Common::String val, uint32 strLength, Common::String description) const {
void Savegame::write(Common::OutSaveFile *file, Common::String val, uint32 strLength, Common::String description) {
debugC(kDebugLevelSavegame, "[Savegame] Writing %s (of length %d): %s", description.c_str(), strLength, val.c_str());
if (val.size() > strLength)
@ -414,7 +417,7 @@ void Savegame::write(Common::OutSaveFile *file, Common::String val, uint32 strLe
}
}
void Savegame::write(Common::OutSaveFile *file, Common::Serializable *data, uint32 size, uint32 count, Common::String description) const {
void Savegame::write(Common::OutSaveFile *file, Common::Serializable *data, uint32 size, uint32 count, Common::String description) {
debugC(kDebugLevelSavegame, "[Savegame] Writing %s (%d block(s) of size %d)", description.c_str(), size, count);
file->writeUint32LE(size);

View file

@ -69,9 +69,11 @@ public:
/**
* Saves a game
*
* @param appendExtended Append the extended savegame header to the stream.
*
* @return true if it succeeds, false if it fails.
*/
void save();
void save(bool appendExtended = false);
/**
* Quick saves a game
@ -85,6 +87,80 @@ public:
*/
void remove();
//////////////////////////////////////////////////////////////////////////
// Static methods
//////////////////////////////////////////////////////////////////////////
/**
* Seeks to a specific place in the file
*
* @param [in,out] file If non-null, the file.
* @param offset Offset index of the info into the file
* @param description The description.
*/
static void seek(Common::InSaveFile *file, uint32 offset, Common::String description);
/**
* Reads data from a file.
*
* @param [in,out] file If non-null, the file.
* @param description The description.
*
* @return the value
*/
static uint32 read(Common::InSaveFile *file, Common::String description);
/**
* Reads data from a file.
*
* @param [in,out] file If non-null, the file.
* @param strLength Length of the string.
* @param description The description.
*
* @return the string
*/
static Common::String read(Common::InSaveFile *file, uint32 strLength, Common::String description);
/**
* Reads data from a file.
*
* @param [in,out] file If non-null, the file.
* @param [in,out] data If non-null, the data.
* @param size The size.
* @param count Number of.
* @param description The description.
*/
static void read(Common::InSaveFile *file, Common::Serializable *data, uint32 size, uint32 count, Common::String description);
/**
* Writes data to a file.
*
* @param [in,out] file If non-null, the file.
* @param val The value
* @param description The description.
*/
static void write(Common::OutSaveFile *file, uint32 val, Common::String description);
/**
* Writes data to a file.
*
* @param [in,out] file If non-null, the file.
* @param val The string
* @param strLength The size of the string.
* @param description The description.
*/
static void write(Common::OutSaveFile *file, Common::String val, uint32 strLength, Common::String description);
/**
* Writes data to a file.
*
* @param [in,out] file If non-null, the file.
* @param [in,out] data If non-null, the data.
* @param size The size.
* @param count Number of.
* @param description The description.
*/
static void write(Common::OutSaveFile *file, Common::Serializable *data, uint32 size, uint32 count, Common::String description);
//////////////////////////////////////////////////////////////////////////
// Movies
//////////////////////////////////////////////////////////////////////////
@ -179,81 +255,11 @@ private:
* @param filename Filename of the file.
* @param name The name.
* @param chapter The chapter.
* @param appendExtended Append the extended savegame header to the stream.
*
* @return true if it succeeds, false if it fails.
*/
bool saveData(Common::String filename, Common::String name, ChapterIndex chapter);
/**
* Seeks to a specific place in the file
*
* @param [in,out] file If non-null, the file.
* @param offset Offset index of the info into the file
* @param description The description.
*/
void seek(Common::InSaveFile *file, uint32 offset, Common::String description) const;
/**
* Reads data from a file.
*
* @param [in,out] file If non-null, the file.
* @param description The description.
*
* @return the value
*/
uint32 read(Common::InSaveFile *file, Common::String description) const;
/**
* Reads data from a file.
*
* @param [in,out] file If non-null, the file.
* @param strLength Length of the string.
* @param description The description.
*
* @return the string
*/
Common::String read(Common::InSaveFile *file, uint32 strLength, Common::String description) const;
/**
* Reads data from a file.
*
* @param [in,out] file If non-null, the file.
* @param [in,out] data If non-null, the data.
* @param size The size.
* @param count Number of.
* @param description The description.
*/
void read(Common::InSaveFile *file, Common::Serializable *data, uint32 size, uint32 count, Common::String description) const;
/**
* Writes data to a file.
*
* @param [in,out] file If non-null, the file.
* @param val The value
* @param description The description.
*/
void write(Common::OutSaveFile *file, uint32 val, Common::String description) const;
/**
* Writes data to a file.
*
* @param [in,out] file If non-null, the file.
* @param val The string
* @param strLength The size of the string.
* @param description The description.
*/
void write(Common::OutSaveFile *file, Common::String val, uint32 strLength, Common::String description) const;
/**
* Writes data to a file.
*
* @param [in,out] file If non-null, the file.
* @param [in,out] data If non-null, the data.
* @param size The size.
* @param count Number of.
* @param description The description.
*/
void write(Common::OutSaveFile *file, Common::Serializable *data, uint32 size, uint32 count, Common::String description) const;
bool saveData(Common::String filename, Common::String name, ChapterIndex chapter, bool appendExtended = false);
};
} // End of namespace Asylum