aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorWalter van Niftrik2016-03-02 11:38:01 +0100
committerWalter van Niftrik2016-03-09 10:03:13 +0100
commit93f5e36c9f9a75a2fa939408a76b0a2632c09425 (patch)
tree452ae58cf0500086b2af6f4675f44ef540d5566a /engines
parent339d3bc86813b454447b02481f82b85c4c8be75b (diff)
downloadscummvm-rg350-93f5e36c9f9a75a2fa939408a76b0a2632c09425.tar.gz
scummvm-rg350-93f5e36c9f9a75a2fa939408a76b0a2632c09425.tar.bz2
scummvm-rg350-93f5e36c9f9a75a2fa939408a76b0a2632c09425.zip
ADL: Add GMM loading and saving
Diffstat (limited to 'engines')
-rw-r--r--engines/adl/adl.cpp105
-rw-r--r--engines/adl/adl.h12
-rw-r--r--engines/adl/hires1.cpp50
3 files changed, 138 insertions, 29 deletions
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 3c405b67b5..8ffb929e7a 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -43,13 +43,31 @@ AdlEngine::AdlEngine(OSystem *syst, const AdlGameDescription *gd) :
Engine(syst),
_gameDescription(gd),
_display(nullptr),
- _isRestarting(false) {
+ _isRestarting(false),
+ _isRestoring(false),
+ _saveVerb(0),
+ _saveNoun(0),
+ _restoreVerb(0),
+ _restoreNoun(0),
+ _canSaveNow(false),
+ _canRestoreNow(false) {
}
AdlEngine::~AdlEngine() {
delete _display;
}
+bool AdlEngine::hasFeature(EngineFeature f) const {
+ switch (f) {
+ case kSupportsLoadingDuringRuntime:
+ case kSupportsSavingDuringRuntime:
+ case kSupportsRTL:
+ return true;
+ default:
+ return false;
+ }
+}
+
Common::Error AdlEngine::run() {
initGraphics(560, 384, true);
@@ -71,6 +89,7 @@ Common::Error AdlEngine::run() {
if (!loadState(saveSlot))
error("Failed to load save game from slot %i", saveSlot);
_display->setCursorPos(Common::Point(0, 23));
+ _isRestoring = true;
} else {
runIntro();
initState();
@@ -162,6 +181,16 @@ void AdlEngine::readCommands(Common::ReadStream &stream, Commands &commands) {
if (stream.eos() || stream.err())
error("Failed to read commands");
+ if (command.numCond == 0 && command.script[0] == IDO_ACT_SAVE) {
+ _saveVerb = command.verb;
+ _saveNoun = command.noun;
+ }
+
+ if (command.numCond == 0 && command.script[0] == IDO_ACT_LOAD) {
+ _restoreVerb = command.verb;
+ _restoreNoun = command.noun;
+ }
+
commands.push_back(command);
}
}
@@ -278,7 +307,15 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
break;
case IDO_ACT_RESTART: {
_display->printString(_strings[IDI_STR_PLAY_AGAIN]);
+
+ // We allow restoring via GMM here
+ _canRestoreNow = true;
Common::String input = inputString();
+ _canRestoreNow = false;
+
+ if (_isRestoring)
+ return;
+
if (input.size() == 0 || input[0] != APPLECHAR('N')) {
_isRestarting = true;
_display->clear(0x00);
@@ -341,7 +378,7 @@ void AdlEngine::doActions(const Command &command, byte noun, byte offset) {
}
}
-bool AdlEngine::checkCommand(const Command &command, byte verb, byte noun) {
+bool AdlEngine::matchCommand(const Command &command, byte verb, byte noun, bool run) {
if (command.room != IDI_NONE && command.room != _state.room)
return false;
@@ -384,7 +421,8 @@ bool AdlEngine::checkCommand(const Command &command, byte verb, byte noun) {
}
}
- doActions(command, noun, offset);
+ if (run)
+ doActions(command, noun, offset);
return true;
}
@@ -395,7 +433,7 @@ bool AdlEngine::doOneCommand(const Commands &commands, byte verb, byte noun) {
Commands::const_iterator cmd;
for (cmd = commands.begin(); cmd != commands.end(); ++cmd)
- if (checkCommand(*cmd, verb, noun))
+ if (matchCommand(*cmd, verb, noun))
return true;
return false;
@@ -403,14 +441,43 @@ bool AdlEngine::doOneCommand(const Commands &commands, byte verb, byte noun) {
void AdlEngine::doAllCommands(const Commands &commands, byte verb, byte noun) {
Commands::const_iterator cmd;
+ bool oldIsRestoring = _isRestoring;
for (cmd = commands.begin(); cmd != commands.end(); ++cmd) {
- checkCommand(*cmd, verb, noun);
- if (_isRestarting)
- return;
+ matchCommand(*cmd, verb, noun);
+
+ // We assume no restarts happen in this command group. This
+ // simplifies enabling GMM savegame loading on the restart
+ // prompt.
+ if (_isRestarting || _isRestoring != oldIsRestoring)
+ error("Unexpected restart action encountered");
}
}
+bool AdlEngine::canSaveGameStateCurrently() {
+ if (!_canSaveNow)
+ return false;
+
+ Commands::const_iterator cmd;
+
+ // Here we check whether or not the game currently accepts the command
+ // "SAVE GAME". This prevents saving via the GMM in situations where
+ // it wouldn't otherwise be possible to do so.
+ for (cmd = _roomCommands.begin(); cmd != _roomCommands.end(); ++cmd) {
+ if (matchCommand(*cmd, _saveVerb, _saveNoun, false)) {
+ if (cmd->verb != _saveVerb || cmd->noun != _saveNoun)
+ return false;
+ return cmd->numCond == 0 && cmd->script[0] == IDO_ACT_SAVE;
+ }
+ }
+
+ return false;
+}
+
+bool AdlEngine::canLoadGameStateCurrently() {
+ return _canRestoreNow;
+}
+
void AdlEngine::clearScreen() {
_display->setMode(Display::kModeMixed);
_display->clear(0x00);
@@ -654,7 +721,7 @@ Common::String AdlEngine::getLine() {
while (1) {
Common::String line = inputString(APPLECHAR('?'));
- if (shouldQuit())
+ if (shouldQuit() || _isRestoring)
return "";
if ((byte)line[0] == ('\r' | 0x80)) {
@@ -703,7 +770,7 @@ void AdlEngine::getInput(uint &verb, uint &noun) {
_display->printString(getEngineString(IDI_STR_ENTER_COMMAND));
Common::String line = getLine();
- if (shouldQuit())
+ if (shouldQuit() || _isRestoring)
return;
uint index = 0;
@@ -755,7 +822,7 @@ Common::String AdlEngine::inputString(byte prompt) {
while (1) {
byte b = inputKey();
- if (g_engine->shouldQuit())
+ if (g_engine->shouldQuit() || _isRestoring)
return 0;
if (b == 0)
@@ -805,7 +872,7 @@ byte AdlEngine::inputKey() {
_display->showCursor(true);
- while (!g_engine->shouldQuit() && key == 0) {
+ while (!g_engine->shouldQuit() && !_isRestoring && key == 0) {
Common::Event event;
if (ev->pollEvent(event)) {
if (event.type != Common::EVENT_KEYDOWN)
@@ -863,6 +930,22 @@ void AdlEngine::delay(uint32 ms) {
}
}
+Common::Error AdlEngine::loadGameState(int slot) {
+ if (loadState(slot)) {
+ _isRestoring = true;
+ return Common::kNoError;
+ }
+
+ return Common::kUnknownError;
+}
+
+Common::Error AdlEngine::saveGameState(int slot, const Common::String &desc) {
+ if (saveState(slot, &desc))
+ return Common::kNoError;
+
+ return Common::kUnknownError;
+}
+
AdlEngine *AdlEngine::create(GameType type, OSystem *syst, const AdlGameDescription *gd) {
switch(type) {
case kGameTypeHires1:
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index a9ac79d9f0..4d160f08b0 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -168,7 +168,7 @@ public:
virtual ~AdlEngine();
const AdlGameDescription *_gameDescription;
- uint32 getFeatures() const;
+ bool hasFeature(EngineFeature f) const;
const char *getGameId() const;
static AdlEngine *create(GameType type, OSystem *syst, const AdlGameDescription *gd);
@@ -184,12 +184,14 @@ protected:
virtual void initState() = 0;
virtual void restartGame() = 0;
virtual uint getEngineMessage(EngineMessage msg) = 0;
+ bool canSaveGameStateCurrently();
+ bool canLoadGameStateCurrently();
Common::String readString(Common::ReadStream &stream, byte until = 0);
void printStrings(Common::SeekableReadStream &stream, int count = 1);
virtual void printMessage(uint idx, bool wait = true);
void wordWrap(Common::String &str);
void readCommands(Common::ReadStream &stream, Commands &commands);
- bool checkCommand(const Command &command, byte verb, byte noun);
+ bool matchCommand(const Command &command, byte verb, byte noun, bool run = true);
bool doOneCommand(const Commands &commands, byte verb, byte noun);
void doAllCommands(const Commands &commands, byte verb, byte noun);
void doActions(const Command &command, byte noun, byte offset);
@@ -213,10 +215,14 @@ protected:
Common::String inputString(byte prompt = 0);
void delay(uint32 ms);
byte inputKey();
+ Common::Error loadGameState(int slot);
+ Common::Error saveGameState(int slot, const Common::String &desc);
Display *_display;
Parser *_parser;
- bool _isRestarting;
+ bool _isRestarting, _isRestoring;
+ byte _saveVerb, _saveNoun, _restoreVerb, _restoreNoun;
+ bool _canSaveNow, _canRestoreNow;
Common::Array<Common::String> _strings;
Common::Array<Common::String> _messages;
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 591216698b..db69a2d863 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -371,29 +371,49 @@ void HiRes1Engine::runGame() {
printASCIIString("\r\r\r\r\r");
while (1) {
- if (_isRestarting)
- _isRestarting = false;
-
uint verb = 0, noun = 0;
- clearScreen();
- showRoom();
- getInput(verb, noun);
- if (!doOneCommand(_roomCommands, verb, noun))
- printMessage(37);
+ // When restoring from the launcher, we don't read
+ // input on the first iteration. This is needed to
+ // ensure that restoring from the launcher and
+ // restoring in-game brings us to the same game state.
+ // (Also see comment below.)
+ if (!_isRestoring) {
+ clearScreen();
+ showRoom();
- if (_isRestarting)
- continue;
+ _canSaveNow = _canRestoreNow = true;
+ getInput(verb, noun);
+ _canSaveNow = _canRestoreNow = false;
- doAllCommands(_globalCommands, verb, noun);
+ if (shouldQuit())
+ return;
+
+ if (!doOneCommand(_roomCommands, verb, noun))
+ printMessage(IDI_HR1_MSG_DONT_UNDERSTAND);
+ }
- if (_isRestarting)
+ if (_isRestoring) {
+ // We restored from the GMM or launcher. As restoring
+ // with "RESTORE GAME" does not end command processing,
+ // we don't break it off here either. This essentially
+ // means that restoring a game will always run through
+ // the global commands and increase the move counter
+ // before the first user input.
+ printASCIIString("\r");
+ _isRestoring = false;
+ verb = _restoreVerb;
+ noun = _restoreNoun;
+ }
+
+ // Restarting does end command processing
+ if (_isRestarting) {
+ _isRestarting = false;
continue;
+ }
+ doAllCommands(_globalCommands, verb, noun);
_state.moves++;
-
- if (shouldQuit())
- return;
}
}