Example #1
0
Common::Error SciEngine::loadGameState(int slot) {
	Common::String fileName = Common::String::format("%s.%03d", _targetName.c_str(), slot);
	Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
	Common::SeekableReadStream *in = saveFileMan->openForLoading(fileName);

	if (in) {
		// found a savegame file
		gamestate_restore(_gamestate, in);
		delete in;
	}

	if (_gamestate->r_acc != make_reg(0, 1)) {
		return Common::kNoError;
	} else {
		warning("Restoring gamestate '%s' failed", fileName.c_str());
		return Common::kUnknownError;
	}
}
Example #2
0
reg_t kRestoreGame(EngineState *s, int funct_nr, int argc, reg_t *argv) {
	char *game_id = kernel_dereference_char_pointer(s, argv[0], 0);
	int savedir_nr = argv[1].toUint16();

	debug(3, "kRestoreGame(%s,%d)", game_id, savedir_nr);

	Common::Array<SavegameDesc> saves;
	listSavegames(saves);

	savedir_nr = saves[savedir_nr].id;

	if (savedir_nr > -1) {
		Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
		Common::String filename = ((Sci::SciEngine*)g_engine)->getSavegameName(savedir_nr);
		Common::SeekableReadStream *in;
		if ((in = saveFileMan->openForLoading(filename))) {
			// found a savegame file

			EngineState *newstate = gamestate_restore(s, in);
			delete in;

			if (newstate) {
				s->successor = newstate;
				script_abort_flag = 2; // Abort current game with replay
				shrink_execution_stack(s, s->execution_stack_base + 1);
			} else {
				s->r_acc = make_reg(0, 1);
				warning("Restoring failed (game_id = '%s')", game_id);
			}
			return s->r_acc;
		}
	}

	s->r_acc = make_reg(0, 1);
	warning("Savegame #%d not found", savedir_nr);

	return s->r_acc;
}
Example #3
0
reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) {
	Common::String game_id = !argv[0].isNull() ? s->_segMan->getString(argv[0]) : "";
	int16 savegameId = argv[1].toSint16();
	bool pausedMusic = false;

	debug(3, "kRestoreGame(%s,%d)", game_id.c_str(), savegameId);

	if (argv[0].isNull()) {
		// Direct call, either from launcher or from a patched Game::restore
		if (savegameId == -1) {
			// we are supposed to show a dialog for the user and let him choose a saved game
			g_sci->_soundCmd->pauseAll(true); // pause music
			GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
			savegameId = dialog->runModalWithCurrentTarget();
			delete dialog;
			if (savegameId < 0) {
				g_sci->_soundCmd->pauseAll(false); // unpause music
				return s->r_acc;
			}
			pausedMusic = true;
		}
		// don't adjust ID of the saved game, it's already correct
	} else {
		if (argv[2].isNull())
			error("kRestoreGame: called with parameter 2 being NULL");
		// Real call from script, we need to adjust ID
		if ((savegameId < SAVEGAMEID_OFFICIALRANGE_START) || (savegameId > SAVEGAMEID_OFFICIALRANGE_END)) {
			warning("Savegame ID %d is not allowed", savegameId);
			return TRUE_REG;
		}
		savegameId -= SAVEGAMEID_OFFICIALRANGE_START;
	}

	s->r_acc = NULL_REG; // signals success

	Common::Array<SavegameDesc> saves;
	listSavegames(saves);
	if (findSavegame(saves, savegameId) == -1) {
		s->r_acc = TRUE_REG;
		warning("Savegame ID %d not found", savegameId);
	} else {
		Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager();
		Common::String filename = g_sci->getSavegameName(savegameId);
		Common::SeekableReadStream *in;

		in = saveFileMan->openForLoading(filename);
		if (in) {
			// found a savegame file

			gamestate_restore(s, in);
			delete in;

			if (g_sci->getGameId() == GID_MOTHERGOOSE256) {
				// WORKAROUND: Mother Goose SCI1/SCI1.1 does some weird things for
				//  saving a previously restored game.
				// We set the current savedgame-id directly and remove the script
				//  code concerning this via script patch.
				s->variables[VAR_GLOBAL][0xB3].setOffset(SAVEGAMEID_OFFICIALRANGE_START + savegameId);
			}
		} else {
			s->r_acc = TRUE_REG;
			warning("Savegame #%d not found", savegameId);
		}
	}

	if (!s->r_acc.isNull()) {
		// no success?
		if (pausedMusic)
			g_sci->_soundCmd->pauseAll(false); // unpause music
	}

	return s->r_acc;
}
Example #4
0
bool GuestAdditions::restoreFromLauncher() const {
	assert(_state->_delayedRestoreGameId != -1);

#ifdef ENABLE_SCI32
	if (getSciVersion() >= SCI_VERSION_2) {
		if (_restoring) {
			// Recursion will occur if a restore fails, as
			// _delayedRestoreGameId will not be reset so the kernel will try
			// to keep restoring forever
			_state->_delayedRestoreGameId = -1;
			_restoring = false;
			return false;
		}

		// Delayed restore should not happen until after the benchmarking room.
		// In particular, in SQ6, delayed restore must not happen until room 100
		// (the Sierra logo & main menu room), otherwise the game scripts will
		// try to make calls to the subtitles ScrollWindow, which does not
		// exist. In other games, restoring early either breaks benchmarking,
		// or, when trying to load an invalid save game, makes the dialog
		// telling the user that the game is invalid impossible to read
		if (strcmp(_segMan->getObjectName(_state->variables[VAR_GLOBAL][kGlobalVarCurrentRoom]), "speedRoom") == 0) {
			return false;
		}

		_restoring = true;

		if (g_sci->getGameId() == GID_SHIVERS) {
			// Shivers accepts the save game number as a parameter to
			// `SHIVERS::restore`
			reg_t args[] = { make_reg(0, _state->_delayedRestoreGameId - kSaveIdShift) };
			invokeSelector(g_sci->getGameObject(), SELECTOR(restore), 1, args);
		} else {
			// When `Game::restore` is invoked, it will call to `Restore::doit`
			// which will automatically return the `_delayedRestoreGameId` instead
			// of prompting the user for a save game
			invokeSelector(g_sci->getGameObject(), SELECTOR(restore));
		}

		_restoring = false;

		return true;
	} else {
#else
	{
#endif
		int savegameId = _state->_delayedRestoreGameId; // delayedRestoreGameId gets destroyed within gamestate_restore()!
		Common::String fileName = g_sci->getSavegameName(savegameId);
		Common::SeekableReadStream *in = g_sci->getSaveFileManager()->openForLoading(fileName);

		if (in) {
			// found a savegame file
			gamestate_restore(_state, in);
			delete in;
			if (_state->r_acc != make_reg(0, 1)) {
				gamestate_afterRestoreFixUp(_state, savegameId);
				return true;
			}
		}

		error("Restoring gamestate '%s' failed", fileName.c_str());
	}
}

#pragma mark -
#pragma mark Message type sync

void GuestAdditions::syncMessageTypeFromScummVM() const {
	switch (_features->getMessageTypeSyncStrategy()) {
	case kMessageTypeSyncStrategyDefault:
		syncMessageTypeFromScummVMUsingDefaultStrategy();
		break;

#ifdef ENABLE_SCI32
	case kMessageTypeSyncStrategyShivers:
		syncMessageTypeFromScummVMUsingShiversStrategy();
		break;

	case kMessageTypeSyncStrategyLSL6Hires:
		syncMessageTypeFromScummVMUsingLSL6HiresStrategy();
		break;
#endif
	case kMessageTypeSyncStrategyNone:
		break;
	}
}

void GuestAdditions::syncMessageTypeFromScummVMUsingDefaultStrategy() const {
	uint8 value = 0;
	if (ConfMan.getBool("subtitles")) {
		value |= kMessageTypeSubtitles;
	}
	if (!ConfMan.getBool(("speech_mute"))) {
		value |= kMessageTypeSpeech;
	}

	if (value == kMessageTypeSubtitles + kMessageTypeSpeech && !_features->supportsSpeechWithSubtitles()) {
		value &= ~kMessageTypeSubtitles;
	}

	if (value) {
		_state->variables[VAR_GLOBAL][kGlobalVarMessageType] = make_reg(0, value);
	}

	if (g_sci->getGameId() == GID_GK1) {
		if (value == kMessageTypeSubtitles) {
			_state->variables[VAR_GLOBAL][kGlobalVarGK1NarratorMode] = NULL_REG;
		} else if (value == kMessageTypeSpeech) {
			_state->variables[VAR_GLOBAL][kGlobalVarGK1NarratorMode] = TRUE_REG;
		}
	}
}