diff options
author | Paul Gilbert | 2012-05-11 23:10:12 +1000 |
---|---|---|
committer | Paul Gilbert | 2012-05-11 23:10:12 +1000 |
commit | 64669234b2fdb2375d23157232d6104e6d8967d2 (patch) | |
tree | d4cdc6c16c1a8aabea68ff07b7cf44ebb6f23b7e /engines | |
parent | 50153aba8832d8707031df2219512515797d93ce (diff) | |
download | scummvm-rg350-64669234b2fdb2375d23157232d6104e6d8967d2.tar.gz scummvm-rg350-64669234b2fdb2375d23157232d6104e6d8967d2.tar.bz2 scummvm-rg350-64669234b2fdb2375d23157232d6104e6d8967d2.zip |
TINSEL: Refactored Tinsel engine to use the Common coroutine scheduler
Diffstat (limited to 'engines')
32 files changed, 137 insertions, 777 deletions
diff --git a/engines/tinsel/actors.cpp b/engines/tinsel/actors.cpp index acacd89667..a784ff5788 100644 --- a/engines/tinsel/actors.cpp +++ b/engines/tinsel/actors.cpp @@ -340,7 +340,7 @@ void RestoreActorProcess(int id, INT_CONTEXT *pic, bool savegameFlag) { if (savegameFlag) pic->resumeState = RES_SAVEGAME; - g_scheduler->createProcess(PID_TCODE, ActorRestoredProcess, &r, sizeof(r)); + CoroScheduler.createProcess(PID_TCODE, ActorRestoredProcess, &r, sizeof(r)); } /** @@ -358,7 +358,7 @@ void ActorEvent(int ano, TINSEL_EVENT event, PLR_EVENT be) { atp.event = event; atp.bev = be; atp.pic = NULL; - g_scheduler->createProcess(PID_TCODE, ActorTinselProcess, &atp, sizeof(atp)); + CoroScheduler.createProcess(PID_TCODE, ActorTinselProcess, &atp, sizeof(atp)); } } @@ -369,7 +369,7 @@ void ActorEvent(CORO_PARAM, int ano, TINSEL_EVENT tEvent, bool bWait, int myEsca ATP_INIT atp; int index; CORO_BEGIN_CONTEXT; - PPROCESS pProc; + Common::PPROCESS pProc; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); @@ -389,7 +389,7 @@ void ActorEvent(CORO_PARAM, int ano, TINSEL_EVENT tEvent, bool bWait, int myEsca myEscape); if (atp.pic != NULL) { - _ctx->pProc = g_scheduler->createProcess(PID_TCODE, ActorTinselProcess, &atp, sizeof(atp)); + _ctx->pProc = CoroScheduler.createProcess(PID_TCODE, ActorTinselProcess, &atp, sizeof(atp)); AttachInterpret(atp.pic, _ctx->pProc); if (bWait) @@ -474,8 +474,8 @@ void StartTaggedActors(SCNHANDLE ah, int numActors, bool bRunScript) { // Run actor's script for this scene if (bRunScript) { // Send in reverse order - they get swapped round in the scheduler - ActorEvent(nullContext, taggedActors[i].id, SHOWEVENT, false, 0); - ActorEvent(nullContext, taggedActors[i].id, STARTUP, false, 0); + ActorEvent(Common::nullContext, taggedActors[i].id, SHOWEVENT, false, 0); + ActorEvent(Common::nullContext, taggedActors[i].id, STARTUP, false, 0); } } } diff --git a/engines/tinsel/background.h b/engines/tinsel/background.h index 34f1bd6dd2..cfa3998eda 100644 --- a/engines/tinsel/background.h +++ b/engines/tinsel/background.h @@ -24,9 +24,9 @@ #ifndef TINSEL_BACKGND_H // prevent multiple includes #define TINSEL_BACKGND_H +#include "common/coroutines.h" #include "common/frac.h" #include "common/rect.h" -#include "tinsel/coroutine.h" #include "tinsel/dw.h" // for SCNHANDLE #include "tinsel/palette.h" // palette definitions diff --git a/engines/tinsel/bg.cpp b/engines/tinsel/bg.cpp index 72ba05f0b9..a3e21a8227 100644 --- a/engines/tinsel/bg.cpp +++ b/engines/tinsel/bg.cpp @@ -255,17 +255,17 @@ void StartupBackground(CORO_PARAM, SCNHANDLE hFilm) { g_BGspeed = ONE_SECOND / FROM_LE_32(pfilm->frate); // Start display process for each reel in the film - g_scheduler->createProcess(PID_REEL, BGmainProcess, &pfilm->reels[0], sizeof(FREEL)); + CoroScheduler.createProcess(PID_REEL, BGmainProcess, &pfilm->reels[0], sizeof(FREEL)); if (TinselV0) { for (uint i = 1; i < FROM_LE_32(pfilm->numreels); ++i) - g_scheduler->createProcess(PID_REEL, BGotherProcess, &pfilm->reels[i], sizeof(FREEL)); + CoroScheduler.createProcess(PID_REEL, BGotherProcess, &pfilm->reels[i], sizeof(FREEL)); } if (g_pBG[0] == NULL) ControlStartOff(); - if (TinselV2 && (coroParam != nullContext)) + if (TinselV2 && (coroParam != Common::nullContext)) CORO_GIVE_WAY; CORO_END_CODE; diff --git a/engines/tinsel/bmv.cpp b/engines/tinsel/bmv.cpp index 24d47b920f..438fd52a81 100644 --- a/engines/tinsel/bmv.cpp +++ b/engines/tinsel/bmv.cpp @@ -529,7 +529,7 @@ int BMVPlayer::MovieCommand(char cmd, int commandOffset) { if (cmd & CD_PRINT) { PRINT_CMD *pCmd = (PRINT_CMD *)(bigBuffer + commandOffset); - MovieText(nullContext, (int16)READ_LE_UINT16(&pCmd->stringId), + MovieText(Common::nullContext, (int16)READ_LE_UINT16(&pCmd->stringId), (int16)READ_LE_UINT16(&pCmd->x), (int16)READ_LE_UINT16(&pCmd->y), pCmd->fontId, @@ -542,7 +542,7 @@ int BMVPlayer::MovieCommand(char cmd, int commandOffset) { TALK_CMD *pCmd = (TALK_CMD *)(bigBuffer + commandOffset); talkColor = TINSEL_RGB(pCmd->r, pCmd->g, pCmd->b); - MovieText(nullContext, (int16)READ_LE_UINT16(&pCmd->stringId), + MovieText(Common::nullContext, (int16)READ_LE_UINT16(&pCmd->stringId), (int16)READ_LE_UINT16(&pCmd->x), (int16)READ_LE_UINT16(&pCmd->y), 0, diff --git a/engines/tinsel/bmv.h b/engines/tinsel/bmv.h index eadf65c3aa..fa254ed26d 100644 --- a/engines/tinsel/bmv.h +++ b/engines/tinsel/bmv.h @@ -24,12 +24,12 @@ #ifndef TINSEL_BMV_H #define TINSEL_BMV_H +#include "common/coroutines.h" #include "common/file.h" #include "audio/audiostream.h" #include "audio/mixer.h" -#include "tinsel/coroutine.h" #include "tinsel/object.h" #include "tinsel/palette.h" diff --git a/engines/tinsel/coroutine.cpp b/engines/tinsel/coroutine.cpp deleted file mode 100644 index ef0097f043..0000000000 --- a/engines/tinsel/coroutine.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "tinsel/coroutine.h" -#include "common/hashmap.h" -#include "common/hash-str.h" - -namespace Tinsel { - - -CoroContext nullContext = NULL; // FIXME: Avoid non-const global vars - - -#if COROUTINE_DEBUG -namespace { -static int s_coroCount = 0; - -typedef Common::HashMap<Common::String, int> CoroHashMap; -static CoroHashMap *s_coroFuncs = 0; - -static void changeCoroStats(const char *func, int change) { - if (!s_coroFuncs) - s_coroFuncs = new CoroHashMap(); - - (*s_coroFuncs)[func] += change; -} - -static void displayCoroStats() { - debug("%d active coros", s_coroCount); - - // Loop over s_coroFuncs and print info about active coros - if (!s_coroFuncs) - return; - for (CoroHashMap::const_iterator it = s_coroFuncs->begin(); - it != s_coroFuncs->end(); ++it) { - if (it->_value != 0) - debug(" %3d x %s", it->_value, it->_key.c_str()); - } -} - -} -#endif - -CoroBaseContext::CoroBaseContext(const char *func) - : _line(0), _sleep(0), _subctx(0) { -#if COROUTINE_DEBUG - _funcName = func; - changeCoroStats(_funcName, +1); - s_coroCount++; -#endif -} - -CoroBaseContext::~CoroBaseContext() { -#if COROUTINE_DEBUG - s_coroCount--; - changeCoroStats(_funcName, -1); - debug("Deleting coro in %s at %p (subctx %p)", - _funcName, (void *)this, (void *)_subctx); - displayCoroStats(); -#endif - delete _subctx; -} - -} // End of namespace Tinsel diff --git a/engines/tinsel/dialogs.cpp b/engines/tinsel/dialogs.cpp index 5396e47566..fbe9e8d1f6 100644 --- a/engines/tinsel/dialogs.cpp +++ b/engines/tinsel/dialogs.cpp @@ -1075,7 +1075,7 @@ static void PrimeSceneHopper() { uint32 vSize; // Open the file (it's on the CD) - CdCD(nullContext); + CdCD(Common::nullContext); if (!f.open(HOPPER_FILENAME)) error(CANNOT_FIND_FILE, HOPPER_FILENAME); @@ -1191,13 +1191,13 @@ static void HopAction() { debugC(DEBUG_BASIC, kTinselDebugAnimations, "Scene hopper chose scene %xh,%d\n", hScene, eNumber); if (FROM_LE_32(pEntry->flags) & fCall) { - SaveScene(nullContext); - NewScene(nullContext, g_pChosenScene->hScene, pEntry->eNumber, TRANS_FADE); + SaveScene(Common::nullContext); + NewScene(Common::nullContext, g_pChosenScene->hScene, pEntry->eNumber, TRANS_FADE); } else if (FROM_LE_32(pEntry->flags) & fHook) HookScene(hScene, eNumber, TRANS_FADE); else - NewScene(nullContext, hScene, eNumber, TRANS_CUT); + NewScene(Common::nullContext, hScene, eNumber, TRANS_CUT); } /**************************************************************************/ @@ -1406,13 +1406,13 @@ static void InvTinselEvent(INV_OBJECT *pinvo, TINSEL_EVENT event, PLR_EVENT be, return; g_GlitterIndex = index; - g_scheduler->createProcess(PID_TCODE, ObjectProcess, &to, sizeof(to)); + CoroScheduler.createProcess(PID_TCODE, ObjectProcess, &to, sizeof(to)); } extern void ObjectEvent(CORO_PARAM, int objId, TINSEL_EVENT event, bool bWait, int myEscape, bool *result) { // COROUTINE CORO_BEGIN_CONTEXT; - PROCESS *pProc; + Common::PROCESS *pProc; INV_OBJECT *pInvo; OP_INIT op; CORO_END_CONTEXT(_ctx); @@ -1428,7 +1428,7 @@ extern void ObjectEvent(CORO_PARAM, int objId, TINSEL_EVENT event, bool bWait, i _ctx->op.event = event; _ctx->op.myEscape = myEscape; - g_scheduler->createProcess(PID_TCODE, ObjectProcess, &_ctx->op, sizeof(_ctx->op)); + CoroScheduler.createProcess(PID_TCODE, ObjectProcess, &_ctx->op, sizeof(_ctx->op)); if (bWait) CORO_INVOKE_2(WaitInterpret, _ctx->pProc, result); @@ -3540,9 +3540,9 @@ extern void ConvAction(int index) { } if (g_thisConvPoly != NOPOLY) - PolygonEvent(nullContext, g_thisConvPoly, CONVERSE, 0, false, 0); + PolygonEvent(Common::nullContext, g_thisConvPoly, CONVERSE, 0, false, 0); else - ActorEvent(nullContext, g_thisConvActor, CONVERSE, false, 0); + ActorEvent(Common::nullContext, g_thisConvActor, CONVERSE, false, 0); } } @@ -5128,7 +5128,7 @@ static void InvPickup(int index) { if (TinselV2) InvPutDown(index); else - g_scheduler->createProcess(PID_TCODE, InvPdProcess, &index, sizeof(index)); + CoroScheduler.createProcess(PID_TCODE, InvPdProcess, &index, sizeof(index)); } } } diff --git a/engines/tinsel/drives.cpp b/engines/tinsel/drives.cpp index d815fd165d..5c4b939e4e 100644 --- a/engines/tinsel/drives.cpp +++ b/engines/tinsel/drives.cpp @@ -48,13 +48,13 @@ void CdCD(CORO_PARAM) { CORO_BEGIN_CODE(_ctx); while (g_bChangingCD) { - if (g_scheduler->getCurrentProcess()) { - // FIXME: CdCD gets passed a nullContext in RegisterGlobals() and + if (CoroScheduler.getCurrentProcess()) { + // FIXME: CdCD gets passed a Common::nullContext in RegisterGlobals() and // PrimeSceneHopper(), because I didn't know how to get a proper // context without converting the whole calling stack to CORO'd // functions. If these functions really get called while a CD // change is requested, this needs to be resolved. - if (coroParam == nullContext) + if (coroParam == Common::nullContext) error("CdCD needs context"); CORO_SLEEP(1); } else diff --git a/engines/tinsel/drives.h b/engines/tinsel/drives.h index 907071d2f8..9e97b92fa5 100644 --- a/engines/tinsel/drives.h +++ b/engines/tinsel/drives.h @@ -24,9 +24,9 @@ #ifndef TINSEL_DRIVES_H #define TINSEL_DRIVES_H +#include "common/coroutines.h" #include "common/stream.h" #include "tinsel/dw.h" -#include "tinsel/coroutine.h" namespace Tinsel { diff --git a/engines/tinsel/effect.cpp b/engines/tinsel/effect.cpp index 22027b0f02..f5adb63c2b 100644 --- a/engines/tinsel/effect.cpp +++ b/engines/tinsel/effect.cpp @@ -108,7 +108,7 @@ static void FettleEffectPolys(int x, int y, int index, PMOVER pActor) { epi.hEpoly = hPoly; epi.pMover = pActor; epi.index = index; - g_scheduler->createProcess(PID_TCODE, EffectProcess, &epi, sizeof(epi)); + CoroScheduler.createProcess(PID_TCODE, EffectProcess, &epi, sizeof(epi)); } } } diff --git a/engines/tinsel/events.cpp b/engines/tinsel/events.cpp index 74454c5f2a..1aa4d34227 100644 --- a/engines/tinsel/events.cpp +++ b/engines/tinsel/events.cpp @@ -22,10 +22,10 @@ * Also provides a couple of utility functions. */ +#include "common/coroutines.h" #include "tinsel/actors.h" #include "tinsel/background.h" #include "tinsel/config.h" -#include "tinsel/coroutine.h" #include "tinsel/cursor.h" #include "tinsel/dw.h" #include "tinsel/events.h" @@ -276,7 +276,7 @@ static void WalkProcess(CORO_PARAM, const void *param) { void WalkTo(int x, int y) { WP_INIT to = { x, y }; - g_scheduler->createProcess(PID_TCODE, WalkProcess, &to, sizeof(to)); + CoroScheduler.createProcess(PID_TCODE, WalkProcess, &to, sizeof(to)); } /** @@ -295,7 +295,7 @@ static void ProcessUserEvent(TINSEL_EVENT uEvent, const Common::Point &coOrds, P if ((actor = GetTaggedActor()) != 0) { // Event for a tagged actor if (TinselV2) - ActorEvent(nullContext, actor, uEvent, false, 0); + ActorEvent(Common::nullContext, actor, uEvent, false, 0); else ActorEvent(actor, uEvent, be); } else if ((hPoly = GetTaggedPoly()) != NOPOLY) { @@ -303,7 +303,7 @@ static void ProcessUserEvent(TINSEL_EVENT uEvent, const Common::Point &coOrds, P if (!TinselV2) RunPolyTinselCode(hPoly, uEvent, be, false); else if (uEvent != PROV_WALKTO) - PolygonEvent(nullContext, hPoly, uEvent, 0, false, 0); + PolygonEvent(Common::nullContext, hPoly, uEvent, 0, false, 0); } else { GetCursorXY(&aniX, &aniY, true); @@ -312,7 +312,7 @@ static void ProcessUserEvent(TINSEL_EVENT uEvent, const Common::Point &coOrds, P if ((hPoly = InPolygon(aniX, aniY, TAG)) != NOPOLY || (!TinselV2 && ((hPoly = InPolygon(aniX, aniY, EXIT)) != NOPOLY))) { if (TinselV2 && (uEvent != PROV_WALKTO)) - PolygonEvent(nullContext, hPoly, uEvent, 0, false, 0); + PolygonEvent(Common::nullContext, hPoly, uEvent, 0, false, 0); else if (!TinselV2) RunPolyTinselCode(hPoly, uEvent, be, false); } else if ((uEvent == PROV_WALKTO) || (uEvent == WALKTO)) { @@ -604,7 +604,7 @@ void PolyTinselProcess(CORO_PARAM, const void *param) { void PolygonEvent(CORO_PARAM, HPOLYGON hPoly, TINSEL_EVENT tEvent, int actor, bool bWait, int myEscape, bool *result) { CORO_BEGIN_CONTEXT; - PPROCESS pProc; + Common::PPROCESS pProc; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); @@ -623,7 +623,7 @@ void PolygonEvent(CORO_PARAM, HPOLYGON hPoly, TINSEL_EVENT tEvent, int actor, bo NULL, // No Object myEscape); if (to.pic != NULL) { - _ctx->pProc = g_scheduler->createProcess(PID_TCODE, PolyTinselProcess, &to, sizeof(to)); + _ctx->pProc = CoroScheduler.createProcess(PID_TCODE, PolyTinselProcess, &to, sizeof(to)); AttachInterpret(to.pic, _ctx->pProc); if (bWait) @@ -640,14 +640,14 @@ void RunPolyTinselCode(HPOLYGON hPoly, TINSEL_EVENT event, PLR_EVENT be, bool tc PTP_INIT to = { hPoly, event, be, tc, 0, NULL }; assert(!TinselV2); - g_scheduler->createProcess(PID_TCODE, PolyTinselProcess, &to, sizeof(to)); + CoroScheduler.createProcess(PID_TCODE, PolyTinselProcess, &to, sizeof(to)); } void effRunPolyTinselCode(HPOLYGON hPoly, TINSEL_EVENT event, int actor) { PTP_INIT to = { hPoly, event, PLR_NOEVENT, false, actor, NULL }; assert(!TinselV2); - g_scheduler->createProcess(PID_TCODE, PolyTinselProcess, &to, sizeof(to)); + CoroScheduler.createProcess(PID_TCODE, PolyTinselProcess, &to, sizeof(to)); } /** diff --git a/engines/tinsel/events.h b/engines/tinsel/events.h index f2b4d7f663..cdf5ae2ae4 100644 --- a/engines/tinsel/events.h +++ b/engines/tinsel/events.h @@ -24,9 +24,9 @@ #ifndef TINSEL_EVENTS_H #define TINSEL_EVENTS_H -#include "tinsel/dw.h" -#include "tinsel/coroutine.h" +#include "common/coroutines.h" #include "common/rect.h" +#include "tinsel/dw.h" namespace Tinsel { diff --git a/engines/tinsel/faders.cpp b/engines/tinsel/faders.cpp index 86d117af81..c1574ff963 100644 --- a/engines/tinsel/faders.cpp +++ b/engines/tinsel/faders.cpp @@ -145,7 +145,7 @@ static void Fader(const long multTable[], SCNHANDLE noFadeTable[]) { if (TinselV2) { // The is only ever one cuncurrent fade // But this could be a fade out and the fade in is still going! - g_scheduler->killMatchingProcess(PID_FADER); + CoroScheduler.killMatchingProcess(PID_FADER); NoFadingPalettes(); } @@ -176,7 +176,7 @@ static void Fader(const long multTable[], SCNHANDLE noFadeTable[]) { fade.pPalQ = pPal; // create a fader process for this palette - g_scheduler->createProcess(PID_FADER, FadeProcess, (void *)&fade, sizeof(FADE)); + CoroScheduler.createProcess(PID_FADER, FadeProcess, (void *)&fade, sizeof(FADE)); } } } diff --git a/engines/tinsel/handle.cpp b/engines/tinsel/handle.cpp index e31b2141f5..c3089db990 100644 --- a/engines/tinsel/handle.cpp +++ b/engines/tinsel/handle.cpp @@ -361,7 +361,7 @@ byte *LockMem(SCNHANDLE offset) { if (TinselV2) { SetCD(pH->flags2 & fAllCds); - CdCD(nullContext); + CdCD(Common::nullContext); } LoadFile(pH); } diff --git a/engines/tinsel/module.mk b/engines/tinsel/module.mk index 2ab94b830a..3485bac74b 100644 --- a/engines/tinsel/module.mk +++ b/engines/tinsel/module.mk @@ -9,7 +9,6 @@ MODULE_OBJS := \ bmv.o \ cliprect.o \ config.o \ - coroutine.o \ cursor.o \ debugger.o \ detection.o \ diff --git a/engines/tinsel/move.cpp b/engines/tinsel/move.cpp index bb49e59fe7..275b6006f5 100644 --- a/engines/tinsel/move.cpp +++ b/engines/tinsel/move.cpp @@ -1299,14 +1299,14 @@ static void SetOffWithinNodePath(PMOVER pMover, HPOLYGON StartPath, HPOLYGON Des */ void SSetActorDest(PMOVER pActor) { if (pActor->UtargetX != -1 && pActor->UtargetY != -1) { - Stand(nullContext, pActor->actorID, pActor->objX, pActor->objY, 0); + Stand(Common::nullContext, pActor->actorID, pActor->objX, pActor->objY, 0); if (pActor->UtargetX != -1 && pActor->UtargetY != -1) { SetActorDest(pActor, pActor->UtargetX, pActor->UtargetY, pActor->bIgPath, 0); } } else { - Stand(nullContext, pActor->actorID, pActor->objX, pActor->objY, 0); + Stand(Common::nullContext, pActor->actorID, pActor->objX, pActor->objY, 0); } } diff --git a/engines/tinsel/pcode.cpp b/engines/tinsel/pcode.cpp index 145a6a8e5d..60f04b47fd 100644 --- a/engines/tinsel/pcode.cpp +++ b/engines/tinsel/pcode.cpp @@ -243,13 +243,13 @@ static INT_CONTEXT *AllocateInterpretContext(GSORT gsort) { for (i = 0, pic = g_icList; i < NUM_INTERPRET; i++, pic++) { if (pic->GSort == GS_NONE) { - pic->pProc = g_scheduler->getCurrentProcess(); + pic->pProc = CoroScheduler.getCurrentProcess(); pic->GSort = gsort; return pic; } #ifdef DEBUG else { - if (pic->pProc == g_scheduler->getCurrentProcess()) + if (pic->pProc == CoroScheduler.getCurrentProcess()) error("Found unreleased interpret context"); } #endif @@ -277,7 +277,7 @@ static void FreeWaitCheck(PINT_CONTEXT pic, bool bVoluntary) { if ((g_icList + i)->waitNumber1 == pic->waitNumber2) { (g_icList + i)->waitNumber1 = 0; (g_icList + i)->resumeCode = bVoluntary ? RES_FINISHED : RES_CUTSHORT; - g_scheduler->reschedule((g_icList + i)->pProc); + CoroScheduler.reschedule((g_icList + i)->pProc); break; } } @@ -301,7 +301,7 @@ static void FreeInterpretContextPi(INT_CONTEXT *pic) { * Ensures that interpret contexts don't get lost when an Interpret() * call doesn't complete. */ -void FreeInterpretContextPr(PROCESS *pProc) { +void FreeInterpretContextPr(Common::PROCESS *pProc) { INT_CONTEXT *pic; int i; @@ -393,7 +393,7 @@ INT_CONTEXT *RestoreInterpretContext(INT_CONTEXT *ric) { ic = AllocateInterpretContext(GS_NONE); // Sort will soon be overridden memcpy(ic, ric, sizeof(INT_CONTEXT)); - ic->pProc = g_scheduler->getCurrentProcess(); + ic->pProc = CoroScheduler.getCurrentProcess(); ic->resumeState = RES_1; LockCode(ic); @@ -422,7 +422,7 @@ void RegisterGlobals(int num) { if (g_icList == NULL) { error("Cannot allocate memory for interpret contexts"); } - g_scheduler->setResourceCallback(FreeInterpretContextPr); + CoroScheduler.setResourceCallback(FreeInterpretContextPr); } else { // Check size is still the same assert(g_numGlobals == num); @@ -433,7 +433,7 @@ void RegisterGlobals(int num) { if (TinselV2) { // read initial values - CdCD(nullContext); + CdCD(Common::nullContext); Common::File f; if (!f.open(GLOBALS_FILENAME)) @@ -839,7 +839,7 @@ void Interpret(CORO_PARAM, INT_CONTEXT *ic) { * Associates an interpret context with the * process that will run it. */ -void AttachInterpret(INT_CONTEXT *pic, PROCESS *pProc) { +void AttachInterpret(INT_CONTEXT *pic, Common::PROCESS *pProc) { // Attach the process which is using this context pic->pProc = pProc; } @@ -869,9 +869,9 @@ static uint32 UniqueWaitNumber() { /** * WaitInterpret */ -void WaitInterpret(CORO_PARAM, PPROCESS pWaitProc, bool *result) { +void WaitInterpret(CORO_PARAM, Common::PPROCESS pWaitProc, bool *result) { int i; - PPROCESS currentProcess = g_scheduler->getCurrentProcess(); + Common::PPROCESS currentProcess = CoroScheduler.getCurrentProcess(); assert(currentProcess); assert(currentProcess != pWaitProc); if (result) *result = false; diff --git a/engines/tinsel/pcode.h b/engines/tinsel/pcode.h index 5d16dae432..4980fc6ed9 100644 --- a/engines/tinsel/pcode.h +++ b/engines/tinsel/pcode.h @@ -25,7 +25,7 @@ #define TINSEL_PCODE_H #include "tinsel/events.h" // for TINSEL_EVENT -#include "tinsel/sched.h" // for PROCESS +#include "tinsel/sched.h" // for Common::PROCESS namespace Common { class Serializer; @@ -56,7 +56,7 @@ struct WorkaroundEntry; struct INT_CONTEXT { // Elements for interpret context management - PROCESS *pProc; ///< processes owning this context + Common::PROCESS *pProc; ///< processes owning this context GSORT GSort; ///< sort of this context // Previously parameters to Interpret() @@ -114,12 +114,12 @@ void SaveInterpretContexts(INT_CONTEXT *sICInfo); void RegisterGlobals(int num); void FreeGlobals(); -void AttachInterpret(INT_CONTEXT *pic, PROCESS *pProc); +void AttachInterpret(INT_CONTEXT *pic, Common::PROCESS *pProc); -void WaitInterpret(CORO_PARAM, PPROCESS pWaitProc, bool *result); +void WaitInterpret(CORO_PARAM, Common::PPROCESS pWaitProc, bool *result); -#define NUM_INTERPRET (NUM_PROCESS - 20) -#define MAX_INTERPRET (MAX_PROCESSES - 20) +#define NUM_INTERPRET (CORO_NUM_PROCESS - 20) +#define MAX_INTERPRET (CORO_MAX_PROCESSES - 20) /*----------------------------------------------------------------------*\ |* Library Procedure and Function codes parameter enums *| diff --git a/engines/tinsel/pdisplay.cpp b/engines/tinsel/pdisplay.cpp index 9a9e6ab00f..b821c5dee2 100644 --- a/engines/tinsel/pdisplay.cpp +++ b/engines/tinsel/pdisplay.cpp @@ -23,9 +23,9 @@ * PointProcess() */ +#include "common/coroutines.h" #include "tinsel/actors.h" #include "tinsel/background.h" -#include "tinsel/coroutine.h" #include "tinsel/cursor.h" #include "tinsel/dw.h" #include "tinsel/events.h" @@ -265,7 +265,7 @@ void DisablePointing() { if (hPoly != NOPOLY && PolyType(hPoly) == TAG && PolyIsPointedTo(hPoly)) { SetPolyPointedTo(hPoly, false); SetPolyTagWanted(hPoly, false, false, 0); - PolygonEvent(nullContext, hPoly, UNPOINT, 0, false, 0); + PolygonEvent(Common::nullContext, hPoly, UNPOINT, 0, false, 0); } } @@ -275,7 +275,7 @@ void DisablePointing() { SetActorPointedTo(i, false); SetActorTagWanted(i, false, false, 0); - ActorEvent(nullContext, i, UNPOINT, false, 0); + ActorEvent(Common::nullContext, i, UNPOINT, false, 0); } } } diff --git a/engines/tinsel/play.cpp b/engines/tinsel/play.cpp index 40729d9f3a..9e0baa749e 100644 --- a/engines/tinsel/play.cpp +++ b/engines/tinsel/play.cpp @@ -21,9 +21,9 @@ * Plays films within a scene, takes into account the actor in each 'column'. | */ +#include "common/coroutines.h" #include "tinsel/actors.h" #include "tinsel/background.h" -#include "tinsel/coroutine.h" #include "tinsel/dw.h" #include "tinsel/film.h" #include "tinsel/handle.h" @@ -395,7 +395,7 @@ static void SoundReelWaitCheck() { if (--g_soundReelWait == 0) { for (int i = 0; i < MAX_SOUNDREELS; i++) { if (g_soundReels[i].hFilm) { - g_scheduler->createProcess(PID_REEL, ResSoundReel, &i, sizeof(i)); + CoroScheduler.createProcess(PID_REEL, ResSoundReel, &i, sizeof(i)); } } } @@ -1001,7 +1001,7 @@ void PlayFilm(CORO_PARAM, SCNHANDLE hFilm, int x, int y, int actorid, bool splay NewestFilm(hFilm, &pFilm->reels[i]); ppi.column = i; - g_scheduler->createProcess(PID_REEL, PlayProcess, &ppi, sizeof(PPINIT)); + CoroScheduler.createProcess(PID_REEL, PlayProcess, &ppi, sizeof(PPINIT)); } if (TinselV2) { @@ -1011,7 +1011,7 @@ void PlayFilm(CORO_PARAM, SCNHANDLE hFilm, int x, int y, int actorid, bool splay CORO_GIVE_WAY; if (myescEvent && myescEvent != GetEscEvents()) - g_scheduler->rescheduleAll(); + CoroScheduler.rescheduleAll(); } CORO_END_CODE; @@ -1063,7 +1063,7 @@ void PlayFilmc(CORO_PARAM, SCNHANDLE hFilm, int x, int y, int actorid, bool spla NewestFilm(hFilm, &pFilm->reels[i]); _ctx->ppi.column = i; - g_scheduler->createProcess(PID_REEL, PlayProcess, &_ctx->ppi, sizeof(PPINIT)); + CoroScheduler.createProcess(PID_REEL, PlayProcess, &_ctx->ppi, sizeof(PPINIT)); } if (TinselV2) { @@ -1078,7 +1078,7 @@ void PlayFilmc(CORO_PARAM, SCNHANDLE hFilm, int x, int y, int actorid, bool spla // Wait until film changes or loop count increases while (GetActorPresFilm(_ctx->i) == hFilm && GetLoopCount(_ctx->i) == _ctx->loopCount) { if (myescEvent && myescEvent != GetEscEvents()) { - g_scheduler->rescheduleAll(); + CoroScheduler.rescheduleAll(); break; } @@ -1126,7 +1126,7 @@ void RestoreActorReels(SCNHANDLE hFilm, short reelnum, short z, int x, int y) { NewestFilm(hFilm, &pfilm->reels[reelnum]); // Start display process for the reel - g_scheduler->createProcess(PID_REEL, PlayProcess, &ppi, sizeof(ppi)); + CoroScheduler.createProcess(PID_REEL, PlayProcess, &ppi, sizeof(ppi)); } /** @@ -1160,7 +1160,7 @@ void RestoreActorReels(SCNHANDLE hFilm, int actor, int x, int y) { NewestFilm(hFilm, &pFilm->reels[i]); // Start display process for the reel - g_scheduler->createProcess(PID_REEL, PlayProcess, &ppi, sizeof(ppi)); + CoroScheduler.createProcess(PID_REEL, PlayProcess, &ppi, sizeof(ppi)); g_soundReelWait++; } diff --git a/engines/tinsel/play.h b/engines/tinsel/play.h index 041b7096a8..fffa8a9329 100644 --- a/engines/tinsel/play.h +++ b/engines/tinsel/play.h @@ -24,7 +24,7 @@ #ifndef TINSEL_PLAY_H // prevent multiple includes #define TINSEL_PLAY_H -#include "tinsel/coroutine.h" +#include "common/coroutines.h" #include "tinsel/dw.h" #include "tinsel/multiobj.h" diff --git a/engines/tinsel/polygons.cpp b/engines/tinsel/polygons.cpp index 6fc1c65ec5..d8c1cef0b6 100644 --- a/engines/tinsel/polygons.cpp +++ b/engines/tinsel/polygons.cpp @@ -1469,7 +1469,7 @@ static void SetExTags(SCNHANDLE ph) { pts = &TagStates[SceneTags[i].offset]; for (j = 0; j < SceneTags[i].nooftags; j++, pts++) { if (!pts->enabled) - DisableTag(nullContext, pts->tid); + DisableTag(Common::nullContext, pts->tid); } return; } @@ -1873,7 +1873,7 @@ void InitPolygons(SCNHANDLE ph, int numPoly, bool bRestart) { } else { for (int i = numPoly - 1; i >= 0; i--) { if (Polys[i]->polyType == TAG) { - PolygonEvent(nullContext, i, STARTUP, 0, false, 0); + PolygonEvent(Common::nullContext, i, STARTUP, 0, false, 0); } } } diff --git a/engines/tinsel/rince.cpp b/engines/tinsel/rince.cpp index bb0aeabd2f..ba8f47f9cf 100644 --- a/engines/tinsel/rince.cpp +++ b/engines/tinsel/rince.cpp @@ -202,8 +202,8 @@ void KillMover(PMOVER pMover) { pMover->bActive = false; MultiDeleteObject(GetPlayfieldList(FIELD_WORLD), pMover->actorObj); pMover->actorObj = NULL; - assert(g_scheduler->getCurrentProcess() != pMover->pProc); - g_scheduler->killProcess(pMover->pProc); + assert(CoroScheduler.getCurrentProcess() != pMover->pProc); + CoroScheduler.killProcess(pMover->pProc); } } @@ -856,10 +856,10 @@ void MoverProcessCreate(int X, int Y, int id, PMOVER pMover) { iStruct.Y = Y; iStruct.pMover = pMover; - g_scheduler->createProcess(PID_MOVER, T2MoverProcess, &iStruct, sizeof(MAINIT)); + CoroScheduler.createProcess(PID_MOVER, T2MoverProcess, &iStruct, sizeof(MAINIT)); } else { MoverProcessHelper(X, Y, id, pMover); - pMover->pProc = g_scheduler->createProcess(PID_MOVER, T1MoverProcess, &pMover, sizeof(PMOVER)); + pMover->pProc = CoroScheduler.createProcess(PID_MOVER, T1MoverProcess, &pMover, sizeof(PMOVER)); } } diff --git a/engines/tinsel/rince.h b/engines/tinsel/rince.h index 93fd191172..b34c3f20de 100644 --- a/engines/tinsel/rince.h +++ b/engines/tinsel/rince.h @@ -31,7 +31,7 @@ namespace Tinsel { struct OBJECT; -struct PROCESS; +struct Common::PROCESS; enum NPS {NOT_IN, GOING_UP, GOING_DOWN, LEAVING, ENTERING}; @@ -110,7 +110,7 @@ struct MOVER { /* NOTE: If effect polys can overlap, this needs improving */ bool bInEffect; - PROCESS *pProc; + Common::PROCESS *pProc; // Discworld 2 specific fields int32 zOverride; diff --git a/engines/tinsel/savescn.cpp b/engines/tinsel/savescn.cpp index 1b06e3929c..0c0cc5c81e 100644 --- a/engines/tinsel/savescn.cpp +++ b/engines/tinsel/savescn.cpp @@ -190,7 +190,7 @@ void sortActors(SAVED_DATA *sd) { RestoreAuxScales(sd->SavedMoverInfo); for (int i = 0; i < MAX_MOVERS; i++) { if (sd->SavedMoverInfo[i].bActive) - Stand(nullContext, sd->SavedMoverInfo[i].actorID, sd->SavedMoverInfo[i].objX, + Stand(Common::nullContext, sd->SavedMoverInfo[i].actorID, sd->SavedMoverInfo[i].objX, sd->SavedMoverInfo[i].objY, sd->SavedMoverInfo[i].hLastfilm); } } @@ -245,7 +245,7 @@ static void SortMAProcess(CORO_PARAM, const void *) { void ResumeInterprets() { // Master script only affected on restore game, not restore scene if (!TinselV2 && (g_rsd == &g_sgData)) { - g_scheduler->killMatchingProcess(PID_MASTER_SCR, -1); + CoroScheduler.killMatchingProcess(PID_MASTER_SCR, -1); FreeMasterInterpretContext(); } @@ -314,7 +314,7 @@ static int DoRestoreSceneFrame(SAVED_DATA *sd, int n) { // Master script only affected on restore game, not restore scene if (sd == &g_sgData) { - g_scheduler->killMatchingProcess(PID_MASTER_SCR); + CoroScheduler.killMatchingProcess(PID_MASTER_SCR); KillGlobalProcesses(); FreeMasterInterpretContext(); } @@ -340,7 +340,7 @@ static int DoRestoreSceneFrame(SAVED_DATA *sd, int n) { SetDoFadeIn(!g_bNoFade); g_bNoFade = false; - StartupBackground(nullContext, sd->SavedBgroundHandle); + StartupBackground(Common::nullContext, sd->SavedBgroundHandle); if (TinselV2) { Offset(EX_USEXY, sd->SavedLoffset, sd->SavedToffset); @@ -354,7 +354,7 @@ static int DoRestoreSceneFrame(SAVED_DATA *sd, int n) { if (TinselV2) { // create process to sort out the moving actors - g_scheduler->createProcess(PID_MOVER, SortMAProcess, NULL, 0); + CoroScheduler.createProcess(PID_MOVER, SortMAProcess, NULL, 0); g_bNotDoneYet = true; RestoreActorZ(sd->savedActorZ); diff --git a/engines/tinsel/scene.cpp b/engines/tinsel/scene.cpp index f635ce13a3..79bb30f7a3 100644 --- a/engines/tinsel/scene.cpp +++ b/engines/tinsel/scene.cpp @@ -193,7 +193,7 @@ void SendSceneTinselProcess(TINSEL_EVENT event) { init.event = event; init.hTinselCode = ss->hSceneScript; - g_scheduler->createProcess(PID_TCODE, SceneTinselProcess, &init, sizeof(init)); + CoroScheduler.createProcess(PID_TCODE, SceneTinselProcess, &init, sizeof(init)); } } } @@ -271,7 +271,7 @@ static void LoadScene(SCNHANDLE scene, int entry) { init.event = STARTUP; init.hTinselCode = es->hScript; - g_scheduler->createProcess(PID_TCODE, SceneTinselProcess, &init, sizeof(init)); + CoroScheduler.createProcess(PID_TCODE, SceneTinselProcess, &init, sizeof(init)); } break; } @@ -291,7 +291,7 @@ static void LoadScene(SCNHANDLE scene, int entry) { init.event = STARTUP; init.hTinselCode = ss->hSceneScript; - g_scheduler->createProcess(PID_TCODE, SceneTinselProcess, &init, sizeof(init)); + CoroScheduler.createProcess(PID_TCODE, SceneTinselProcess, &init, sizeof(init)); } } @@ -344,7 +344,7 @@ void EndScene() { KillAllObjects(); // kill all destructable process - g_scheduler->killMatchingProcess(PID_DESTROY, PID_DESTROY); + CoroScheduler.killMatchingProcess(PID_DESTROY, PID_DESTROY); } /** @@ -405,16 +405,16 @@ void PrimeScene() { if (!TinselV2) EnableTags(); // Next scene with tags enabled - g_scheduler->createProcess(PID_SCROLL, ScrollProcess, NULL, 0); - g_scheduler->createProcess(PID_SCROLL, EffectPolyProcess, NULL, 0); + CoroScheduler.createProcess(PID_SCROLL, ScrollProcess, NULL, 0); + CoroScheduler.createProcess(PID_SCROLL, EffectPolyProcess, NULL, 0); #ifdef DEBUG if (g_ShowPosition) - g_scheduler->createProcess(PID_POSITION, CursorPositionProcess, NULL, 0); + CoroScheduler.createProcess(PID_POSITION, CursorPositionProcess, NULL, 0); #endif - g_scheduler->createProcess(PID_TAG, TagProcess, NULL, 0); - g_scheduler->createProcess(PID_TAG, PointProcess, NULL, 0); + CoroScheduler.createProcess(PID_TAG, TagProcess, NULL, 0); + CoroScheduler.createProcess(PID_TAG, PointProcess, NULL, 0); // init the current background PrimeBackground(); @@ -471,7 +471,7 @@ void DoHailScene(SCNHANDLE scene) { init.event = NOEVENT; init.hTinselCode = ss->hSceneScript; - g_scheduler->createProcess(PID_TCODE, SceneTinselProcess, &init, sizeof(init)); + CoroScheduler.createProcess(PID_TCODE, SceneTinselProcess, &init, sizeof(init)); } } diff --git a/engines/tinsel/sched.cpp b/engines/tinsel/sched.cpp index 343758d924..4bf356ba36 100644 --- a/engines/tinsel/sched.cpp +++ b/engines/tinsel/sched.cpp @@ -32,8 +32,6 @@ namespace Tinsel { -Scheduler *g_scheduler = 0; - #include "common/pack-start.h" // START STRUCT PACKING struct PROCESS_STRUC { @@ -53,471 +51,6 @@ static SCNHANDLE g_hSceneProcess; static uint32 g_numGlobalProcess; static PROCESS_STRUC *g_pGlobalProcess; -//--------------------- FUNCTIONS ------------------------ - -Scheduler::Scheduler() { - processList = 0; - pFreeProcesses = 0; - pCurrent = 0; - -#ifdef DEBUG - // diagnostic process counters - numProcs = 0; - maxProcs = 0; -#endif - - pRCfunction = 0; - - active = new PROCESS; - active->pPrevious = NULL; - active->pNext = NULL; - - g_scheduler = this; // FIXME HACK -} - -Scheduler::~Scheduler() { - // Kill all running processes (i.e. free memory allocated for their state). - PROCESS *pProc = active->pNext; - while (pProc != NULL) { - delete pProc->state; - pProc->state = 0; - pProc = pProc->pNext; - } - - free(processList); - processList = NULL; - - delete active; - active = 0; -} - -/** - * Kills all processes and places them on the free list. - */ -void Scheduler::reset() { - -#ifdef DEBUG - // clear number of process in use - numProcs = 0; -#endif - - if (processList == NULL) { - // first time - allocate memory for process list - processList = (PROCESS *)calloc(MAX_PROCESSES, sizeof(PROCESS)); - - // make sure memory allocated - if (processList == NULL) { - error("Cannot allocate memory for process data"); - } - - // fill with garbage - memset(processList, 'S', MAX_PROCESSES * sizeof(PROCESS)); - } - - // Kill all running processes (i.e. free memory allocated for their state). - PROCESS *pProc = active->pNext; - while (pProc != NULL) { - delete pProc->state; - pProc->state = 0; - pProc = pProc->pNext; - } - - // no active processes - pCurrent = active->pNext = NULL; - - // place first process on free list - pFreeProcesses = processList; - - // link all other processes after first - for (int i = 1; i <= NUM_PROCESS; i++) { - processList[i - 1].pNext = (i == NUM_PROCESS) ? NULL : processList + i; - processList[i - 1].pPrevious = (i == 1) ? active : processList + (i - 2); - } -} - - -#ifdef DEBUG -/** - * Shows the maximum number of process used at once. - */ -void Scheduler::printStats() { - debug("%i process of %i used", maxProcs, NUM_PROCESS); -} -#endif - -#ifdef DEBUG -/** - * Checks both the active and free process list to insure all the links are valid, - * and that no processes have been lost - */ -void Scheduler::CheckStack() { - Common::List<PROCESS *> pList; - - // Check both the active and free process lists - for (int i = 0; i < 2; ++i) { - PROCESS *p = (i == 0) ? active : pFreeProcesses; - - if (p != NULL) { - // Make sure the linkages are correct - while (p->pNext != NULL) { - assert(p->pNext->pPrevious == p); - pList.push_back(p); - p = p->pNext; - } - pList.push_back(p); - } - } - - // Make sure all processes are accounted for - for (int idx = 0; idx < NUM_PROCESS; idx++) { - bool found = false; - for (Common::List<PROCESS *>::iterator i = pList.begin(); i != pList.end(); ++i) { - PROCESS *pTemp = *i; - if (*i == &processList[idx]) { - found = true; - break; - } - } - - assert(found); - } -} -#endif - -/** - * Give all active processes a chance to run - */ -void Scheduler::schedule() { - // start dispatching active process list - PROCESS *pNext; - PROCESS *pProc = active->pNext; - while (pProc != NULL) { - pNext = pProc->pNext; - - if (--pProc->sleepTime <= 0) { - // process is ready for dispatch, activate it - pCurrent = pProc; - pProc->coroAddr(pProc->state, pProc->param); - - if (!pProc->state || pProc->state->_sleep <= 0) { - // Coroutine finished - pCurrent = pCurrent->pPrevious; - killProcess(pProc); - } else { - pProc->sleepTime = pProc->state->_sleep; - } - - // pCurrent may have been changed - pNext = pCurrent->pNext; - pCurrent = NULL; - } - - pProc = pNext; - } -} - -/** - * Reschedules all the processes to run again this query - */ -void Scheduler::rescheduleAll() { - assert(pCurrent); - - // Unlink current process - pCurrent->pPrevious->pNext = pCurrent->pNext; - if (pCurrent->pNext) - pCurrent->pNext->pPrevious = pCurrent->pPrevious; - - // Add process to the start of the active list - pCurrent->pNext = active->pNext; - active->pNext->pPrevious = pCurrent; - active->pNext = pCurrent; - pCurrent->pPrevious = active; -} - -/** - * If the specified process has already run on this tick, make it run - * again on the current tick. - */ -void Scheduler::reschedule(PPROCESS pReSchedProc) { - // If not currently processing the schedule list, then no action is needed - if (!pCurrent) - return; - - if (!pReSchedProc) - pReSchedProc = pCurrent; - - PPROCESS pEnd; - - // Find the last process in the list. - // But if the target process is down the list from here, do nothing - for (pEnd = pCurrent; pEnd->pNext != NULL; pEnd = pEnd->pNext) { - if (pEnd->pNext == pReSchedProc) - return; - } - - assert(pEnd->pNext == NULL); - - // Could be in the middle of a KillProc()! - // Dying process was last and this process was penultimate - if (pReSchedProc->pNext == NULL) - return; - - // If we're moving the current process, move it back by one, so that the next - // schedule() iteration moves to the now next one - if (pCurrent == pReSchedProc) - pCurrent = pCurrent->pPrevious; - - // Unlink the process, and add it at the end - pReSchedProc->pPrevious->pNext = pReSchedProc->pNext; - pReSchedProc->pNext->pPrevious = pReSchedProc->pPrevious; - pEnd->pNext = pReSchedProc; - pReSchedProc->pPrevious = pEnd; - pReSchedProc->pNext = NULL; -} - -/** - * Moves the specified process to the end of the dispatch queue - * allowing it to run again within the current game cycle. - * @param pGiveProc Which process - */ -void Scheduler::giveWay(PPROCESS pReSchedProc) { - // If not currently processing the schedule list, then no action is needed - if (!pCurrent) - return; - - if (!pReSchedProc) - pReSchedProc = pCurrent; - - // If the process is already at the end of the queue, nothing has to be done - if (!pReSchedProc->pNext) - return; - - PPROCESS pEnd; - - // Find the last process in the list. - for (pEnd = pCurrent; pEnd->pNext != NULL; pEnd = pEnd->pNext) - ; - assert(pEnd->pNext == NULL); - - - // If we're moving the current process, move it back by one, so that the next - // schedule() iteration moves to the now next one - if (pCurrent == pReSchedProc) - pCurrent = pCurrent->pPrevious; - - // Unlink the process, and add it at the end - pReSchedProc->pPrevious->pNext = pReSchedProc->pNext; - pReSchedProc->pNext->pPrevious = pReSchedProc->pPrevious; - pEnd->pNext = pReSchedProc; - pReSchedProc->pPrevious = pEnd; - pReSchedProc->pNext = NULL; -} - -/** - * Creates a new process. - * - * @param pid process identifier - * @param CORO_ADDR coroutine start address - * @param pParam process specific info - * @param sizeParam size of process specific info - */ -PROCESS *Scheduler::createProcess(int pid, CORO_ADDR coroAddr, const void *pParam, int sizeParam) { - PROCESS *pProc; - - // get a free process - pProc = pFreeProcesses; - - // trap no free process - assert(pProc != NULL); // Out of processes - -#ifdef DEBUG - // one more process in use - if (++numProcs > maxProcs) - maxProcs = numProcs; -#endif - - // get link to next free process - pFreeProcesses = pProc->pNext; - if (pFreeProcesses) - pFreeProcesses->pPrevious = NULL; - - if (pCurrent != NULL) { - // place new process before the next active process - pProc->pNext = pCurrent->pNext; - if (pProc->pNext) - pProc->pNext->pPrevious = pProc; - - // make this new process the next active process - pCurrent->pNext = pProc; - pProc->pPrevious = pCurrent; - - } else { // no active processes, place process at head of list - pProc->pNext = active->pNext; - pProc->pPrevious = active; - - if (pProc->pNext) - pProc->pNext->pPrevious = pProc; - active->pNext = pProc; - - } - - // set coroutine entry point - pProc->coroAddr = coroAddr; - - // clear coroutine state - pProc->state = 0; - - // wake process up as soon as possible - pProc->sleepTime = 1; - - // set new process id - pProc->pid = pid; - - // set new process specific info - if (sizeParam) { - assert(sizeParam > 0 && sizeParam <= PARAM_SIZE); - - // set new process specific info - memcpy(pProc->param, pParam, sizeParam); - } - - // return created process - return pProc; -} - -/** - * Kills the specified process. - * - * @param pKillProc which process to kill - */ -void Scheduler::killProcess(PROCESS *pKillProc) { - // make sure a valid process pointer - assert(pKillProc >= processList && pKillProc <= processList + NUM_PROCESS - 1); - - // can not kill the current process using killProcess ! - assert(pCurrent != pKillProc); - -#ifdef DEBUG - // one less process in use - --numProcs; - assert(numProcs >= 0); -#endif - - // Free process' resources - if (pRCfunction != NULL) - (pRCfunction)(pKillProc); - - delete pKillProc->state; - pKillProc->state = 0; - - // Take the process out of the active chain list - pKillProc->pPrevious->pNext = pKillProc->pNext; - if (pKillProc->pNext) - pKillProc->pNext->pPrevious = pKillProc->pPrevious; - - // link first free process after pProc - pKillProc->pNext = pFreeProcesses; - if (pFreeProcesses) - pKillProc->pNext->pPrevious = pKillProc; - pKillProc->pPrevious = NULL; - - // make pKillProc the first free process - pFreeProcesses = pKillProc; -} - - - -/** - * Returns a pointer to the currently running process. - */ -PROCESS *Scheduler::getCurrentProcess() { - return pCurrent; -} - -/** - * Returns the process identifier of the specified process. - * - * @param pProc which process - */ -int Scheduler::getCurrentPID() const { - PROCESS *pProc = pCurrent; - - // make sure a valid process pointer - assert(pProc >= processList && pProc <= processList + NUM_PROCESS - 1); - - // return processes PID - return pProc->pid; -} - -/** - * Kills any process matching the specified PID. The current - * process cannot be killed. - * - * @param pidKill process identifier of process to kill - * @param pidMask mask to apply to process identifiers before comparison - * @return The number of processes killed is returned. - */ -int Scheduler::killMatchingProcess(int pidKill, int pidMask) { - int numKilled = 0; - PROCESS *pProc, *pPrev; // process list pointers - - for (pProc = active->pNext, pPrev = active; pProc != NULL; pPrev = pProc, pProc = pProc->pNext) { - if ((pProc->pid & pidMask) == pidKill) { - // found a matching process - - // dont kill the current process - if (pProc != pCurrent) { - // kill this process - numKilled++; - - // Free the process' resources - if (pRCfunction != NULL) - (pRCfunction)(pProc); - - delete pProc->state; - pProc->state = 0; - - // make prev point to next to unlink pProc - pPrev->pNext = pProc->pNext; - if (pProc->pNext) - pPrev->pNext->pPrevious = pPrev; - - // link first free process after pProc - pProc->pNext = pFreeProcesses; - pProc->pPrevious = NULL; - pFreeProcesses->pPrevious = pProc; - - // make pProc the first free process - pFreeProcesses = pProc; - - // set to a process on the active list - pProc = pPrev; - } - } - } - -#ifdef DEBUG - // adjust process in use - numProcs -= numKilled; - assert(numProcs >= 0); -#endif - - // return number of processes killed - return numKilled; -} - -/** - * Set pointer to a function to be called by killProcess(). - * - * May be called by a resource allocator, the function supplied is - * called by killProcess() to allow the resource allocator to free - * resources allocated to the dying process. - * - * @param pFunc Function to be called by killProcess() - */ -void Scheduler::setResourceCallback(VFPTRPP pFunc) { - pRCfunction = pFunc; -} /**************************************************************************\ |*********** Stuff to do with scene and global processes ************| @@ -537,7 +70,7 @@ static void RestoredProcessProcess(CORO_PARAM, const void *param) { _ctx->pic = *(const PINT_CONTEXT *)param; _ctx->pic = RestoreInterpretContext(_ctx->pic); - AttachInterpret(_ctx->pic, g_scheduler->getCurrentProcess()); + AttachInterpret(_ctx->pic, CoroScheduler.getCurrentProcess()); CORO_INVOKE_1(Interpret, _ctx->pic); @@ -577,7 +110,7 @@ void RestoreSceneProcess(INT_CONTEXT *pic) { pStruc = (PROCESS_STRUC *)LockMem(g_hSceneProcess); for (i = 0; i < g_numSceneProcess; i++) { if (FROM_LE_32(pStruc[i].hProcessCode) == pic->hCode) { - g_scheduler->createProcess(PID_PROCESS + i, RestoredProcessProcess, + CoroScheduler.createProcess(PID_PROCESS + i, RestoredProcessProcess, &pic, sizeof(pic)); break; } @@ -596,7 +129,7 @@ void SceneProcessEvent(CORO_PARAM, uint32 procID, TINSEL_EVENT event, bool bWait CORO_BEGIN_CONTEXT; PROCESS_STRUC *pStruc; - PPROCESS pProc; + Common::PPROCESS pProc; PINT_CONTEXT pic; CORO_END_CONTEXT(_ctx); @@ -617,7 +150,7 @@ void SceneProcessEvent(CORO_PARAM, uint32 procID, TINSEL_EVENT event, bool bWait if (_ctx->pic == NULL) return; - _ctx->pProc = g_scheduler->createProcess(PID_PROCESS + i, ProcessTinselProcess, + _ctx->pProc = CoroScheduler.createProcess(PID_PROCESS + i, ProcessTinselProcess, &_ctx->pic, sizeof(_ctx->pic)); AttachInterpret(_ctx->pic, _ctx->pProc); break; @@ -644,7 +177,7 @@ void KillSceneProcess(uint32 procID) { pStruc = (PROCESS_STRUC *) LockMem(g_hSceneProcess); for (i = 0; i < g_numSceneProcess; i++) { if (FROM_LE_32(pStruc[i].processId) == procID) { - g_scheduler->killMatchingProcess(PID_PROCESS + i, -1); + CoroScheduler.killMatchingProcess(PID_PROCESS + i, -1); break; } } @@ -671,7 +204,7 @@ void RestoreGlobalProcess(INT_CONTEXT *pic) { for (i = 0; i < g_numGlobalProcess; i++) { if (g_pGlobalProcess[i].hProcessCode == pic->hCode) { - g_scheduler->createProcess(PID_GPROCESS + i, RestoredProcessProcess, + CoroScheduler.createProcess(PID_GPROCESS + i, RestoredProcessProcess, &pic, sizeof(pic)); break; } @@ -686,7 +219,7 @@ void RestoreGlobalProcess(INT_CONTEXT *pic) { void KillGlobalProcesses() { for (uint32 i = 0; i < g_numGlobalProcess; ++i) { - g_scheduler->killMatchingProcess(PID_GPROCESS + i, -1); + CoroScheduler.killMatchingProcess(PID_GPROCESS + i, -1); } } @@ -696,7 +229,7 @@ void KillGlobalProcesses() { bool GlobalProcessEvent(CORO_PARAM, uint32 procID, TINSEL_EVENT event, bool bWait, int myEscape) { CORO_BEGIN_CONTEXT; PINT_CONTEXT pic; - PPROCESS pProc; + Common::PPROCESS pProc; CORO_END_CONTEXT(_ctx); bool result = false; @@ -720,7 +253,7 @@ bool GlobalProcessEvent(CORO_PARAM, uint32 procID, TINSEL_EVENT event, bool bWai if (_ctx->pic != NULL) { - _ctx->pProc = g_scheduler->createProcess(PID_GPROCESS + i, ProcessTinselProcess, + _ctx->pProc = CoroScheduler.createProcess(PID_GPROCESS + i, ProcessTinselProcess, &_ctx->pic, sizeof(_ctx->pic)); AttachInterpret(_ctx->pic, _ctx->pProc); } @@ -745,7 +278,7 @@ void xKillGlobalProcess(uint32 procID) { for (i = 0; i < g_numGlobalProcess; ++i) { if (g_pGlobalProcess[i].processId == procID) { - g_scheduler->killMatchingProcess(PID_GPROCESS + i, -1); + CoroScheduler.killMatchingProcess(PID_GPROCESS + i, -1); break; } } diff --git a/engines/tinsel/sched.h b/engines/tinsel/sched.h index a1eafcdc47..3e791cecd8 100644 --- a/engines/tinsel/sched.h +++ b/engines/tinsel/sched.h @@ -24,105 +24,16 @@ #ifndef TINSEL_SCHED_H // prevent multiple includes #define TINSEL_SCHED_H +#include "common/coroutines.h" #include "tinsel/dw.h" // new data types -#include "tinsel/coroutine.h" #include "tinsel/events.h" +#include "tinsel/pcode.h" #include "tinsel/tinsel.h" namespace Tinsel { -// the size of process specific info -#define PARAM_SIZE 32 - -// the maximum number of processes -#define NUM_PROCESS (TinselV2 ? 70 : 64) -#define MAX_PROCESSES 70 - -typedef void (*CORO_ADDR)(CoroContext &, const void *); - -/** process structure */ -struct PROCESS { - PROCESS *pNext; ///< pointer to next process in active or free list - PROCESS *pPrevious; ///< pointer to previous process in active or free list - - CoroContext state; ///< the state of the coroutine - CORO_ADDR coroAddr; ///< the entry point of the coroutine - - int sleepTime; ///< number of scheduler cycles to sleep - int pid; ///< process ID - char param[PARAM_SIZE]; ///< process specific info -}; -typedef PROCESS *PPROCESS; - struct INT_CONTEXT; -/** - * Create and manage "processes" (really coroutines). - */ -class Scheduler { -public: - /** Pointer to a function of the form "void function(PPROCESS)" */ - typedef void (*VFPTRPP)(PROCESS *); - -private: - - /** list of all processes */ - PROCESS *processList; - - /** active process list - also saves scheduler state */ - PROCESS *active; - - /** pointer to free process list */ - PROCESS *pFreeProcesses; - - /** the currently active process */ - PROCESS *pCurrent; - -#ifdef DEBUG - // diagnostic process counters - int numProcs; - int maxProcs; - - void CheckStack(); -#endif - - /** - * Called from killProcess() to enable other resources - * a process may be allocated to be released. - */ - VFPTRPP pRCfunction; - - -public: - - Scheduler(); - ~Scheduler(); - - void reset(); - - #ifdef DEBUG - void printStats(); - #endif - - void schedule(); - void rescheduleAll(); - void reschedule(PPROCESS pReSchedProc = NULL); - void giveWay(PPROCESS pReSchedProc = NULL); - - PROCESS *createProcess(int pid, CORO_ADDR coroAddr, const void *pParam, int sizeParam); - void killProcess(PROCESS *pKillProc); - - PROCESS *getCurrentProcess(); - int getCurrentPID() const; - int killMatchingProcess(int pidKill, int pidMask = -1); - - - void setResourceCallback(VFPTRPP pFunc); - -}; - -extern Scheduler *g_scheduler; // FIXME: Temporary global var, to be used until everything has been OOifyied - //----------------- FUNCTION PROTOTYPES -------------------- void SceneProcesses(uint32 numProcess, SCNHANDLE hProcess); diff --git a/engines/tinsel/text.h b/engines/tinsel/text.h index 4c80300c46..97e82c7a93 100644 --- a/engines/tinsel/text.h +++ b/engines/tinsel/text.h @@ -24,7 +24,7 @@ #ifndef TINSEL_TEXT_H // prevent multiple includes #define TINSEL_TEXT_H -#include "tinsel/coroutine.h" +#include "common/coroutines.h" #include "tinsel/object.h" // object manager defines namespace Tinsel { diff --git a/engines/tinsel/tinlib.cpp b/engines/tinsel/tinlib.cpp index c652abca25..dfa44c505a 100644 --- a/engines/tinsel/tinlib.cpp +++ b/engines/tinsel/tinlib.cpp @@ -28,11 +28,11 @@ #define BODGE +#include "common/coroutines.h" #include "tinsel/actors.h" #include "tinsel/background.h" #include "tinsel/bmv.h" #include "tinsel/config.h" -#include "tinsel/coroutine.h" #include "tinsel/cursor.h" #include "tinsel/drives.h" #include "tinsel/dw.h" @@ -1468,7 +1468,7 @@ void NewScene(CORO_PARAM, SCNHANDLE scene, int entrance, int transition) { ++g_sceneCtr; // Prevent code subsequent to this call running before scene changes - if (g_scheduler->getCurrentPID() != PID_MASTER_SCR) + if (CoroScheduler.getCurrentPID() != PID_MASTER_SCR) CORO_KILL_SELF(); CORO_END_CODE; } @@ -2594,7 +2594,7 @@ static void Scroll(CORO_PARAM, EXTREME extreme, int xp, int yp, int xIter, int y sm.y = _ctx->y; sm.thisScroll = g_scrollNumber; sm.myEscape = myEscape; - g_scheduler->createProcess(PID_TCODE, ScrollMonitorProcess, &sm, sizeof(sm)); + CoroScheduler.createProcess(PID_TCODE, ScrollMonitorProcess, &sm, sizeof(sm)); } } CORO_END_CODE; @@ -2975,12 +2975,12 @@ static void StandTag(int actor, HPOLYGON hp) { && hFilm != TF_LEFT && hFilm != TF_RIGHT) hFilm = 0; - Stand(nullContext, actor, pnodex, pnodey, hFilm); + Stand(Common::nullContext, actor, pnodex, pnodey, hFilm); } else if (hFilm && (actor == LEAD_ACTOR || actor == GetLeadId())) - Stand(nullContext, actor, pnodex, pnodey, hFilm); + Stand(Common::nullContext, actor, pnodex, pnodey, hFilm); else - Stand(nullContext, actor, pnodex, pnodey, 0); + Stand(Common::nullContext, actor, pnodex, pnodey, 0); } diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp index 65900cc7f3..e09e2c1dcf 100644 --- a/engines/tinsel/tinsel.cpp +++ b/engines/tinsel/tinsel.cpp @@ -109,8 +109,8 @@ static Scene g_NextScene = { 0, 0, 0 }; static Scene g_HookScene = { 0, 0, 0 }; static Scene g_DelayedScene = { 0, 0, 0 }; -static PROCESS *g_pMouseProcess = 0; -static PROCESS *g_pKeyboardProcess = 0; +static Common::PROCESS *g_pMouseProcess = 0; +static Common::PROCESS *g_pKeyboardProcess = 0; static SCNHANDLE g_hCdChangeScene; @@ -324,7 +324,7 @@ static void MouseProcess(CORO_PARAM, const void *) { if (TinselV2) { // Kill off the button process and fire off the action command - g_scheduler->killMatchingProcess(PID_BTN_CLICK, -1); + CoroScheduler.killMatchingProcess(PID_BTN_CLICK, -1); PlayerEvent(PLR_ACTION, _ctx->clickPos); } else { // signal left drag start @@ -368,7 +368,7 @@ static void MouseProcess(CORO_PARAM, const void *) { // will activate a single button click if (TinselV2 && ControlIsOn()) { _ctx->clickPos = mousePos; - g_scheduler->createProcess(PID_BTN_CLICK, SingleLeftProcess, &_ctx->clickPos, sizeof(Common::Point)); + CoroScheduler.createProcess(PID_BTN_CLICK, SingleLeftProcess, &_ctx->clickPos, sizeof(Common::Point)); } } else _ctx->lastLeftClick -= _vm->_config->_dclickSpeed; @@ -616,11 +616,11 @@ static void RestoredProcess(CORO_PARAM, const void *param) { } void RestoreProcess(INT_CONTEXT *pic) { - g_scheduler->createProcess(PID_TCODE, RestoredProcess, &pic, sizeof(pic)); + CoroScheduler.createProcess(PID_TCODE, RestoredProcess, &pic, sizeof(pic)); } void RestoreMasterProcess(INT_CONTEXT *pic) { - g_scheduler->createProcess(PID_MASTER_SCR, RestoredProcess, &pic, sizeof(pic)); + CoroScheduler.createProcess(PID_MASTER_SCR, RestoredProcess, &pic, sizeof(pic)); } // FIXME: CountOut is used by ChangeScene @@ -878,7 +878,6 @@ TinselEngine::~TinselEngine() { FreeObjectList(); FreeGlobalProcesses(); FreeGlobals(); - delete _scheduler; delete _config; @@ -905,7 +904,7 @@ Common::Error TinselEngine::run() { _console = new Console(); - _scheduler = new Scheduler(); + CoroScheduler.reset(); InitSysVars(); @@ -1022,7 +1021,7 @@ void TinselEngine::NextGameCycle() { ResetEcount(); // schedule process - _scheduler->schedule(); + CoroScheduler.schedule(); if (_bmv->MoviePlaying()) _bmv->CopyMovieToScreen(); @@ -1078,11 +1077,11 @@ bool TinselEngine::pollEvent() { */ void TinselEngine::CreateConstProcesses() { // Process to run the master script - _scheduler->createProcess(PID_MASTER_SCR, MasterScriptProcess, NULL, 0); + CoroScheduler.createProcess(PID_MASTER_SCR, MasterScriptProcess, NULL, 0); // Processes to run the cursor and inventory, - _scheduler->createProcess(PID_CURSOR, CursorProcess, NULL, 0); - _scheduler->createProcess(PID_INVENTORY, InventoryProcess, NULL, 0); + CoroScheduler.createProcess(PID_CURSOR, CursorProcess, NULL, 0); + CoroScheduler.createProcess(PID_INVENTORY, InventoryProcess, NULL, 0); } /** @@ -1132,11 +1131,11 @@ void TinselEngine::RestartDrivers() { KillAllObjects(); // init the process scheduler - _scheduler->reset(); + CoroScheduler.reset(); // init the event handlers - g_pMouseProcess = _scheduler->createProcess(PID_MOUSE, MouseProcess, NULL, 0); - g_pKeyboardProcess = _scheduler->createProcess(PID_KEYBOARD, KeyboardProcess, NULL, 0); + g_pMouseProcess = CoroScheduler.createProcess(PID_MOUSE, MouseProcess, NULL, 0); + g_pKeyboardProcess = CoroScheduler.createProcess(PID_KEYBOARD, KeyboardProcess, NULL, 0); // open MIDI files OpenMidiFiles(); @@ -1164,8 +1163,8 @@ void TinselEngine::ChopDrivers() { DeleteMidiBuffer(); // remove event drivers - _scheduler->killProcess(g_pMouseProcess); - _scheduler->killProcess(g_pKeyboardProcess); + CoroScheduler.killProcess(g_pMouseProcess); + CoroScheduler.killProcess(g_pKeyboardProcess); } /** diff --git a/engines/tinsel/token.cpp b/engines/tinsel/token.cpp index c26fa40466..080c005c3c 100644 --- a/engines/tinsel/token.cpp +++ b/engines/tinsel/token.cpp @@ -31,7 +31,7 @@ namespace Tinsel { //----------------- LOCAL GLOBAL DATA -------------------- struct Token { - PROCESS *proc; + Common::PROCESS *proc; }; static Token g_tokens[NUMTOKENS]; // FIXME: Avoid non-const global vars @@ -40,7 +40,7 @@ static Token g_tokens[NUMTOKENS]; // FIXME: Avoid non-const global vars /** * Release all tokens held by this process, and kill the process. */ -static void TerminateProcess(PROCESS *tProc) { +static void TerminateProcess(Common::PROCESS *tProc) { // Release tokens held by the process for (int i = 0; i < NUMTOKENS; i++) { @@ -50,7 +50,7 @@ static void TerminateProcess(PROCESS *tProc) { } // Kill the process - g_scheduler->killProcess(tProc); + CoroScheduler.killProcess(tProc); } /** @@ -60,7 +60,7 @@ void GetControlToken() { const int which = TOKEN_CONTROL; if (g_tokens[which].proc == NULL) { - g_tokens[which].proc = g_scheduler->getCurrentProcess(); + g_tokens[which].proc = CoroScheduler.getCurrentProcess(); } } @@ -85,11 +85,11 @@ void GetToken(int which) { assert(TOKEN_LEAD <= which && which < NUMTOKENS); if (g_tokens[which].proc != NULL) { - assert(g_tokens[which].proc != g_scheduler->getCurrentProcess()); + assert(g_tokens[which].proc != CoroScheduler.getCurrentProcess()); TerminateProcess(g_tokens[which].proc); } - g_tokens[which].proc = g_scheduler->getCurrentProcess(); + g_tokens[which].proc = CoroScheduler.getCurrentProcess(); } /** @@ -99,7 +99,7 @@ void GetToken(int which) { void FreeToken(int which) { assert(TOKEN_LEAD <= which && which < NUMTOKENS); - assert(g_tokens[which].proc == g_scheduler->getCurrentProcess()); // we'd have been killed if some other proc had taken this token + assert(g_tokens[which].proc == CoroScheduler.getCurrentProcess()); // we'd have been killed if some other proc had taken this token g_tokens[which].proc = NULL; } |