diff options
Diffstat (limited to 'engines/adl/adl.cpp')
-rw-r--r-- | engines/adl/adl.cpp | 275 |
1 files changed, 145 insertions, 130 deletions
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp index bc5bc74f3a..c1c3820b10 100644 --- a/engines/adl/adl.cpp +++ b/engines/adl/adl.cpp @@ -56,11 +56,14 @@ AdlEngine::AdlEngine(OSystem *syst, const AdlGameDescription *gd) : _dumpFile(nullptr), _display(nullptr), _graphics(nullptr), + _speaker(nullptr), _isRestarting(false), _isRestoring(false), _isQuitting(false), _skipOneCommand(false), _gameDescription(gd), + _console(nullptr), + _messageIds(), _saveVerb(0), _saveNoun(0), _restoreVerb(0), @@ -427,6 +430,11 @@ void AdlEngine::initState() { initGameState(); } +void AdlEngine::switchRoom(byte roomNr) { + getCurRoom().curPicture = getCurRoom().picture; + _state.room = roomNr; +} + byte AdlEngine::roomArg(byte room) const { return room; } @@ -578,6 +586,60 @@ void AdlEngine::dropItem(byte noun) { printMessage(_messageIds.dontUnderstand); } +void AdlEngine::gameLoop() { + uint verb = 0, noun = 0; + _isRestarting = false; + + // 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) { + showRoom(); + + if (_isRestarting) + return; + + _canSaveNow = _canRestoreNow = true; + getInput(verb, noun); + _canSaveNow = _canRestoreNow = false; + + if (shouldQuit()) + return; + + // If we just restored from the GMM, we skip this command + // set, as no command has been input by the user + if (!_isRestoring) + checkInput(verb, noun); + } + + 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. + _display->printAsciiString("\r"); + _isRestoring = false; + verb = _restoreVerb; + noun = _restoreNoun; + } + + // Restarting does end command processing + if (_isRestarting) + return; + + doAllCommands(_globalCommands, verb, noun); + + if (_isRestarting) + return; + + advanceClock(); + _state.moves++; +} + Common::Error AdlEngine::run() { initGraphics(DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 2, true); @@ -603,59 +665,8 @@ Common::Error AdlEngine::run() { _display->setMode(DISPLAY_MODE_MIXED); - while (!_isQuitting) { - uint verb = 0, noun = 0; - _isRestarting = false; - - // 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) { - showRoom(); - - if (_isRestarting) - continue; - - _canSaveNow = _canRestoreNow = true; - getInput(verb, noun); - _canSaveNow = _canRestoreNow = false; - - if (shouldQuit()) - break; - - // If we just restored from the GMM, we skip this command - // set, as no command has been input by the user - if (!_isRestoring) - checkInput(verb, noun); - } - - 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. - _display->printAsciiString("\r"); - _isRestoring = false; - verb = _restoreVerb; - noun = _restoreNoun; - } - - // Restarting does end command processing - if (_isRestarting) - continue; - - doAllCommands(_globalCommands, verb, noun); - - if (_isRestarting) - continue; - - advanceClock(); - _state.moves++; - } + while (!(_isQuitting || shouldQuit())) + gameLoop(); return Common::kNoError; } @@ -671,6 +682,49 @@ bool AdlEngine::hasFeature(EngineFeature f) const { } } +void AdlEngine::loadState(Common::ReadStream &stream) { + _state.room = stream.readByte(); + _state.moves = stream.readByte(); + _state.isDark = stream.readByte(); + _state.time.hours = stream.readByte(); + _state.time.minutes = stream.readByte(); + + uint32 size = stream.readUint32BE(); + if (size != _state.rooms.size()) + error("Room count mismatch (expected %i; found %i)", _state.rooms.size(), size); + + for (uint i = 0; i < size; ++i) { + _state.rooms[i].picture = stream.readByte(); + _state.rooms[i].curPicture = stream.readByte(); + _state.rooms[i].isFirstTime = stream.readByte(); + } + + // NOTE: _state.curPicture is part of the save state in the original engine. We + // reconstruct it instead. This is believed to be safe for at least hires 0-2, but + // this may need to be re-evaluated for later games. + _state.curPicture = getCurRoom().curPicture; + + size = stream.readUint32BE(); + if (size != _state.items.size()) + error("Item count mismatch (expected %i; found %i)", _state.items.size(), size); + + Common::List<Item>::iterator item; + for (item = _state.items.begin(); item != _state.items.end(); ++item) { + item->room = stream.readByte(); + item->picture = stream.readByte(); + item->position.x = stream.readByte(); + item->position.y = stream.readByte(); + item->state = stream.readByte(); + } + + size = stream.readUint32BE(); + if (size != _state.vars.size()) + error("Variable count mismatch (expected %i; found %i)", _state.vars.size(), size); + + for (uint i = 0; i < size; ++i) + _state.vars[i] = stream.readByte(); +} + Common::Error AdlEngine::loadGameState(int slot) { Common::String fileName = Common::String::format("%s.s%02d", _targetName.c_str(), slot); Common::InSaveFile *inFile = getSaveFileManager()->openForLoading(fileName); @@ -703,47 +757,7 @@ Common::Error AdlEngine::loadGameState(int slot) { Graphics::skipThumbnail(*inFile); initState(); - - _state.room = inFile->readByte(); - _state.moves = inFile->readByte(); - _state.isDark = inFile->readByte(); - _state.time.hours = inFile->readByte(); - _state.time.minutes = inFile->readByte(); - - uint32 size = inFile->readUint32BE(); - if (size != _state.rooms.size()) - error("Room count mismatch (expected %i; found %i)", _state.rooms.size(), size); - - for (uint i = 0; i < size; ++i) { - _state.rooms[i].picture = inFile->readByte(); - _state.rooms[i].curPicture = inFile->readByte(); - _state.rooms[i].isFirstTime = inFile->readByte(); - } - - // NOTE: _state.curPicture is part of the save state in the original engine. We - // reconstruct it instead. This is believed to be safe for at least hires 0-2, but - // this may need to be re-evaluated for later games. - _state.curPicture = getCurRoom().curPicture; - - size = inFile->readUint32BE(); - if (size != _state.items.size()) - error("Item count mismatch (expected %i; found %i)", _state.items.size(), size); - - Common::List<Item>::iterator item; - for (item = _state.items.begin(); item != _state.items.end(); ++item) { - item->room = inFile->readByte(); - item->picture = inFile->readByte(); - item->position.x = inFile->readByte(); - item->position.y = inFile->readByte(); - item->state = inFile->readByte(); - } - - size = inFile->readUint32BE(); - if (size != _state.vars.size()) - error("Variable count mismatch (expected %i; found %i)", _state.vars.size(), size); - - for (uint i = 0; i < size; ++i) - _state.vars[i] = inFile->readByte(); + loadState(*inFile); if (inFile->err() || inFile->eos()) error("Failed to load game '%s'", fileName.c_str()); @@ -760,6 +774,35 @@ bool AdlEngine::canLoadGameStateCurrently() { return _canRestoreNow; } +void AdlEngine::saveState(Common::WriteStream &stream) { + stream.writeByte(_state.room); + stream.writeByte(_state.moves); + stream.writeByte(_state.isDark); + stream.writeByte(_state.time.hours); + stream.writeByte(_state.time.minutes); + + stream.writeUint32BE(_state.rooms.size()); + for (uint i = 0; i < _state.rooms.size(); ++i) { + stream.writeByte(_state.rooms[i].picture); + stream.writeByte(_state.rooms[i].curPicture); + stream.writeByte(_state.rooms[i].isFirstTime); + } + + stream.writeUint32BE(_state.items.size()); + Common::List<Item>::const_iterator item; + for (item = _state.items.begin(); item != _state.items.end(); ++item) { + stream.writeByte(item->room); + stream.writeByte(item->picture); + stream.writeByte(item->position.x); + stream.writeByte(item->position.y); + stream.writeByte(item->state); + } + + stream.writeUint32BE(_state.vars.size()); + for (uint i = 0; i < _state.vars.size(); ++i) + stream.writeByte(_state.vars[i]); +} + Common::Error AdlEngine::saveGameState(int slot, const Common::String &desc) { Common::String fileName = Common::String::format("%s.s%02d", _targetName.c_str(), slot); Common::OutSaveFile *outFile = getSaveFileManager()->openForSaving(fileName); @@ -797,34 +840,7 @@ Common::Error AdlEngine::saveGameState(int slot, const Common::String &desc) { outFile->writeUint32BE(playTime); _display->saveThumbnail(*outFile); - - outFile->writeByte(_state.room); - outFile->writeByte(_state.moves); - outFile->writeByte(_state.isDark); - outFile->writeByte(_state.time.hours); - outFile->writeByte(_state.time.minutes); - - outFile->writeUint32BE(_state.rooms.size()); - for (uint i = 0; i < _state.rooms.size(); ++i) { - outFile->writeByte(_state.rooms[i].picture); - outFile->writeByte(_state.rooms[i].curPicture); - outFile->writeByte(_state.rooms[i].isFirstTime); - } - - outFile->writeUint32BE(_state.items.size()); - Common::List<Item>::const_iterator item; - for (item = _state.items.begin(); item != _state.items.end(); ++item) { - outFile->writeByte(item->room); - outFile->writeByte(item->picture); - outFile->writeByte(item->position.x); - outFile->writeByte(item->position.y); - outFile->writeByte(item->state); - } - - outFile->writeUint32BE(_state.vars.size()); - for (uint i = 0; i < _state.vars.size(); ++i) - outFile->writeByte(_state.vars[i]); - + saveState(*outFile); outFile->finalize(); if (outFile->err()) { @@ -1073,8 +1089,7 @@ int AdlEngine::o1_moveItem(ScriptEnv &e) { int AdlEngine::o1_setRoom(ScriptEnv &e) { OP_DEBUG_1("\tROOM = %d", e.arg(1)); - getCurRoom().curPicture = getCurRoom().picture; - _state.room = e.arg(1); + switchRoom(e.arg(1)); return 1; } @@ -1228,8 +1243,8 @@ bool AdlEngine::matchCommand(ScriptEnv &env) const { return false; if (DebugMan.isDebugChannelEnabled(kDebugChannelScript)) { - op_debug("IF\n\tROOM == %s", roomStr(env.getCommand().room).c_str()); - op_debug("\t&& SAID(%s, %s)", verbStr(env.getCommand().verb).c_str(), nounStr(env.getCommand().noun).c_str()); + (void)op_debug("IF\n\tROOM == %s", roomStr(env.getCommand().room).c_str()); + (void)op_debug("\t&& SAID(%s, %s)", verbStr(env.getCommand().verb).c_str(), nounStr(env.getCommand().noun).c_str()); } for (uint i = 0; i < env.getCondCount(); ++i) { @@ -1242,7 +1257,7 @@ bool AdlEngine::matchCommand(ScriptEnv &env) const { if (numArgs < 0) { if (DebugMan.isDebugChannelEnabled(kDebugChannelScript)) - op_debug("FAIL\n"); + (void)op_debug("FAIL\n"); return false; } @@ -1254,7 +1269,7 @@ bool AdlEngine::matchCommand(ScriptEnv &env) const { void AdlEngine::doActions(ScriptEnv &env) { if (DebugMan.isDebugChannelEnabled(kDebugChannelScript)) - op_debug("THEN"); + (void)op_debug("THEN"); for (uint i = 0; i < env.getActCount(); ++i) { byte op = env.op(); @@ -1266,7 +1281,7 @@ void AdlEngine::doActions(ScriptEnv &env) { if (numArgs < 0) { if (DebugMan.isDebugChannelEnabled(kDebugChannelScript)) - op_debug("ABORT\n"); + (void)op_debug("ABORT\n"); return; } @@ -1274,7 +1289,7 @@ void AdlEngine::doActions(ScriptEnv &env) { } if (DebugMan.isDebugChannelEnabled(kDebugChannelScript)) - op_debug("END\n"); + (void)op_debug("END\n"); } bool AdlEngine::doOneCommand(const Commands &commands, byte verb, byte noun) { |