MADS: Implemented savegame header read/writes

This commit is contained in:
Paul Gilbert 2014-04-26 09:08:46 -04:00
parent 44fd705fdf
commit bae0a6590a
5 changed files with 164 additions and 15 deletions

View File

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

View File

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

View File

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

View File

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

View File

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