Exemple #1
0
void QueenEngine::update(bool checkPlayerInput) {
	_debugger->onFrame();

	_graphics->update(_logic->currentRoom());
	_logic->update();

	int frameDelay = (_lastUpdateTime + Input::DELAY_NORMAL - _system->getMillis());
	if (frameDelay <= 0) {
		frameDelay = 1;
	}
	_input->delay(frameDelay);
	_lastUpdateTime = _system->getMillis();

	if (!_resource->isInterview()) {
		_display->palCustomScroll(_logic->currentRoom());
	}
	BobSlot *joe = _graphics->bob(0);
	_display->update(joe->active, joe->x, joe->y);

	_input->checkKeys();
	if (_input->debugger()) {
		_input->debuggerReset();
		_debugger->attach();
	}
	if (canLoadOrSave()) {
		if (_input->quickSave()) {
			_input->quickSaveReset();
			saveGameState(SLOT_QUICKSAVE, "Quicksave");
		}
		if (_input->quickLoad()) {
			_input->quickLoadReset();
			loadGameState(SLOT_QUICKSAVE);
		}
		if (shouldPerformAutoSave(_lastSaveTime)) {
			saveGameState(SLOT_AUTOSAVE, "Autosave");
			_lastSaveTime = _system->getMillis();
		}
	}
	if (!_input->cutawayRunning()) {
		if (checkPlayerInput) {
			_command->updatePlayer();
		}
		if (_input->idleTime() >= Input::DELAY_SCREEN_BLANKER) {
			_display->blankScreen();
		}
	}
	_sound->updateMusic();
}
Exemple #2
0
void KyraEngine_v1::checkAutosave() {
	if (shouldPerformAutoSave(_lastAutosave)) {
		saveGameStateIntern(999, "Autosave", 0);
		_lastAutosave = _system->getMillis();
	}
}
Exemple #3
0
Common::Error ZVision::run() {
	initialize();

	// Check if a saved game is to be loaded from the launcher
	if (ConfMan.hasKey("save_slot"))
		_saveManager->loadGame(ConfMan.getInt("save_slot"));

	bool foundAllFonts = true;

	// Before starting, make absolutely sure that the user has copied the needed fonts
	for (int i = 0; i < FONT_COUNT; i++) {
		FontStyle curFont = getSystemFont(i);
		Common::String freeFontBoldItalic = Common::String("Bold") + curFont.freeFontItalicName;

		const char *fontSuffixes[4] = { "", "bd", "i", "bi" };
		const char *freeFontSuffixes[4] = { "", "Bold", curFont.freeFontItalicName, freeFontBoldItalic.c_str() };
		const char *liberationFontSuffixes[4] = { "-Regular", "-Bold", "-Italic", "-BoldItalic" };

		for (int j = 0; j < 4; j++) {
			Common::String fontName = curFont.fontBase;
			if (fontName == "censcbk" && j > 0)
				fontName = "schlbk";
			fontName += fontSuffixes[j];
			fontName += ".ttf";

			if (fontName == "schlbkbd.ttf")
				fontName = "schlbkb.ttf";
			if (fontName == "garabi.ttf")
				continue;
			if (fontName == "garai.ttf")
				fontName = "garait.ttf";

			Common::String freeFontName = curFont.freeFontBase;
			freeFontName += freeFontSuffixes[j];
			freeFontName += ".ttf";

			Common::String liberationFontName = curFont.liberationFontBase;
			liberationFontName += liberationFontSuffixes[j];
			liberationFontName += ".ttf";

			if (!Common::File::exists(fontName) && !_searchManager->hasFile(fontName) &&
				!Common::File::exists(liberationFontName) && !_searchManager->hasFile(liberationFontName) &&
				!Common::File::exists(freeFontName) && !_searchManager->hasFile(freeFontName)) {
				foundAllFonts = false;
				break;
			}
		}

		if (!foundAllFonts)
			break;
	}

	if (!foundAllFonts) {
		GUI::MessageDialog dialog(
				"Before playing this game, you'll need to copy the required "
				"fonts into ScummVM's extras directory, or into the game directory. "
				"On Windows, you'll need the following font files from the Windows "
				"font directory: Times New Roman, Century Schoolbook, Garamond, "
				"Courier New and Arial. Alternatively, you can download the "
				"Liberation Fonts or the GNU FreeFont package. You'll need all the "
				"fonts from the font package you choose, i.e., LiberationMono, "
				"LiberationSans and LiberationSerif, or FreeMono, FreeSans and "
				"FreeSerif respectively."
		);
		dialog.runModal();
		quitGame();
		return Common::kUnknownError;
	}

	// Main loop
	while (!shouldQuit()) {
		_clock.update();
		uint32 currentTime = _clock.getLastMeasuredTime();
		uint32 deltaTime = _clock.getDeltaTime();

		_cursorManager->setItemID(_scriptManager->getStateValue(StateKey_InventoryItem));

		processEvents();
		_renderManager->updateRotation();

		_scriptManager->update(deltaTime);
		_menu->process(deltaTime);

		// Render the backBuffer to the screen
		_renderManager->prepareBackground();
		_renderManager->renderMenuToScreen();
		_renderManager->processSubs(deltaTime);
		_renderManager->renderSceneToScreen();

		// Update the screen
		if (canRender()) {
			_system->updateScreen();
			_renderedFrameCount++;
		} else {
			_frameRenderDelay--;
		}

		// Calculate the frame delay based off a desired frame time
		int delay = _desiredFrameTime - int32(_system->getMillis() - currentTime);
		// Ensure non-negative
		delay = delay < 0 ? 0 : delay;

		if (_doubleFPS) {
			delay >>= 1;
		}

		if (canSaveGameStateCurrently() && shouldPerformAutoSave(_saveManager->getLastSaveTime())) {
			_saveManager->autoSave();
		}

		_system->delayMillis(delay);
	}

	return Common::kNoError;
}
Exemple #4
0
Common::Error SkyEngine::go() {
	_keyPressed.reset();

	uint16 result = 0;
	if (ConfMan.hasKey("save_slot")) {
		int saveSlot = ConfMan.getInt("save_slot");
		if (saveSlot >= 0 && saveSlot <= 999)
			result = _skyControl->quickXRestore(ConfMan.getInt("save_slot"));
	}

	if (result != GAME_RESTORED) {
		bool introSkipped = false;
		if (_systemVars.gameVersion > 272) { // don't do intro for floppydemos
			Intro *skyIntro = new Intro(_skyDisk, _skyScreen, _skyMusic, _skySound, _skyText, _mixer, _system);
			bool floppyIntro = ConfMan.getBool("alt_intro");
			introSkipped = !skyIntro->doIntro(floppyIntro);
			delete skyIntro;
		}

		if (!shouldQuit()) {
			_skyLogic->initScreen0();
			if (introSkipped)
				_skyControl->restartGame();
		}
	}

	_lastSaveTime = _system->getMillis();

	uint32 delayCount = _system->getMillis();
	while (!shouldQuit()) {
		_debugger->onFrame();

		if (shouldPerformAutoSave(_lastSaveTime)) {
			if (_skyControl->loadSaveAllowed()) {
				_lastSaveTime = _system->getMillis();
				_skyControl->doAutoSave();
			} else
				_lastSaveTime += 30 * 1000; // try again in 30 secs
		}
		_skySound->checkFxQueue();
		_skyMouse->mouseEngine();
		handleKey();
		if (_systemVars.paused) {
			do {
				_system->updateScreen();
				delay(50);
				handleKey();
			} while (_systemVars.paused);
			delayCount = _system->getMillis();
		}

		_skyLogic->engine();
		_skyScreen->processSequence();
		_skyScreen->recreate();
		_skyScreen->spriteEngine();
		if (_debugger->showGrid()) {
			uint8 *grid = _skyLogic->_skyGrid->giveGrid(Logic::_scriptVariables[SCREEN]);
			if (grid) {
				_skyScreen->showGrid(grid);
				_skyScreen->forceRefresh();
			}
		}
		_skyScreen->flip();

		if (_fastMode & 2)
			delay(0);
		else if (_fastMode & 1)
			delay(10);
		else {
			delayCount += _systemVars.gameSpeed;
			int needDelay = delayCount - (int)_system->getMillis();
			if ((needDelay < 0) || (needDelay > _systemVars.gameSpeed)) {
				needDelay = 0;
				delayCount = _system->getMillis();
			}
			delay(needDelay);
		}
	}

	_skyControl->showGameQuitMsg();
	_skyMusic->stopMusic();
	ConfMan.flushToDisk();
	delay(1500);
	return Common::kNoError;
}
Exemple #5
0
int AgiEngine::playGame() {
	int ec = errOK;

	debugC(2, kDebugLevelMain, "initializing...");
	debugC(2, kDebugLevelMain, "game version = 0x%x", getVersion());

	_sound->stopSound();
	_gfx->clearScreen(0);

	_game.horizon = HORIZON;
	_game.playerControl = false;

	setflag(fLogicZeroFirsttime, true);	// not in 2.917
	setflag(fNewRoomExec, true);	// needed for MUMG and SQ2!
	setflag(fSoundOn, true);	// enable sound
	setvar(vTimeDelay, 2);	// "normal" speed

	_game.gfxMode = true;
	_game.clockEnabled = true;
	_game.lineUserInput = 22;

	// We run AGIMOUSE always as a side effect
	if (getFeatures() & GF_AGIMOUSE || true)
		debug(1, "Using AGI Mouse 1.0 protocol");

	if (getFeatures() & GF_AGIPAL)
		debug(1, "Running AGIPAL game");

	debug(0, "Running AGI script.\n");

	setflag(fEnteredCli, false);
	setflag(fSaidAcceptedInput, false);
	_game.vars[vWordNotFound] = 0;
	_game.vars[vKey] = 0;

	debugC(2, kDebugLevelMain, "Entering main loop");
	bool firstLoop = !getflag(fRestartGame); // Do not restore on game restart

	do {

		if (!mainCycle())
			continue;

		if (getvar(vTimeDelay) == 0 || (1 + _clockCount) % getvar(vTimeDelay) == 0) {
			if (!_game.hasPrompt && _game.inputMode == INPUT_NORMAL) {
				writePrompt();
				_game.hasPrompt = 1;
			} else if (_game.hasPrompt && _game.inputMode == INPUT_NONE) {
				writePrompt();
				_game.hasPrompt = 0;
			}

			interpretCycle();

			// Check if the user has asked to load a game from the command line
			// or the launcher
			if (firstLoop) {
				checkQuickLoad();
				firstLoop = false;
			}

			setflag(fEnteredCli, false);
			setflag(fSaidAcceptedInput, false);
			_game.vars[vWordNotFound] = 0;
			_game.vars[vKey] = 0;
		}

		if (shouldPerformAutoSave(_lastSaveTime)) {
			saveGame(getSavegameFilename(0), "Autosave");
		}

	} while (!(shouldQuit() || _restartGame));

	_sound->stopSound();

	return ec;
}
Exemple #6
0
int AgiEngine::playGame() {
	int ec = errOK;
	const AgiAppleIIgsDelayOverwriteGameEntry *appleIIgsDelayOverwrite = nullptr;
	const AgiAppleIIgsDelayOverwriteRoomEntry *appleIIgsDelayRoomOverwrite = nullptr;

	debugC(2, kDebugLevelMain, "initializing...");
	debugC(2, kDebugLevelMain, "game version = 0x%x", getVersion());

	_sound->stopSound();

	// We need to do this accurately and reset the AGI priorityscreen to 4
	// otherwise at least the fan game Nick's Quest will go into an endless
	// loop, because the game draws views before it draws the first background picture.
	// For further study see bug #3451122
	_gfx->clear(0, 4);

	_game.horizon = 36;
	_game.playerControl = false;

	setFlag(VM_FLAG_LOGIC_ZERO_FIRST_TIME, true); // not in 2.917
	setFlag(VM_FLAG_NEW_ROOM_EXEC, true);         // needed for MUMG and SQ2!
	setFlag(VM_FLAG_SOUND_ON, true);              // enable sound
	// do not set VM_VAR_TIME_DELAY, original AGI did not do it (in the data segment it was simply set to 0)

	_game.gfxMode = true;
	_text->promptRow_Set(22);

	// We run AGIMOUSE always as a side effect
	//if (getFeatures() & GF_AGIMOUSE)
		debug(1, "Using AGI Mouse 1.0 protocol");

	if (getFeatures() & GF_AGIPAL)
		debug(1, "Running AGIPAL game");

	debug(0, "Running AGI script.\n");

	setFlag(VM_FLAG_ENTERED_CLI, false);
	setFlag(VM_FLAG_SAID_ACCEPTED_INPUT, false);
	setVar(VM_VAR_WORD_NOT_FOUND, 0);
	setVar(VM_VAR_KEY, 0);

	debugC(2, kDebugLevelMain, "Entering main loop");
	bool firstLoop = !getFlag(VM_FLAG_RESTART_GAME); // Do not restore on game restart

	if (firstLoop) {
		if (ConfMan.hasKey("save_slot")) {
			// quick restore enabled
			_game.automaticRestoreGame = true;
		}
	}

	artificialDelay_Reset();

	if (getPlatform() == Common::kPlatformApple2GS) {
		// Look up, if there is a time delay overwrite table for the current game
		appleIIgsDelayOverwrite = appleIIgsDelayOverwriteGameTable;
		while (appleIIgsDelayOverwrite->gameId != GID_AGIDEMO) {
			if (appleIIgsDelayOverwrite->gameId == getGameID())
				break; // game found
			appleIIgsDelayOverwrite++;
		}		
	}

	do {
		processAGIEvents();

		inGameTimerUpdate();

		uint16 timeDelay = getVar(VM_VAR_TIME_DELAY);

		if (getPlatform() == Common::kPlatformApple2GS) {
			timeDelay++;
			// It seems that either Apple IIgs ran very slowly or that the delay in its interpreter was not working as everywhere else
			// Most games on that platform set the delay to 0, which means no delay in DOS
			// Gold Rush! even "optimizes" itself when larger sprites are on the screen it sets TIME_DELAY to 0.
			// Normally that game runs at TIME_DELAY 1.
			// Maybe a script patch for this game would make sense.
			// TODO: needs further investigation

			int16 timeDelayOverwrite = -99;

			// Now check, if we got a time delay overwrite entry for current room
			if (appleIIgsDelayOverwrite->roomTable) {
				byte curRoom = getVar(VM_VAR_CURRENT_ROOM);

				appleIIgsDelayRoomOverwrite = appleIIgsDelayOverwrite->roomTable;
				while (appleIIgsDelayRoomOverwrite->fromRoom >= 0) {
					if ((appleIIgsDelayRoomOverwrite->fromRoom <= curRoom) && (appleIIgsDelayRoomOverwrite->toRoom >= curRoom)) {
						if (appleIIgsDelayRoomOverwrite->onlyWhenPlayerNotInControl) {
							if (_game.playerControl) {
								// Player is actually currently in control? -> then skip this entry
								appleIIgsDelayRoomOverwrite++;
								continue;
							}
						}
						timeDelayOverwrite = appleIIgsDelayRoomOverwrite->timeDelayOverwrite;
						break;
					}
					appleIIgsDelayRoomOverwrite++;
				}

				if (timeDelayOverwrite == -99) {
					// use default time delay in case no room specific one was found
					timeDelayOverwrite = appleIIgsDelayOverwrite->defaultTimeDelayOverwrite;
				}
			} else {
				timeDelayOverwrite = appleIIgsDelayOverwrite->defaultTimeDelayOverwrite;
			}

			if (timeDelayOverwrite >= 0) {
				if (timeDelayOverwrite != timeDelay) {
					// delayOverwrite is not the same as the delay taken from the scripts? overwrite it
					warning("AppleIIgs: time delay overwrite from %d to %d", timeDelay, timeDelayOverwrite);

					setVar(VM_VAR_TIME_DELAY, timeDelayOverwrite - 1); // adjust for Apple IIgs
					timeDelay = timeDelayOverwrite;
				}
			}
		}

		if (_passedPlayTimeCycles >= timeDelay) {
			inGameTimerResetPassedCycles();

			interpretCycle();

			// Check if the user has asked to load a game from the command line
			// or the launcher
			if (_game.automaticRestoreGame) {
				_game.automaticRestoreGame = false;
				checkQuickLoad();
			}

			setFlag(VM_FLAG_ENTERED_CLI, false);
			setFlag(VM_FLAG_SAID_ACCEPTED_INPUT, false);
			setVar(VM_VAR_WORD_NOT_FOUND, 0);
			setVar(VM_VAR_KEY, 0);
		}

		if (shouldPerformAutoSave(_lastSaveTime)) {
			saveGame(getSavegameFilename(0), "Autosave");
		}

	} while (!(shouldQuit() || _restartGame));

	_sound->stopSound();

	return ec;
}
Exemple #7
0
Common::Error ComposerEngine::run() {
	Common::Event event;

	_vars.resize(1000);
	for (uint i = 0; i < _vars.size(); i++)
		_vars[i] = 0;

	_queuedScripts.resize(10);
	for (uint i = 0; i < _queuedScripts.size(); i++) {
		_queuedScripts[i]._count = 0;
		_queuedScripts[i]._scriptId = 0;
	}

	if (!_bookIni.loadFromFile("book.ini")) {
		_directoriesToStrip = 0;
		if (!_bookIni.loadFromFile("programs/book.ini")) {
			// mac version?
			if (!_bookIni.loadFromFile("Darby the Dragon.ini"))
				if (!_bookIni.loadFromFile("Gregory.ini"))
					error("failed to find book.ini");
		}
	}

	uint width = 640;
	if (_bookIni.hasKey("Width", "Common"))
		width = atoi(getStringFromConfig("Common", "Width").c_str());
	uint height = 480;
	if (_bookIni.hasKey("Height", "Common"))
		height = atoi(getStringFromConfig("Common", "Height").c_str());
	initGraphics(width, height);
	_screen.create(width, height, Graphics::PixelFormat::createFormatCLUT8());

	Graphics::Cursor *cursor = Graphics::makeDefaultWinCursor();
	CursorMan.replaceCursor(cursor->getSurface(), cursor->getWidth(), cursor->getHeight(), cursor->getHotspotX(),
		cursor->getHotspotY(), cursor->getKeyColor());
	CursorMan.replaceCursorPalette(cursor->getPalette(), cursor->getPaletteStartIndex(), cursor->getPaletteCount());
	delete cursor;

	_console = new Console(this);

	loadLibrary(0);

	uint fps = atoi(getStringFromConfig("Common", "FPS").c_str());
	uint frameTime = 125; // Default to 125ms (1000/8)
	if (fps != 0)
		frameTime = 1000 / fps;
	else
		warning("FPS in book.ini is zero. Defaulting to 8...");
	uint32 lastDrawTime = 0;
	_lastSaveTime = _system->getMillis();

	bool loadFromLauncher = ConfMan.hasKey("save_slot");

	while (!shouldQuit()) {
		for (uint i = 0; i < _pendingPageChanges.size(); i++) {
			if (_pendingPageChanges[i]._remove)
				unloadLibrary(_pendingPageChanges[i]._pageId);
			else
				loadLibrary(_pendingPageChanges[i]._pageId);

			lastDrawTime = 0;
		}
		_pendingPageChanges.clear();

		uint32 thisTime = _system->getMillis();
		// maintain our own internal timing, since otherwise we get
		// confused when starved of CPU (for example when the user
		// is dragging the scummvm window around)
		if (thisTime > _lastTime + frameTime)
			_currentTime += frameTime;
		else
			_currentTime += thisTime - _lastTime;
		_lastTime = thisTime;

		for (uint i = 0; i < _queuedScripts.size(); i++) {
			QueuedScript &script = _queuedScripts[i];
			if (!script._count)
				continue;
			if (script._baseTime + script._duration > _currentTime)
				continue;
			if (script._count != 0xffffffff)
				script._count--;
			script._baseTime = _currentTime;
			runScript(script._scriptId, i, 0, 0);
		}

		if (lastDrawTime + frameTime <= thisTime) {
			// catch up if we're more than 2 frames behind
			if (lastDrawTime + (frameTime * 2) <= thisTime)
				lastDrawTime = thisTime;
			else
				lastDrawTime += frameTime;

			tickOldScripts();

			redraw();

			processAnimFrame();
		} else if (_needsUpdate) {
			redraw();
		}
		if (loadFromLauncher) {
			loadGameState(ConfMan.getInt("save_slot"));
			loadFromLauncher = false;
		}
		if (shouldPerformAutoSave(_lastSaveTime))
			saveGameState(0, "Autosave");
		while (_eventMan->pollEvent(event)) {
			switch (event.type) {
			case Common::EVENT_LBUTTONDOWN:
				onMouseDown(event.mouse);
				break;

			case Common::EVENT_LBUTTONUP:
				break;

			case Common::EVENT_RBUTTONDOWN:
				break;

			case Common::EVENT_MOUSEMOVE:
				onMouseMove(event.mouse);
				break;

			case Common::EVENT_KEYDOWN:
				switch (event.kbd.keycode) {
				case Common::KEYCODE_d:
					if (event.kbd.hasFlags(Common::KBD_CTRL)) {
						// Start the debugger
						getDebugger()->attach();
						getDebugger()->onFrame();
					}
					break;

				case Common::KEYCODE_q:
					if (event.kbd.hasFlags(Common::KBD_CTRL))
						quitGame();
					break;

				default:
					break;
				}

				onKeyDown(event.kbd.keycode);
				break;

			default:
				break;
			}
		}

		_system->delayMillis(20);
	}

	_screen.free();

	return Common::kNoError;
}