Пример #1
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;
}
Пример #2
0
void ScummEngine::parseEvent(Common::Event event) {
	switch (event.type) {
	case Common::EVENT_KEYDOWN:
		if (event.kbd.keycode >= Common::KEYCODE_0 && event.kbd.keycode <= Common::KEYCODE_9 &&
			((event.kbd.hasFlags(Common::KBD_ALT) && canSaveGameStateCurrently()) ||
			(event.kbd.hasFlags(Common::KBD_CTRL) && canLoadGameStateCurrently()))) {
			_saveLoadSlot = event.kbd.keycode - Common::KEYCODE_0;

			//  don't overwrite autosave (slot 0)
			if (_saveLoadSlot == 0)
				_saveLoadSlot = 10;

			_saveLoadDescription = Common::String::format("Quicksave %d", _saveLoadSlot);
			_saveLoadFlag = (event.kbd.hasFlags(Common::KBD_ALT)) ? 1 : 2;
			_saveTemporaryState = false;
		} else if (event.kbd.hasFlags(Common::KBD_CTRL) && event.kbd.keycode == Common::KEYCODE_f) {
			_fastMode ^= 1;
		} else if (event.kbd.hasFlags(Common::KBD_CTRL) && event.kbd.keycode == Common::KEYCODE_g) {
			_fastMode ^= 2;
		} else if ((event.kbd.hasFlags(Common::KBD_CTRL) && event.kbd.keycode == Common::KEYCODE_d)
		        || event.kbd.ascii == '~' || event.kbd.ascii == '#') {
			_debugger->attach();
		} else if (event.kbd.hasFlags(Common::KBD_CTRL) && event.kbd.keycode == Common::KEYCODE_s) {
			_res->resourceStats();
		} else {
			// Normal key press, pass on to the game.
			_keyPressed = event.kbd;
		}

		// FIXME: We are using ASCII values to index the _keyDownMap here,
		// yet later one code which checks _keyDownMap will use KEYCODEs
		// to do so. That is, we are mixing ascii and keycode values here,
		// which is bad. We probably should be only using keycodes, but at
		// least INSANE checks for "Shift-V" by looking for the 'V' key
		// being pressed. It would be easy to solve that by also storing
		// the modifier flags. However, since getKeyState() is also called
		// by scripts, we have to be careful with semantic changes.
		if (_keyPressed.ascii >= 512)
			debugC(DEBUG_GENERAL, "_keyPressed > 512 (%d)", _keyPressed.ascii);
		else
			_keyDownMap[_keyPressed.ascii] = true;
		break;

	case Common::EVENT_KEYUP:
		if (event.kbd.ascii >= 512) {
			debugC(DEBUG_GENERAL, "keyPressed > 512 (%d)", event.kbd.ascii);
		} else {
			_keyDownMap[event.kbd.ascii] = false;

			// Due to some weird bug with capslock key pressed
			// generated keydown event is for lower letter but
			// keyup is for upper letter
			// On most (all?) keyboards it is safe to assume that
			// both upper and lower letters are unpressed on keyup event
			//
			// Fixes bug #1709430: "FT: CAPSLOCK + V enables cheating for all fights"
			//
			// Fingolfin remarks: This wouldn't be a problem if we used keycodes.
			_keyDownMap[toupper(event.kbd.ascii)] = false;
		}
		break;


	// We update the mouse position whenever the mouse moves or a click occurs.
	// The latter is done to accomodate systems with a touchpad / pen controller.
	case Common::EVENT_LBUTTONDOWN:
	case Common::EVENT_RBUTTONDOWN:
	case Common::EVENT_MOUSEMOVE:
		if (event.type == Common::EVENT_LBUTTONDOWN)
			_leftBtnPressed |= msClicked|msDown;
		else if (event.type == Common::EVENT_RBUTTONDOWN)
			_rightBtnPressed |= msClicked|msDown;
		_mouse.x = event.mouse.x;
		_mouse.y = event.mouse.y;

		if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
			_mouse.x -= (kHercWidth - _screenWidth * 2) / 2;
			_mouse.x >>= 1;
			_mouse.y = _mouse.y * 4 / 7;
		} else if (_useCJKMode && _textSurfaceMultiplier == 2) {
Пример #3
0
void CGEEngine::runGame() {
	if (_quitFlag)
		return;

	loadHeroXY();

	_sceneLight->_flags._tran = true;
	_vga->_showQ->append(_sceneLight);
	_sceneLight->_flags._hide = false;

	const Seq pocSeq[] = {
		{ 0, 0, 0, 0, 20 },
		{ 1, 2, 0, 0,  4 },
		{ 2, 3, 0, 0,  4 },
		{ 3, 4, 0, 0, 16 },
		{ 2, 5, 0, 0,  4 },
		{ 1, 6, 0, 0,  4 },
		{ 0, 1, 0, 0, 16 },
	};
	Seq *seq = (Seq *)malloc(7 * sizeof(Seq));
	Common::copy(pocSeq, pocSeq + 7, seq);
	_pocLight->setSeq(seq);

	_pocLight->_flags._tran = true;
	_pocLight->_time = 1;
	_pocLight->_z = 120;
	_vga->_showQ->append(_pocLight);
	selectPocket(-1);

	_vga->_showQ->append(_mouse);

	loadUser();

	if ((_sprite = _vga->_spareQ->locate(121)) != NULL)
		_commandHandlerTurbo->addCommand(kCmdSeq, -1, _vga->_mono, _sprite);
	if ((_sprite = _vga->_spareQ->locate(122)) != NULL)
		_sprite->step(_music);
	_commandHandlerTurbo->addCommand(kCmdSeq, -1, _music, _sprite);
	if (!_music)
		_midiPlayer->killMidi();

	if (_resman->exist("MINI.SPR")) {
		_miniShp = new BitmapPtr[2];
		_miniShp[0] = _miniShp[1] = NULL;

		loadSprite("MINI", -1, 0, kMiniX, kMiniY);
		expandSprite(_miniScene = _sprite);  // NULL is ok
		if (_miniScene) {
			_miniScene->_flags._kill = false;
			_miniScene->_flags._hide = true;
			_miniShp[0] = new Bitmap(this, *_miniScene->shp());
			_miniShpList = _miniScene->setShapeList(_miniShp);
			postMiniStep(-1);
		}
	}

	if (_hero) {
		expandSprite(_hero);
		_hero->gotoxy(_heroXY[_now - 1].x, _heroXY[_now - 1].y);
		if (_resman->exist("00SHADOW.SPR")) {
			loadSprite("00SHADOW", -1, 0, _hero->_x + 14, _hero->_y + 51);
			delete _shadow;
			if ((_shadow = _sprite) != NULL) {
				_shadow->_ref = 2;
				_shadow->_flags._tran = true;
				_shadow->_flags._kill = false;
				_hero->_flags._shad = true;
				_vga->_showQ->insert(_vga->_spareQ->remove(_shadow), _hero);
			}
		}
	}

	_infoLine->gotoxy(kInfoX, kInfoY);
	_infoLine->_flags._tran = true;
	_infoLine->update(NULL);
	_vga->_showQ->insert(_infoLine);

	_debugLine->_z = 126;
	_vga->_showQ->insert(_debugLine);

	if (_horzLine) {
		_horzLine->_y = kMapTop - (kMapTop > 0);
		_horzLine->_z = 126;
		_vga->_showQ->insert(_horzLine);
	}

	_mouse->_busy = _vga->_spareQ->locate(kBusyRef);
	if (_mouse->_busy)
		expandSprite(_mouse->_busy);

	_startupMode = 0;

	_commandHandler->addCommand(kCmdLevel, -1, _oldLev, &_sceneLight);
	_sceneLight->gotoxy(kSceneX + ((_now - 1) % kSceneNx) * kSceneDx + kSceneSX,
	                  kSceneY + ((_now - 1) / kSceneNx) * kSceneDy + kSceneSY);
	sceneUp();

	_keyboard->setClient(_sys);
	// main loop
	while (!_endGame && !_quitFlag) {
		if (_flag[3]) // Flag FINIS
			_commandHandler->addCallback(kCmdExec,  -1, 0, kQGame);
		mainLoop();
	}

	// If finishing game due to closing ScummVM window, explicitly save the game
	if (!_endGame && canSaveGameStateCurrently())
		qGame();

	_keyboard->setClient(NULL);
	_commandHandler->addCommand(kCmdClear, -1, 0, NULL);
	_commandHandlerTurbo->addCommand(kCmdClear, -1, 0, NULL);
	_mouse->off();
	_vga->_showQ->clear();
	_vga->_spareQ->clear();
	_hero = NULL;
	_shadow = NULL;
}
Пример #4
0
void StarkEngine::processEvents() {
	Common::Event e;
	while (g_system->getEventManager()->pollEvent(e)) {
		// Handle any buttons, keys and joystick operations

		if (isPaused()) {
			// Only pressing key P to resume the game is allowed when the game is paused
			if (e.type == Common::EVENT_KEYDOWN && e.kbd.keycode == Common::KEYCODE_p) {
				pauseEngine(false);
			}
			continue;
		} 

		if (e.type == Common::EVENT_KEYDOWN) {
			if (e.kbd.keycode == Common::KEYCODE_d) {
				if (e.kbd.flags & Common::KBD_CTRL) {
					_console->attach();
					_console->onFrame();
				}
			} else if (e.kbd.keycode == Common::KEYCODE_ESCAPE) {
				_userInterface->handleEscape();
			} else if ((e.kbd.keycode == Common::KEYCODE_RETURN
					|| e.kbd.keycode == Common::KEYCODE_KP_ENTER)) {
				if (e.kbd.hasFlags(Common::KBD_ALT)) {
					_gfx->toggleFullscreen();
				} else if (_userInterface->isInGameScreen()){
					_userInterface->selectFocusedDialogOption();
				}
			} else if (e.kbd.keycode == Common::KEYCODE_F1) {
				_userInterface->toggleScreen(Screen::kScreenDiaryIndex);
			} else if (e.kbd.keycode == Common::KEYCODE_F2) {
				if (_userInterface->isInSaveLoadMenuScreen() || canSaveGameStateCurrently()) {
					_userInterface->toggleScreen(Screen::kScreenSaveMenu);
				}
			} else if (e.kbd.keycode == Common::KEYCODE_F3) {
				_userInterface->toggleScreen(Screen::kScreenLoadMenu);
			} else if (e.kbd.keycode == Common::KEYCODE_F4) {
				_userInterface->toggleScreen(Screen::kScreenDialog);
			} else if (e.kbd.keycode == Common::KEYCODE_F5) {
				if (_diary->isEnabled()) {
					_userInterface->toggleScreen(Screen::kScreenDiaryPages);
				}
			} else if (e.kbd.keycode == Common::KEYCODE_F6) {
				_userInterface->toggleScreen(Screen::kScreenFMVMenu);
			} else if (e.kbd.keycode == Common::KEYCODE_F7) {
				_userInterface->toggleScreen(Screen::kScreenSettingsMenu);
			} else if (e.kbd.keycode == Common::KEYCODE_F8) {
				warning("TODO: Implement the screenshot saving to local game directory");
			} else if (e.kbd.keycode == Common::KEYCODE_F9) {
				if (_userInterface->isInGameScreen()) {
					_userInterface->requestToggleSubtitle();
				}
			} else if (e.kbd.keycode == Common::KEYCODE_F10) {
				if (_userInterface->isInGameScreen() || _userInterface->isInDiaryIndexScreen()) {
					if (_userInterface->confirm(GameMessage::kQuitGamePrompt)) {
						_userInterface->requestQuitToMainMenu();
					}
				}
			} else if (e.kbd.keycode == Common::KEYCODE_a) {
				if (_userInterface->isInGameScreen()) {
					_userInterface->cycleBackInventory();
				}
			} else if (e.kbd.keycode == Common::KEYCODE_s) {
				if (_userInterface->isInGameScreen()) {
					_userInterface->cycleForwardInventory();
				}
			} else if (e.kbd.keycode == Common::KEYCODE_i) {
				if (_userInterface->isInGameScreen()) {
					_userInterface->inventoryOpen(!_userInterface->isInventoryOpen());
				}
			} else if (e.kbd.keycode == Common::KEYCODE_x
					&& !e.kbd.hasFlags(Common::KBD_ALT)) {
				if (_userInterface->isInGameScreen()) {
					_userInterface->toggleExitDisplay();
				}
			} else if ((e.kbd.keycode == Common::KEYCODE_x
					|| e.kbd.keycode == Common::KEYCODE_q)
					&& e.kbd.hasFlags(Common::KBD_ALT)) {
				if (_userInterface->confirm(GameMessage::kQuitPrompt)) {
					_userInterface->notifyShouldExit();
				}
			} else if (e.kbd.keycode == Common::KEYCODE_p) {
				if (_userInterface->isInGameScreen()) {
					pauseEngine(true);
					debug("The game is paused");
				}
			} else if (e.kbd.keycode == Common::KEYCODE_PAGEUP) {
				if (_userInterface->isInGameScreen()) {
					if (_userInterface->isInventoryOpen()) {
						_userInterface->scrollInventoryUp();
					} else {
						_userInterface->scrollDialogUp();
					}
				}
			} else if (e.kbd.keycode == Common::KEYCODE_UP) {
				if (_userInterface->isInGameScreen()) {
					if (_userInterface->isInventoryOpen()) {
						_userInterface->scrollInventoryUp();
					} else {
						_userInterface->focusPrevDialogOption();
					}
				}
			} else if (e.kbd.keycode == Common::KEYCODE_PAGEDOWN) {
				if (_userInterface->isInGameScreen()) {
					if (_userInterface->isInventoryOpen()) {
						_userInterface->scrollInventoryDown();
					} else {
						_userInterface->scrollDialogDown();
					}
				}
			} else if (e.kbd.keycode == Common::KEYCODE_DOWN) {
				if (_userInterface->isInGameScreen()) {
					if (_userInterface->isInventoryOpen()) {
						_userInterface->scrollInventoryDown();
					} else {
						_userInterface->focusNextDialogOption();
					}
				}
			} else if (e.kbd.keycode >= Common::KEYCODE_1 && e.kbd.keycode <= Common::KEYCODE_9) {
				if (_userInterface->isInGameScreen()) {
					_userInterface->selectDialogOptionByIndex(e.kbd.keycode - Common::KEYCODE_1);
				}
			}

		} else if (e.type == Common::EVENT_LBUTTONUP) {
			_userInterface->handleMouseUp();
		} else if (e.type == Common::EVENT_MOUSEMOVE) {
			_userInterface->handleMouseMove(e.mouse);
		} else if (e.type == Common::EVENT_LBUTTONDOWN) {
			_userInterface->handleClick();
			if (_system->getMillis() - _lastClickTime < _doubleClickDelay) {
				_userInterface->handleDoubleClick();
			}
			_lastClickTime = _system->getMillis();
		} else if (e.type == Common::EVENT_RBUTTONDOWN) {
			_userInterface->handleRightClick();
		} else if (e.type == Common::EVENT_SCREEN_CHANGED) {
			_gfx->computeScreenViewport();
			_fontProvider->initFonts();
			_userInterface->onScreenChanged();
		}
	}
}