/** * Started up for scene script and entrance script. */ static void SceneTinselProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; INT_CONTEXT *pic; const TP_INIT *pInit; int myEscape; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); // The following myEscape value setting is used for enabling title screen skipping in DW1 if (TinselV1 && (sceneCtr == 1)) initialMyEscape = GetEscEvents(); _ctx->myEscape = (TinselV1 && (sceneCtr < 4)) ? initialMyEscape : 0; // get the stuff copied to process when it was created _ctx->pInit = (const TP_INIT *)param; assert(_ctx->pInit); assert(_ctx->pInit->hTinselCode); // Must have some code to run _ctx->pic = InitInterpretContext(GS_SCENE, READ_LE_UINT32(&_ctx->pInit->hTinselCode), TinselV2 ? _ctx->pInit->event : NOEVENT, NOPOLY, // No polygon 0, // No actor NULL, // No object _ctx->myEscape); CORO_INVOKE_1(Interpret, _ctx->pic); if (_ctx->pInit->event == CLOSEDOWN || _ctx->pInit->event == LEAVE_T2) bWatchingOut = false; CORO_END_CODE; }
static void ActorRestoredProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; INT_CONTEXT *pic; CORO_END_CONTEXT(_ctx); // get the stuff copied to process when it was created const RATP_INIT *r = (const RATP_INIT *)param; bool isSavegame = r->pic->resumeState == RES_SAVEGAME; CORO_BEGIN_CODE(_ctx); _ctx->pic = RestoreInterpretContext(r->pic); // The newly added check here specially sets the process to RES_NOT when loading a savegame. // This is needed particularly for the Psychiatrist scene in Discworld 1 - otherwise Rincewind // can't go upstairs without leaving the building and returning. If this patch causes problems // in other scenes, an added check for the hCode == 1174490602 could be added. if (isSavegame && TinselV1) _ctx->pic->resumeState = RES_NOT; CORO_INVOKE_1(Interpret, _ctx->pic); // If it gets here, actor's code has run to completion actorInfo[r->id - 1].completed = true; CORO_END_CODE; }
/** * Runs actor's glitter code. */ static void ActorTinselProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; INT_CONTEXT *pic; bool bTookControl; CORO_END_CONTEXT(_ctx); // get the stuff copied to process when it was created const ATP_INIT *atp = (const ATP_INIT *)param; CORO_BEGIN_CODE(_ctx); if (TinselV2) { // Take control for CONVERSE events if (atp->event == CONVERSE) { _ctx->bTookControl = GetControl(); HideConversation(true); } else _ctx->bTookControl = false; // Run the Glitter code CORO_INVOKE_1(Interpret, atp->pic); // Restore conv window if applicable if (atp->event == CONVERSE) { // Free control if we took it if (_ctx->bTookControl) ControlOn(); HideConversation(false); } } else { CORO_INVOKE_1(AllowDclick, atp->bev); // May kill us if single click // Run the Glitter code assert(actorInfo[atp->id - 1].actorCode); // no code to run _ctx->pic = InitInterpretContext(GS_ACTOR, actorInfo[atp->id - 1].actorCode, atp->event, NOPOLY, atp->id, NULL); CORO_INVOKE_1(Interpret, _ctx->pic); // If it gets here, actor's code has run to completion actorInfo[atp->id - 1].completed = true; } CORO_END_CODE; }
/** * Main process for playing the game. * * @remarks This needs to be in a separate process, since there are some things that can briefly * block the execution of process. For now, all ScummVm event handling is dispatched to within the context of this * process. If it ever proves a problem, we may have to look into whether it's feasible to have it still remain * in the outer 'main' process. */ void TonyEngine::playProcess(CORO_PARAM, const void *param) { CORO_BEGIN_CONTEXT; Common::String fn; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); // Game loop. We rely on the outer main process to detect if a shutdown is required, // and kill the scheudler and all the processes, including this one for (;;) { // If a savegame needs to be loaded, then do so if (g_vm->_loadSlotNumber != -1 && GLOBALS._gfxEngine != NULL) { _ctx->fn = getSaveStateFileName(g_vm->_loadSlotNumber); CORO_INVOKE_1(GLOBALS._gfxEngine->loadState, _ctx->fn); g_vm->_loadSlotNumber = -1; } // Wait for the next frame CORO_INVOKE_1(CoroScheduler.sleep, 50); // Call the engine to handle the next frame CORO_INVOKE_1(g_vm->_theEngine.doFrame, g_vm->_bDrawLocation); // Warns that a frame is finished CoroScheduler.pulseEvent(g_vm->_hEndOfFrame); // Handle drawing the frame if (!g_vm->_bPaused) { if (!g_vm->_theEngine._bWiping) g_vm->_window.getNewFrame(g_vm->_theEngine, NULL); else g_vm->_window.getNewFrame(g_vm->_theEngine, &g_vm->_theEngine._rcWipeEllipse); } // Paint the frame onto the screen g_vm->_window.repaint(); // Signal the ScummVM debugger g_vm->_debugger->onFrame(); } CORO_END_CODE; }
/** * Run the master script. * Continues between scenes, or until Interpret() returns. */ static void MasterScriptProcess(CORO_PARAM, const void *) { // COROUTINE CORO_BEGIN_CONTEXT; INT_CONTEXT *pic; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); _ctx->pic = InitInterpretContext(GS_MASTER, 0, NOEVENT, NOPOLY, 0, NULL); CORO_INVOKE_1(Interpret, _ctx->pic); CORO_END_CODE; }
void TonyEngine::loadState(CORO_PARAM, int n) { CORO_BEGIN_CONTEXT; Common::String buf; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); _ctx->buf = getSaveStateFileName(n); CORO_INVOKE_1(_theEngine.loadState, _ctx->buf.c_str()); CORO_END_CODE; }
void RMDialogChoice::doFrame(CORO_PARAM, RMPoint ptMousePos) { CORO_BEGIN_CONTEXT; int i; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); if (ptMousePos._y > _ptDrawPos._y) { for (_ctx->i = 0; _ctx->i < _numChoices; _ctx->i++) { if ((ptMousePos._y >= _ptDrawPos._y + _ptDrawStrings[_ctx->i]._y) && (ptMousePos._y < _ptDrawPos._y + _ptDrawStrings[_ctx->i]._y + _drawedStrings[_ctx->i].getDimy())) { CORO_INVOKE_1(setSelected, _ctx->i); break; } } if (_ctx->i == _numChoices) CORO_INVOKE_1(setSelected, -1); } CORO_END_CODE; }
/** * Process Tinsel Process */ static void ProcessTinselProcess(CORO_PARAM, const void *param) { const PINT_CONTEXT *pPic = (const PINT_CONTEXT *)param; CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); // get the stuff copied to process when it was created CORO_INVOKE_1(Interpret, *pPic); CORO_KILL_SELF(); CORO_END_CODE; }
/** * The code for for restored scene processes. */ static void RestoredProcessProcess(CORO_PARAM, const void *param) { CORO_BEGIN_CONTEXT; INT_CONTEXT *pic; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); // get the stuff copied to process when it was created _ctx->pic = *(const PINT_CONTEXT *)param; _ctx->pic = RestoreInterpretContext(_ctx->pic); AttachInterpret(_ctx->pic, g_scheduler->getCurrentProcess()); CORO_INVOKE_1(Interpret, _ctx->pic); CORO_END_CODE; }
static void ActorRestoredProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; INT_CONTEXT *pic; CORO_END_CONTEXT(_ctx); // get the stuff copied to process when it was created const RATP_INIT *r = (const RATP_INIT *)param; CORO_BEGIN_CODE(_ctx); _ctx->pic = RestoreInterpretContext(r->pic); CORO_INVOKE_1(Interpret, _ctx->pic); // If it gets here, actor's code has run to completion actorInfo[r->id - 1].completed = true; CORO_END_CODE; }
/** * Continually checks to see if active sounds have finished playing * Sets the event signalling the sound has ended */ void FPSfx::soundCheckProcess(CORO_PARAM, const void *param) { CORO_BEGIN_CONTEXT; Common::List<FPSfx *>::iterator i; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); for (;;) { // Check each active sound for (_ctx->i = g_vm->_activeSfx.begin(); _ctx->i != g_vm->_activeSfx.end(); ++_ctx->i) { FPSfx *sfx = *_ctx->i; if (sfx->endOfBuffer()) CoroScheduler.setEvent(sfx->_hEndOfBuffer); } // Delay until the next check is done CORO_INVOKE_1(CoroScheduler.sleep, 50); } CORO_END_CODE; }
static void RestoredProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; INT_CONTEXT *pic; bool bConverse; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); // get the stuff copied to process when it was created _ctx->pic = *((INT_CONTEXT * const *)param); _ctx->pic = RestoreInterpretContext(_ctx->pic); _ctx->bConverse = TinselV2 && (_ctx->pic->event == CONVERSE); CORO_INVOKE_1(Interpret, _ctx->pic); // Restore control after CallScene() from a conversation icon if (_ctx->bConverse) ControlOn(); CORO_END_CODE; }
void RMGfxEngine::doFrame(CORO_PARAM, bool bDrawLocation) { CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); // Poll of input devices _input.poll(); if (_bMustEnterMenu && GLOBALS._bIdleExited) { _bOption = true; _bMustEnterMenu = false; GLOBALS._bIdleExited = false; } if (_bOption) { CORO_INVOKE_1(_opt.doFrame, &_input); _bOption = !_opt.isClosing(); if (!_bOption) { disableMouse(); enableInput(); mpalStartIdlePoll(_nCurLoc); g_vm->pauseSound(false); } } if (bDrawLocation && _bLocationLoaded) { // Location and objects _loc.doFrame(&_bigBuf); // Check the mouse input if (_bInput && !_tony.inAction()) { // If we are on the inventory, it is it who controls all input if (_inv.haveFocus(_input.mousePos()) && !_inter.active()) { // Left Click // ********** if (_input.mouseLeftClicked()/* && m_itemName.IsItemSelected()*/) { // Left click activates the combine, if we are on an object if (_inv.leftClick(_input.mousePos(), _curActionObj)) { _curAction = TA_COMBINE; _point.setAction(_curAction); } } else // Right Click // *********** if (_input.mouseRightClicked()) { if (_itemName.isItemSelected()) { _curActionObj = 0; _inv.rightClick(_input.mousePos()); } else _inv.rightClick(_input.mousePos()); } else // Right Release // ************* if (_input.mouseRightReleased()) { if (_inv.rightRelease(_input.mousePos(), _curAction)) { CORO_INVOKE_3(_tony.moveAndDoAction, _itemName.getHotspot(), _itemName.getSelectedItem(), _curAction); _curAction = TA_GOTO; _point.setAction(_curAction); } } } else { // Options Menu // ************ if (_bGUIOption) { if (!_tony.inAction() && _bInput) { if ((_input.mouseLeftClicked() && _input.mousePos()._x < 3 && _input.mousePos()._y < 3)) { CORO_INVOKE_1(openOptionScreen, 0); goto SKIPCLICKSINISTRO; } else if (_input.getAsyncKeyState(Common::KEYCODE_ESCAPE)) CORO_INVOKE_1(openOptionScreen, 0); else if (!g_vm->getIsDemo()) { if (_input.getAsyncKeyState(Common::KEYCODE_F3) || _input.getAsyncKeyState(Common::KEYCODE_F5)) // Save game screen CORO_INVOKE_1(openOptionScreen, 4); else if (_input.getAsyncKeyState(Common::KEYCODE_F2) || _input.getAsyncKeyState(Common::KEYCODE_F7)) // Load game screen CORO_INVOKE_1(openOptionScreen, 3); } } } // Left Click // ************** if (_input.mouseLeftClicked() && !_inter.active()) { if (_curAction != TA_COMBINE) CORO_INVOKE_3(_tony.moveAndDoAction, _itemName.getHotspot(), _itemName.getSelectedItem(), _point.curAction()); else if (_itemName.getSelectedItem() != NULL) CORO_INVOKE_4(_tony.moveAndDoAction, _itemName.getHotspot(), _itemName.getSelectedItem(), TA_COMBINE, _curActionObj); if (_curAction == TA_COMBINE) { _inv.endCombine(); _point.setSpecialPointer(RMPointer::PTR_NONE); } _curAction = TA_GOTO; _point.setAction(_curAction); } SKIPCLICKSINISTRO: // Right Click // ************ if (_curAction == TA_COMBINE) { // During a combine, it cancels it if (_input.mouseRightClicked()) { _inv.endCombine(); _curActionObj = 0; _curAction = TA_GOTO; _point.setAction(_curAction); _point.setSpecialPointer(RMPointer::PTR_NONE); } } else if (_input.mouseRightClicked() && _itemName.isItemSelected() && _point.getSpecialPointer() == RMPointer::PTR_NONE) { if (_bGUIInterface) { // Before opening the interface, replaces GOTO _curAction = TA_GOTO; _curActionObj = 0; _point.setAction(_curAction); _inter.clicked(_input.mousePos()); } } // Right Release // ************* if (_input.mouseRightReleased()) { if (_bGUIInterface) { if (_inter.released(_input.mousePos(), _curAction)) { _point.setAction(_curAction); CORO_INVOKE_3(_tony.moveAndDoAction, _itemName.getHotspot(), _itemName.getSelectedItem(), _curAction); _curAction = TA_GOTO; _point.setAction(_curAction); } } } } // Update the name under the mouse pointer _itemName.setMouseCoord(_input.mousePos()); if (!_inter.active() && !_inv.miniActive()) CORO_INVOKE_4(_itemName.doFrame, _bigBuf, _loc, _point, _inv); } // Interface & Inventory _inter.doFrame(_bigBuf, _input.mousePos()); _inv.doFrame(_bigBuf, _point, _input.mousePos(), (!_tony.inAction() && !_inter.active() && _bGUIInventory)); } // Animate Tony CORO_INVOKE_2(_tony.doFrame, &_bigBuf, _nCurLoc); // Update screen scrolling to keep Tony in focus if (_tony.mustUpdateScrolling() && _bLocationLoaded) { RMPoint showThis = _tony.position(); showThis._y -= 60; _loc.updateScrolling(showThis); } if (_bLocationLoaded) _tony.setScrollPosition(_loc.scrollPosition()); if ((!_tony.inAction() && _bInput) || _bAlwaysDrawMouse) { _point.showCursor(); } else { _point.hideCursor(); } _point.doFrame(); // ********************** // Draw the list in the OT // ********************** CORO_INVOKE_0(_bigBuf.drawOT); #define FSTEP (480/32) // Wipe if (_bWiping) { switch (_nWipeType) { case 1: if (!(_rcWipeEllipse.bottom - _rcWipeEllipse.top >= FSTEP * 2)) { CoroScheduler.setEvent(_hWipeEvent); _nWipeType = 3; break; } _rcWipeEllipse.top += FSTEP; _rcWipeEllipse.left += FSTEP; _rcWipeEllipse.right -= FSTEP; _rcWipeEllipse.bottom -= FSTEP; break; case 2: if (!(_rcWipeEllipse.bottom - _rcWipeEllipse.top < 480 - FSTEP)) { CoroScheduler.setEvent(_hWipeEvent); _nWipeType = 3; break; } _rcWipeEllipse.top -= FSTEP; _rcWipeEllipse.left -= FSTEP; _rcWipeEllipse.right += FSTEP; _rcWipeEllipse.bottom += FSTEP; break; } } CORO_END_CODE; }
/** * Runs glitter code associated with a polygon. */ void PolyTinselProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; INT_CONTEXT *pic; bool bTookControl; // Set if this function takes control CORO_END_CONTEXT(_ctx); const PTP_INIT *to = (const PTP_INIT *)param; // get the stuff copied to process when it was created CORO_BEGIN_CODE(_ctx); if (TinselV2) { // Take control for CONVERSE events if (to->event == CONVERSE) { _ctx->bTookControl = GetControl(); HideConversation(true); } else _ctx->bTookControl = false; CORO_INVOKE_1(Interpret, to->pic); // Restore conv window if applicable if (to->event == CONVERSE) { // Free control if we took it if (_ctx->bTookControl) ControlOn(); HideConversation(false); } } else { CORO_INVOKE_1(AllowDclick, to->bev); // May kill us if single click // Control may have gone off during AllowDclick() if (!TestToken(TOKEN_CONTROL) && (to->event == WALKTO || to->event == ACTION || to->event == LOOK)) CORO_KILL_SELF(); // Take control, if requested if (to->take_control) _ctx->bTookControl = GetControl(CONTROL_OFF); else _ctx->bTookControl = false; // Hide conversation if appropriate if (to->event == CONVERSE) HideConversation(true); // Run the code _ctx->pic = InitInterpretContext(GS_POLYGON, GetPolyScript(to->hPoly), to->event, to->hPoly, to->actor, NULL); CORO_INVOKE_1(Interpret, _ctx->pic); // Free control if we took it if (_ctx->bTookControl) Control(CONTROL_ON); // Restore conv window if applicable if (to->event == CONVERSE) HideConversation(false); } CORO_END_CODE; }