ZVISION: Implement several advanced engine features and ScummVM dialogs

The functionality to return to launcher, list saves, delete saves, load
games from the launcher and load and save games during runtime has been
implemented. Also, ScummVM save/load dialogs have been implemented.
Saved games now have three numbers in their file extension, bumping the
possible save game slots up to 999
This commit is contained in:
Filippos Karapetis 2014-12-08 01:08:27 +02:00
parent f2511e5a9e
commit ec1fdeb25a
7 changed files with 121 additions and 23 deletions

View file

@ -23,22 +23,60 @@
#include "common/scummsys.h" #include "common/scummsys.h"
#include "zvision/core/save_manager.h" #include "zvision/core/save_manager.h"
#include "zvision/zvision.h" #include "zvision/zvision.h"
#include "zvision/scripting/script_manager.h" #include "zvision/scripting/script_manager.h"
#include "zvision/graphics/render_manager.h" #include "zvision/graphics/render_manager.h"
#include "common/system.h" #include "common/system.h"
#include "common/translation.h"
#include "graphics/surface.h" #include "graphics/surface.h"
#include "graphics/thumbnail.h" #include "graphics/thumbnail.h"
#include "gui/message.h" #include "gui/message.h"
#include "gui/saveload.h"
namespace ZVision { namespace ZVision {
const uint32 SaveManager::SAVEGAME_ID = MKTAG('Z', 'E', 'N', 'G'); const uint32 SaveManager::SAVEGAME_ID = MKTAG('Z', 'E', 'N', 'G');
bool SaveManager::scummVMSaveLoadDialog(bool isSave) {
GUI::SaveLoadChooser *dialog;
Common::String desc;
int slot;
if (isSave) {
dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
slot = dialog->runModalWithCurrentTarget();
desc = dialog->getResultString();
if (desc.empty()) {
// create our own description for the saved game, the user didnt enter it
desc = dialog->createDefaultSaveDescription(slot);
}
if (desc.size() > 28)
desc = Common::String(desc.c_str(), 28);
} else {
dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
slot = dialog->runModalWithCurrentTarget();
}
delete dialog;
if (slot < 0)
return false;
if (isSave) {
saveGame(slot, desc);
return true;
} else {
Common::ErrorCode result = loadGame(slot).getCode();
return (result == Common::kNoError);
}
}
void SaveManager::saveGame(uint slot, const Common::String &saveName) { void SaveManager::saveGame(uint slot, const Common::String &saveName) {
// The games only support 20 slots // The games only support 20 slots
//assert(slot <= 1 && slot <= 20); //assert(slot <= 1 && slot <= 20);

View file

@ -96,6 +96,7 @@ public:
void prepareSaveBuffer(); void prepareSaveBuffer();
void flushSaveBuffer(); void flushSaveBuffer();
bool scummVMSaveLoadDialog(bool isSave);
private: private:
void writeSaveGameHeader(Common::OutSaveFile *file, const Common::String &saveName); void writeSaveGameHeader(Common::OutSaveFile *file, const Common::String &saveName);
}; };

View file

@ -26,6 +26,8 @@
#include "zvision/zvision.h" #include "zvision/zvision.h"
#include "zvision/detection.h" #include "zvision/detection.h"
#include "zvision/core/save_manager.h"
#include "zvision/scripting/script_manager.h"
#include "common/translation.h" #include "common/translation.h"
#include "common/savefile.h" #include "common/savefile.h"
@ -178,24 +180,40 @@ public:
}; };
bool ZVisionMetaEngine::hasFeature(MetaEngineFeature f) const { bool ZVisionMetaEngine::hasFeature(MetaEngineFeature f) const {
return false; return
/*
(f == kSupportsListSaves) || (f == kSupportsListSaves) ||
(f == kSupportsLoadingDuringStartup) || (f == kSupportsLoadingDuringStartup) ||
(f == kSupportsDeleteSave) || (f == kSupportsDeleteSave);
(f == kSavesSupportMetaInfo) || //(f == kSavesSupportMetaInfo) ||
(f == kSavesSupportThumbnail) || //(f == kSavesSupportThumbnail) ||
(f == kSavesSupportCreationDate) || //(f == kSavesSupportCreationDate) ||
(f == kSavesSupportPlayTime); //(f == kSavesSupportPlayTime);
*/
} }
/*bool ZVision::ZVision::hasFeature(EngineFeature f) const { bool ZVision::ZVision::hasFeature(EngineFeature f) const {
return return
(f == kSupportsRTL) || (f == kSupportsRTL) ||
(f == kSupportsLoadingDuringRuntime) || (f == kSupportsLoadingDuringRuntime) ||
(f == kSupportsSavingDuringRuntime); (f == kSupportsSavingDuringRuntime);
}*/ }
Common::Error ZVision::ZVision::loadGameState(int slot) {
return _saveManager->loadGame(slot);
}
Common::Error ZVision::ZVision::saveGameState(int slot, const Common::String &desc) {
_saveManager->saveGame(slot, desc);
return Common::kNoError;
}
bool ZVision::ZVision::canLoadGameStateCurrently() {
return !_videoIsPlaying;
}
bool ZVision::ZVision::canSaveGameStateCurrently() {
Location currentLocation = _scriptManager->getCurrentLocation();
return !_videoIsPlaying && currentLocation.world != 'g' && !(currentLocation.room == 'j' || currentLocation.room == 'a');
}
bool ZVisionMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { bool ZVisionMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
const ZVision::ZVisionGameDescription *gd = (const ZVision::ZVisionGameDescription *)desc; const ZVision::ZVisionGameDescription *gd = (const ZVision::ZVisionGameDescription *)desc;
@ -213,8 +231,8 @@ const ExtraGuiOptions ZVisionMetaEngine::getExtraGuiOptions(const Common::String
} }
SaveStateList ZVisionMetaEngine::listSaves(const char *target) const { SaveStateList ZVisionMetaEngine::listSaves(const char *target) const {
//Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
/*ZVision::ZVision::SaveHeader header; ZVision::SaveGameHeader header;
Common::String pattern = target; Common::String pattern = target;
pattern += ".???"; pattern += ".???";
@ -223,20 +241,25 @@ SaveStateList ZVisionMetaEngine::listSaves(const char *target) const {
Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)*/ Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)*/
SaveStateList saveList; SaveStateList saveList;
/* for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); file++) { // We only use readSaveGameHeader() here, which doesn't need an engine callback
ZVision::SaveManager *zvisionSaveMan = new ZVision::SaveManager(NULL);
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 // Obtain the last 3 digits of the filename, since they correspond to the save slot
int slotNum = atoi(file->c_str() + file->size() - 3); int slotNum = atoi(file->c_str() + file->size() - 3);
if (slotNum >= 0 && slotNum <= 999) { if (slotNum >= 0 && slotNum <= 999) {
Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str()); Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
if (in) { if (in) {
if (ZVision::ZVision::readSaveHeader(in, false, header) == ZVision::ZVision::kRSHENoError) { if (zvisionSaveMan->readSaveGameHeader(in, header)) {
saveList.push_back(SaveStateDescriptor(slotNum, header.description)); saveList.push_back(SaveStateDescriptor(slotNum, header.saveName));
} }
delete in; delete in;
} }
} }
}*/ }
delete zvisionSaveMan;
return saveList; return saveList;
} }
@ -246,9 +269,8 @@ int ZVisionMetaEngine::getMaximumSaveSlot() const {
} }
void ZVisionMetaEngine::removeSaveState(const char *target, int slot) const { void ZVisionMetaEngine::removeSaveState(const char *target, int slot) const {
/*
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
Common::String filename = ZVision::ZVision::getSavegameFilename(target, slot); Common::String filename = Common::String::format("%s.%03u", target, slot);
saveFileMan->removeSavefile(filename.c_str()); saveFileMan->removeSavefile(filename.c_str());
@ -265,10 +287,9 @@ void ZVisionMetaEngine::removeSaveState(const char *target, int slot) const {
// Rename every slot greater than the deleted slot, // Rename every slot greater than the deleted slot,
if (slotNum > slot) { if (slotNum > slot) {
saveFileMan->renameSavefile(file->c_str(), filename.c_str()); saveFileMan->renameSavefile(file->c_str(), filename.c_str());
filename = ZVision::ZVision::getSavegameFilename(target, ++slot); filename = Common::String::format("%s.%03u", target, ++slot);
} }
} }
*/
} }
SaveStateDescriptor ZVisionMetaEngine::querySaveMetaInfos(const char *target, int slot) const { SaveStateDescriptor ZVisionMetaEngine::querySaveMetaInfos(const char *target, int slot) const {

View file

@ -36,6 +36,7 @@
#include "common/hashmap.h" #include "common/hashmap.h"
#include "common/debug.h" #include "common/debug.h"
#include "common/stream.h" #include "common/stream.h"
#include "common/config-manager.h"
namespace ZVision { namespace ZVision {
@ -521,6 +522,28 @@ void ScriptManager::ChangeLocationReal() {
assert(_nextLocation.world != 0); assert(_nextLocation.world != 0);
debug(1, "Changing location to: %c %c %c %c %u", _nextLocation.world, _nextLocation.room, _nextLocation.node, _nextLocation.view, _nextLocation.offset); debug(1, "Changing location to: %c %c %c %c %u", _nextLocation.world, _nextLocation.room, _nextLocation.node, _nextLocation.view, _nextLocation.offset);
if (_nextLocation.world == 'g' && _nextLocation.room == 'j' && !ConfMan.getBool("originalsaveload")) {
if ((_nextLocation.node == 's' || _nextLocation.node == 'r') && _nextLocation.view == 'e') {
// Hook up the ScummVM save/restore dialog
bool isSave = (_nextLocation.node == 's');
bool gameSavedOrLoaded = _engine->getSaveManager()->scummVMSaveLoadDialog(isSave);
if (!gameSavedOrLoaded || isSave) {
// Reload the current room
_nextLocation.world = _currentLocation.world;
_nextLocation.room = _currentLocation.room;
_nextLocation.node = _currentLocation.node;
_nextLocation.view = _currentLocation.view;
_nextLocation.offset = _currentLocation.offset;
_currentLocation.world = '0';
_currentLocation.room = '0';
_currentLocation.node = '0';
_currentLocation.view = '0';
_currentLocation.offset = 0;
} else
return;
}
}
_engine->setRenderDelay(2); _engine->setRenderDelay(2);
if (getStateValue(StateKey_World) != 'g' || getStateValue(StateKey_Room) != 'j') { if (getStateValue(StateKey_World) != 'g' || getStateValue(StateKey_Room) != 'j') {

View file

@ -53,6 +53,7 @@ void ZVision::playVideo(Video::VideoDecoder &vid, const Common::Rect &destRect,
_clock.stop(); _clock.stop();
vid.start(); vid.start();
_videoIsPlaying = true;
// Only continue while the video is still playing // Only continue while the video is still playing
while (!shouldQuit() && !vid.endOfVideo() && vid.isPlaying()) { while (!shouldQuit() && !vid.endOfVideo() && vid.isPlaying()) {
@ -99,6 +100,7 @@ void ZVision::playVideo(Video::VideoDecoder &vid, const Common::Rect &destRect,
_system->delayMillis(vid.getTimeToNextFrame() / 2); _system->delayMillis(vid.getTimeToNextFrame() / 2);
} }
_videoIsPlaying = false;
_clock.start(); _clock.start();
if (scaled) { if (scaled) {

View file

@ -96,7 +96,8 @@ ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc)
_audioId(0), _audioId(0),
_rendDelay(2), _rendDelay(2),
_kbdVelocity(0), _kbdVelocity(0),
_mouseVelocity(0) { _mouseVelocity(0),
_videoIsPlaying(false) {
debug(1, "ZVision::ZVision"); debug(1, "ZVision::ZVision");
@ -205,6 +206,10 @@ void ZVision::initialize() {
Common::Error ZVision::run() { Common::Error ZVision::run() {
initialize(); initialize();
// Check if a saved game is to be loaded from the launcher
if (ConfMan.hasKey("save_slot"))
_saveManager->loadGame(ConfMan.getInt("save_slot"));
// Main loop // Main loop
while (!shouldQuit()) { while (!shouldQuit()) {
_clock.update(); _clock.update();
@ -327,7 +332,7 @@ void ZVision::pauseEngineIntern(bool pause) {
} }
Common::String ZVision::generateSaveFileName(uint slot) { Common::String ZVision::generateSaveFileName(uint slot) {
return Common::String::format("%s.%02u", _targetName.c_str(), slot); return Common::String::format("%s.%03u", _targetName.c_str(), slot);
} }
Common::String ZVision::generateAutoSaveFileName() { Common::String ZVision::generateAutoSaveFileName() {

View file

@ -124,6 +124,7 @@ private:
int16 _mouseVelocity; int16 _mouseVelocity;
int16 _kbdVelocity; int16 _kbdVelocity;
bool _halveDelay; bool _halveDelay;
bool _videoIsPlaying;
uint8 _cheatBuff[KEYBUF_SIZE]; uint8 _cheatBuff[KEYBUF_SIZE];
public: public:
@ -198,6 +199,13 @@ public:
void checkBorders(); void checkBorders();
void showDebugMsg(const Common::String &msg, int16 delay = 3000); void showDebugMsg(const Common::String &msg, int16 delay = 3000);
// Engine features
bool hasFeature(EngineFeature f) const;
bool canLoadGameStateCurrently();
bool canSaveGameStateCurrently();
Common::Error loadGameState(int slot);
Common::Error saveGameState(int slot, const Common::String &desc);
private: private:
void initialize(); void initialize();
void initFonts(); void initFonts();