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(); }
void KyraEngine_v1::checkAutosave() { if (shouldPerformAutoSave(_lastAutosave)) { saveGameStateIntern(999, "Autosave", 0); _lastAutosave = _system->getMillis(); } }
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; }
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; }
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; }
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; }
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; }