diff options
-rw-r--r-- | engines/tinsel/actors.cpp | 12 | ||||
-rw-r--r-- | engines/tinsel/bg.cpp | 6 | ||||
-rw-r--r-- | engines/tinsel/coroutine.h | 69 | ||||
-rw-r--r-- | engines/tinsel/cursor.cpp | 2 | ||||
-rw-r--r-- | engines/tinsel/effect.cpp | 8 | ||||
-rw-r--r-- | engines/tinsel/events.cpp | 14 | ||||
-rw-r--r-- | engines/tinsel/faders.cpp | 6 | ||||
-rw-r--r-- | engines/tinsel/inventory.cpp | 14 | ||||
-rw-r--r-- | engines/tinsel/pcode.cpp | 20 | ||||
-rw-r--r-- | engines/tinsel/pdisplay.cpp | 6 | ||||
-rw-r--r-- | engines/tinsel/play.cpp | 10 | ||||
-rw-r--r-- | engines/tinsel/rince.cpp | 10 | ||||
-rw-r--r-- | engines/tinsel/savescn.cpp | 2 | ||||
-rw-r--r-- | engines/tinsel/scene.cpp | 31 | ||||
-rw-r--r-- | engines/tinsel/sched.cpp | 111 | ||||
-rw-r--r-- | engines/tinsel/sched.h | 110 | ||||
-rw-r--r-- | engines/tinsel/scroll.cpp | 2 | ||||
-rw-r--r-- | engines/tinsel/scroll.h | 2 | ||||
-rw-r--r-- | engines/tinsel/tinlib.cpp | 2 | ||||
-rw-r--r-- | engines/tinsel/tinsel.cpp | 76 | ||||
-rw-r--r-- | engines/tinsel/tinsel.h | 3 | ||||
-rw-r--r-- | engines/tinsel/token.cpp | 10 |
22 files changed, 271 insertions, 255 deletions
diff --git a/engines/tinsel/actors.cpp b/engines/tinsel/actors.cpp index 7ea2da28f6..5e4a17fb65 100644 --- a/engines/tinsel/actors.cpp +++ b/engines/tinsel/actors.cpp @@ -174,14 +174,14 @@ struct ATP_INIT { /** * Runs actor's glitter code. */ -static void ActorTinselProcess(CORO_PARAM) { +static void ActorTinselProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; PINT_CONTEXT pic; CORO_END_CONTEXT(_ctx); // get the stuff copied to process when it was created - ATP_INIT *atp = (ATP_INIT *)ProcessGetParamsSelf(); + ATP_INIT *atp = (ATP_INIT *)param; CORO_BEGIN_CODE(_ctx); @@ -207,14 +207,14 @@ struct RATP_INIT { int id; // Actor number }; -static void ActorRestoredProcess(CORO_PARAM) { +static void ActorRestoredProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; PINT_CONTEXT pic; CORO_END_CONTEXT(_ctx); // get the stuff copied to process when it was created - RATP_INIT *r = (RATP_INIT *)ProcessGetParamsSelf(); + RATP_INIT *r = (RATP_INIT *)param; CORO_BEGIN_CODE(_ctx); @@ -230,7 +230,7 @@ static void ActorRestoredProcess(CORO_PARAM) { void RestoreActorProcess(int id, PINT_CONTEXT pic) { RATP_INIT r = { pic, id }; - ProcessCreate(PID_TCODE, ActorRestoredProcess, &r, sizeof(r)); + g_scheduler->createProcess(PID_TCODE, ActorRestoredProcess, &r, sizeof(r)); } /** @@ -247,7 +247,7 @@ void actorEvent(int ano, USER_EVENT event, BUTEVENT be) { atp.id = ano; atp.event = event; atp.bev = be; - ProcessCreate(PID_TCODE, ActorTinselProcess, &atp, sizeof(atp)); + g_scheduler->createProcess(PID_TCODE, ActorTinselProcess, &atp, sizeof(atp)); } } diff --git a/engines/tinsel/bg.cpp b/engines/tinsel/bg.cpp index 833c2fe37f..922e21bd18 100644 --- a/engines/tinsel/bg.cpp +++ b/engines/tinsel/bg.cpp @@ -93,7 +93,7 @@ int BackgroundHeight(void) { /** * Run main animation that comprises the scene background. */ -static void BGmainProcess(CORO_PARAM) { +static void BGmainProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); @@ -104,7 +104,7 @@ static void BGmainProcess(CORO_PARAM) { const MULTI_INIT *pmi; // get the stuff copied to process when it was created - pfr = (const FREEL *)ProcessGetParamsSelf(); + pfr = (const FREEL *)param; if (pBG == NULL) { /*** At start of scene ***/ @@ -176,7 +176,7 @@ void startupBackground(SCNHANDLE bfilm) { // Start display process for each reel in the film assert(FROM_LE_32(pfilm->numreels) == 1); // Multi-reeled backgrounds withdrawn - ProcessCreate(PID_REEL, BGmainProcess, &pfilm->reels[0], sizeof(FREEL)); + g_scheduler->createProcess(PID_REEL, BGmainProcess, &pfilm->reels[0], sizeof(FREEL)); } /** diff --git a/engines/tinsel/coroutine.h b/engines/tinsel/coroutine.h index 4a8997fe00..e0292735bb 100644 --- a/engines/tinsel/coroutine.h +++ b/engines/tinsel/coroutine.h @@ -30,15 +30,36 @@ namespace Tinsel { -// The following is loosely based on <http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html>, -// Proper credit to Simon Tatham shall be given. - /* + * The following is loosely based on an article by Simon Tatham: + * <http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html>. + * However, many improvements and tweaks have been made, in particular + * by taking advantage of C++ features not available in C. + * + * Why is this code here? Well, the Tinsel engine apparently used + * setjmp/longjmp based coroutines as a core tool from the start, and + * so they are deeply ingrained into the whole code base. When we + * started to get Tinsel ready for ScummVM, we had to deal with that. + * It soon got clear that we could not simply rewrite the code to work + * without some form of coroutines. While possible in principle, it + * would have meant a major restructuring of the entire code base, a + * rather daunting task. Also, it would have very likely introduced + * tons of regressons. + * + * So instead of getting rid of the coroutines, we chose to implement + * them in an alternate way, using Simon Tatham's trick as described + * above. While the trick is dirty, the result seems to be clear enough, + * we hope; plus, it allowed us to stay relatively close to the + * original structure of the code, which made it easier to avoid + * regressions, and will be helpful in the future when comparing things + * against the original code base. + */ - * `ccr' macros for re-entrant coroutines. +/** + * The core of any coroutine context which captures the 'state' of a coroutine. + * Private use only */ - struct CoroBaseContext { int _line; int _sleep; @@ -53,16 +74,28 @@ typedef CoroBaseContext *CoroContext; /** * Wrapper class which holds a pointer to a pointer to a CoroBaseContext. * The interesting part is the destructor, which kills the context being held, - * but ONLY if the _sleep val of that context is zero. + * but ONLY if the _sleep val of that context is zero. This way, a coroutine + * can just 'return' w/o having to worry about freeing the allocated context + * (in Simon Tatham's original code, one had to use a special macro to + * return from a coroutine). */ -struct CoroContextHolder { +class CoroContextHolder { CoroContext &_ctx; +public: CoroContextHolder(CoroContext &ctx) : _ctx(ctx) {} - ~CoroContextHolder() { if (_ctx && _ctx->_sleep == 0) { delete _ctx; _ctx = 0; } } + ~CoroContextHolder() { + if (_ctx && _ctx->_sleep == 0) { + delete _ctx; + _ctx = 0; + } + } }; + #define CORO_PARAM CoroContext &coroParam +#define CORO_SUBCTX coroParam->_subctx + #define CORO_BEGIN_CONTEXT struct CoroContextTag : CoroBaseContext { int DUMMY #define CORO_END_CONTEXT(x) } *x = (CoroContextTag *)coroParam @@ -80,19 +113,18 @@ struct CoroContextHolder { #define CORO_SLEEP(delay) \ do {\ - coroParam->_line=__LINE__;\ - coroParam->_sleep=delay;\ + coroParam->_line = __LINE__;\ + coroParam->_sleep = delay;\ return; case __LINE__:;\ } while (0) -// Stop the currently running coroutine +/** Stop the currently running coroutine */ #define CORO_KILL_SELF() do { coroParam->_sleep = -1; return; } while(0) -//#define CORO_ABORT() do { delete (ctx); ctx = 0; } while (0) - +/** Invoke another coroutine */ #define CORO_INVOKE_ARGS(subCoro, ARGS) \ do {\ - coroParam->_line=__LINE__;\ + coroParam->_line = __LINE__;\ coroParam->_subctx = 0;\ do {\ subCoro ARGS;\ @@ -102,21 +134,12 @@ struct CoroContextHolder { } while(1);\ } while (0) -#define CORO_SUBCTX coroParam->_subctx - #define CORO_INVOKE_0(subCoroutine) \ CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX)) #define CORO_INVOKE_1(subCoroutine, a0) \ CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX,a0)) #define CORO_INVOKE_2(subCoroutine, a0,a1) \ CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX,a0,a1)) -#define CORO_INVOKE_3(subCoroutine, a0,a1,a2) \ - CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX,a0,a1,a2)) -#define CORO_INVOKE_4(subCoroutine, a0,a1,a2,a3) \ - CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX,a0,a1,a2,a3)) -#define CORO_INVOKE_5(subCoroutine, a0,a1,a2,a3,a4) \ - CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX,a0,a1,a2,a3,a4)) - } // end of namespace Tinsel diff --git a/engines/tinsel/cursor.cpp b/engines/tinsel/cursor.cpp index 087730c165..042c5b88e3 100644 --- a/engines/tinsel/cursor.cpp +++ b/engines/tinsel/cursor.cpp @@ -522,7 +522,7 @@ static void CursorStoppedCheck(CORO_PARAM) { /** * The main cursor process. */ -void CursorProcess(CORO_PARAM) { +void CursorProcess(CORO_PARAM, const void *) { // COROUTINE CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); diff --git a/engines/tinsel/effect.cpp b/engines/tinsel/effect.cpp index b75e186c74..91645da71b 100644 --- a/engines/tinsel/effect.cpp +++ b/engines/tinsel/effect.cpp @@ -56,12 +56,12 @@ struct EP_INIT { * actor to leave that polygon. Then runs the polygon's Glitter code * with LEAVE event. */ -static void EffectProcess(CORO_PARAM) { +static void EffectProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); - EP_INIT *to = (EP_INIT *)ProcessGetParamsSelf(); // get the stuff copied to process when it was created + EP_INIT *to = (EP_INIT *)param; // get the stuff copied to process when it was created CORO_BEGIN_CODE(_ctx); @@ -102,7 +102,7 @@ static void FettleEffectPolys(int x, int y, int index, PMACTOR pActor) { epi.hEpoly = hPoly; epi.pActor = pActor; epi.index = index; - ProcessCreate(PID_TCODE, EffectProcess, &epi, sizeof(epi)); + g_scheduler->createProcess(PID_TCODE, EffectProcess, &epi, sizeof(epi)); } } } @@ -110,7 +110,7 @@ static void FettleEffectPolys(int x, int y, int index, PMACTOR pActor) { /** * Just calls FettleEffectPolys() every clock tick. */ -void EffectPolyProcess(CORO_PARAM) { +void EffectPolyProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); diff --git a/engines/tinsel/events.cpp b/engines/tinsel/events.cpp index 311f1c0906..dea699a75d 100644 --- a/engines/tinsel/events.cpp +++ b/engines/tinsel/events.cpp @@ -135,14 +135,14 @@ struct TP_INIT { /** * Runs glitter code associated with a polygon. */ -static void PolyTinselProcess(CORO_PARAM) { +static void PolyTinselProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; PINT_CONTEXT pic; bool took_control; // Set if this function takes control CORO_END_CONTEXT(_ctx); - TP_INIT *to = (TP_INIT *)ProcessGetParamsSelf(); // get the stuff copied to process when it was created + TP_INIT *to = (TP_INIT *)param; // get the stuff copied to process when it was created CORO_BEGIN_CODE(_ctx); @@ -184,13 +184,13 @@ static void PolyTinselProcess(CORO_PARAM) { void RunPolyTinselCode(HPOLYGON hPoly, USER_EVENT event, BUTEVENT be, bool tc) { TP_INIT to = { hPoly, event, be, tc, 0 }; - ProcessCreate(PID_TCODE, PolyTinselProcess, &to, sizeof(to)); + g_scheduler->createProcess(PID_TCODE, PolyTinselProcess, &to, sizeof(to)); } void effRunPolyTinselCode(HPOLYGON hPoly, USER_EVENT event, int actor) { TP_INIT to = { hPoly, event, BE_NONE, false, actor }; - ProcessCreate(PID_TCODE, PolyTinselProcess, &to, sizeof(to)); + g_scheduler->createProcess(PID_TCODE, PolyTinselProcess, &to, sizeof(to)); } //----------------------------------------------------------------------- @@ -203,13 +203,13 @@ struct WP_INIT { /** * Perform a walk directly initiated by a click. */ -static void WalkProcess(CORO_PARAM) { +static void WalkProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; PMACTOR pActor; CORO_END_CONTEXT(_ctx); - WP_INIT *to = (WP_INIT *)ProcessGetParamsSelf(); // get the co-ordinates - copied to process when it was created + WP_INIT *to = (WP_INIT *)param; // get the co-ordinates - copied to process when it was created CORO_BEGIN_CODE(_ctx); @@ -233,7 +233,7 @@ static void WalkProcess(CORO_PARAM) { void walkto(int x, int y) { WP_INIT to = { x, y }; - ProcessCreate(PID_TCODE, WalkProcess, &to, sizeof(to)); + g_scheduler->createProcess(PID_TCODE, WalkProcess, &to, sizeof(to)); } /** diff --git a/engines/tinsel/faders.cpp b/engines/tinsel/faders.cpp index 3b3940fa9c..0018727ccb 100644 --- a/engines/tinsel/faders.cpp +++ b/engines/tinsel/faders.cpp @@ -80,7 +80,7 @@ static void FadePalette(COLORREF *pNew, COLORREF *pOrig, int numColours, uint32 * A pointer to a 'FADE' structure must be passed to this process when * it is created. */ -static void FadeProcess(CORO_PARAM) { +static void FadeProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; COLORREF fadeRGB[MAX_COLOURS]; // local copy of palette @@ -89,7 +89,7 @@ static void FadeProcess(CORO_PARAM) { CORO_END_CONTEXT(_ctx); // get the fade data structure - copied to process when it was created - FADE *pFade = (FADE *)ProcessGetParamsSelf(); + FADE *pFade = (FADE *)param; CORO_BEGIN_CODE(_ctx); @@ -149,7 +149,7 @@ static void Fader(const long multTable[], SCNHANDLE noFadeTable[]) { fade.pPalQ = pPal; // create a fader process for this palette - ProcessCreate(PID_FADER, FadeProcess, (void *)&fade, sizeof(FADE)); + g_scheduler->createProcess(PID_FADER, FadeProcess, (void *)&fade, sizeof(FADE)); } } } diff --git a/engines/tinsel/inventory.cpp b/engines/tinsel/inventory.cpp index 9c07748ab3..aef171c2a2 100644 --- a/engines/tinsel/inventory.cpp +++ b/engines/tinsel/inventory.cpp @@ -932,7 +932,7 @@ struct ITP_INIT { /** * Run inventory item's Glitter code */ -static void InvTinselProcess(CORO_PARAM) { +static void InvTinselProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; PINT_CONTEXT pic; @@ -940,7 +940,7 @@ static void InvTinselProcess(CORO_PARAM) { CORO_END_CONTEXT(_ctx); // get the stuff copied to process when it was created - ITP_INIT *to = (ITP_INIT *)ProcessGetParamsSelf(); + ITP_INIT *to = (ITP_INIT *)param; CORO_BEGIN_CODE(_ctx); @@ -980,7 +980,7 @@ void RunInvTinselCode(PINV_OBJECT pinvo, USER_EVENT event, BUTEVENT be, int inde return; GlitterIndex = index; - ProcessCreate(PID_TCODE, InvTinselProcess, &to, sizeof(to)); + g_scheduler->createProcess(PID_TCODE, InvTinselProcess, &to, sizeof(to)); } /**************************************************************************/ @@ -3005,7 +3005,7 @@ void CloseInventory(void) { /** * Redraws the icons if appropriate. Also handle button press/toggle effects */ -void InventoryProcess(CORO_PARAM) { +void InventoryProcess(CORO_PARAM, const void *) { // COROUTINE CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); @@ -3901,7 +3901,7 @@ void InvPutDown(int index) { InvCursor(IC_DROP, aniX, aniY); } -void InvPdProcess(CORO_PARAM) { +void InvPdProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); @@ -3913,7 +3913,7 @@ void InvPdProcess(CORO_PARAM) { FreeToken(TOKEN_LEFT_BUT); // get the stuff copied to process when it was created - int *pindex = (int *)ProcessGetParamsSelf(); + int *pindex = (int *)param; InvPutDown(*pindex); @@ -3938,7 +3938,7 @@ void InvPickup(int index) { else if (!(invObj->attribute & IO_ONLYINV1 && ino !=INV_1) && !(invObj->attribute & IO_ONLYINV2 && ino !=INV_2)) - ProcessCreate(PID_TCODE, InvPdProcess, &index, sizeof(index)); + g_scheduler->createProcess(PID_TCODE, InvPdProcess, &index, sizeof(index)); } } } diff --git a/engines/tinsel/pcode.cpp b/engines/tinsel/pcode.cpp index 22b7ca8275..9408149ebd 100644 --- a/engines/tinsel/pcode.cpp +++ b/engines/tinsel/pcode.cpp @@ -126,13 +126,13 @@ static PINT_CONTEXT AllocateInterpretContext(GSORT gsort) { for (i = 0, pic = icList; i < MAX_INTERPRET; i++, pic++) { if (pic->GSort == GS_NONE) { - pic->pProc = CurrentProcess(); + pic->pProc = g_scheduler->getCurrentProcess(); pic->GSort = gsort; return pic; } #ifdef DEBUG else { - if (pic->pProc == CurrentProcess()) + if (pic->pProc == g_scheduler->getCurrentProcess()) error("Found unreleased interpret context"); } #endif @@ -241,7 +241,7 @@ PINT_CONTEXT RestoreInterpretContext(PINT_CONTEXT ric) { ic = AllocateInterpretContext(GS_NONE); // Sort will soon be overridden memcpy(ic, ric, sizeof(INT_CONTEXT)); - ic->pProc = CurrentProcess(); + ic->pProc = g_scheduler->getCurrentProcess(); ic->resumeState = RES_1; LockCode(ic); @@ -268,7 +268,7 @@ void RegisterGlobals(int num) { error("Cannot allocate memory for interpret contexts"); } - SetResourceCallback(FreeInterpretContextPr); + g_scheduler->setResourceCallback(FreeInterpretContextPr); } else { // Check size is still the same assert(numGlobals == num); @@ -279,15 +279,11 @@ void RegisterGlobals(int num) { } void FreeGlobals(void) { - if (pGlobals) { - free(pGlobals); - pGlobals = NULL; - } + free(pGlobals); + pGlobals = NULL; - if (icList) { - free(icList); - icList = NULL; - } + free(icList); + icList = NULL; } /** diff --git a/engines/tinsel/pdisplay.cpp b/engines/tinsel/pdisplay.cpp index a51f13e62e..cf7f130ef6 100644 --- a/engines/tinsel/pdisplay.cpp +++ b/engines/tinsel/pdisplay.cpp @@ -92,7 +92,7 @@ static enum { TAGS_OFF, TAGS_ON } TagsActive = TAGS_ON; * This process is only started up if a Glitter showpos() call is made. * Obviously, this is for testing purposes only... */ -void CursorPositionProcess(CORO_PARAM) { +void CursorPositionProcess(CORO_PARAM, const void *) { // COROUTINE CORO_BEGIN_CONTEXT; int prevsX, prevsY; // Last screen top left @@ -503,7 +503,7 @@ static bool PolyTag(SCNHANDLE *pTag, OBJECT **ppText) { * Handle display of tagged actor and polygon tags. * Tagged actor's get priority over polygons. */ -void TagProcess(CORO_PARAM) { +void TagProcess(CORO_PARAM, const void *) { // COROUTINE CORO_BEGIN_CONTEXT; OBJECT *pText; // text object pointer @@ -577,7 +577,7 @@ static void leavingpoly(HPOLYGON hp) { * Maintain the polygons' pointState and tagState flags accordingly. * Also run the polygon's Glitter code when the cursor enters. */ -void PointProcess(CORO_PARAM) { +void PointProcess(CORO_PARAM, const void *) { // COROUTINE CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); diff --git a/engines/tinsel/play.cpp b/engines/tinsel/play.cpp index 9b355a6da9..7c4f6be7e6 100644 --- a/engines/tinsel/play.cpp +++ b/engines/tinsel/play.cpp @@ -361,9 +361,9 @@ void PlayReel(CORO_PARAM, const PPINIT *ppi) { /** * Run all animations that comprise the play film. */ -static void playProcess(CORO_PARAM) { +static void playProcess(CORO_PARAM, const void *param) { // get the stuff copied to process when it was created - PPINIT *ppi = (PPINIT *)ProcessGetParamsSelf(); + PPINIT *ppi = (PPINIT *)param; PlayReel(coroParam, ppi); } @@ -417,7 +417,7 @@ void playFilm(SCNHANDLE film, int x, int y, int actorid, bool splay, int sfact, newestFilm(film, &pfilm->reels[i]); ppi.column = i; - ProcessCreate(PID_REEL, playProcess, &ppi, sizeof(ppi)); + g_scheduler->createProcess(PID_REEL, playProcess, &ppi, sizeof(ppi)); } } @@ -459,7 +459,7 @@ void playFilmc(CORO_PARAM, SCNHANDLE film, int x, int y, int actorid, bool splay newestFilm(film, &pfilm->reels[i]); _ctx->ppi.column = i; - ProcessCreate(PID_REEL, playProcess, &_ctx->ppi, sizeof(PPINIT)); + g_scheduler->createProcess(PID_REEL, playProcess, &_ctx->ppi, sizeof(PPINIT)); } newestFilm(film, &pfilm->reels[0]); @@ -501,7 +501,7 @@ void playThisReel(SCNHANDLE film, short reelnum, short z, int x, int y) { newestFilm(film, &pfilm->reels[reelnum]); // Start display process for the reel - ProcessCreate(PID_REEL, playProcess, &ppi, sizeof(ppi)); + g_scheduler->createProcess(PID_REEL, playProcess, &ppi, sizeof(ppi)); } } // end of namespace Tinsel diff --git a/engines/tinsel/rince.cpp b/engines/tinsel/rince.cpp index fbae8bc6b0..2f8f055472 100644 --- a/engines/tinsel/rince.cpp +++ b/engines/tinsel/rince.cpp @@ -142,8 +142,8 @@ void KillMActor(PMACTOR pActor) { pActor->MActorState = NO_MACTOR; MultiDeleteObject(GetPlayfieldList(FIELD_WORLD), pActor->actorObj); pActor->actorObj = NULL; - assert(CurrentProcess() != pActor->pProc); - ProcessKill(pActor->pProc); + assert(g_scheduler->getCurrentProcess() != pActor->pProc); + g_scheduler->killProcess(pActor->pProc); } } @@ -604,12 +604,12 @@ static void MActorProcessHelper(int X, int Y, int id, PMACTOR pActor) { /** * Moving actor process - 1 per moving actor in current scene. */ -void MActorProcess(CORO_PARAM) { +void MActorProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); - PMACTOR pActor = *(PMACTOR *)ProcessGetParamsSelf(); + PMACTOR pActor = *(PMACTOR *)param; CORO_BEGIN_CODE(_ctx); @@ -633,7 +633,7 @@ void MActorProcess(CORO_PARAM) { void MActorProcessCreate(int X, int Y, int id, PMACTOR pActor) { MActorProcessHelper(X, Y, id, pActor); - pActor->pProc = ProcessCreate(PID_MACTOR, MActorProcess, &pActor, sizeof(PMACTOR)); + pActor->pProc = g_scheduler->createProcess(PID_MACTOR, MActorProcess, &pActor, sizeof(PMACTOR)); } diff --git a/engines/tinsel/savescn.cpp b/engines/tinsel/savescn.cpp index fa6e921a56..a21161e872 100644 --- a/engines/tinsel/savescn.cpp +++ b/engines/tinsel/savescn.cpp @@ -181,7 +181,7 @@ void sortActors(SAVED_DATA *rsd) { void ResumeInterprets(SAVED_DATA *rsd) { // Master script only affected on restore game, not restore scene if (rsd == &sgData) { - KillMatchingProcess(PID_MASTER_SCR, -1); + g_scheduler->killMatchingProcess(PID_MASTER_SCR, -1); FreeMasterInterpretContext(); } diff --git a/engines/tinsel/scene.cpp b/engines/tinsel/scene.cpp index a7d48e2406..ab48e26c4c 100644 --- a/engines/tinsel/scene.cpp +++ b/engines/tinsel/scene.cpp @@ -54,14 +54,14 @@ namespace Tinsel { extern void DropBackground(void); // in EFFECT.C -extern void EffectPolyProcess(CORO_PARAM); +extern void EffectPolyProcess(CORO_PARAM, const void *); // in PDISPLAY.C #ifdef DEBUG -extern void CursorPositionProcess(CORO_PARAM); +extern void CursorPositionProcess(CORO_PARAM, const void *); #endif -extern void TagProcess(CORO_PARAM); -extern void PointProcess(CORO_PARAM); +extern void TagProcess(CORO_PARAM, const void *); +extern void PointProcess(CORO_PARAM, const void *); extern void EnableTags(void); @@ -102,14 +102,14 @@ static SCNHANDLE SceneHandle = 0; // Current scene handle - stored in case of Sa /** * Started up for scene script and entrance script. */ -static void SceneTinselProcess(CORO_PARAM) { +static void SceneTinselProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; PINT_CONTEXT pic; CORO_END_CONTEXT(_ctx); // get the stuff copied to process when it was created - SCNHANDLE *ss = (SCNHANDLE *)ProcessGetParamsSelf(); + SCNHANDLE *ss = (SCNHANDLE *)param; assert(*ss); // Must have some code to run CORO_BEGIN_CODE(_ctx); @@ -154,7 +154,7 @@ static void LoadScene(SCNHANDLE scene, int entry) { for (i = 0; i < FROM_LE_32(ss->numEntrance); i++, es++) { if (FROM_LE_32(es->eNumber) == (uint)entry) { if (es->hScript) - ProcessCreate(PID_TCODE, SceneTinselProcess, &es->hScript, sizeof(es->hScript)); + g_scheduler->createProcess(PID_TCODE, SceneTinselProcess, &es->hScript, sizeof(es->hScript)); break; } } @@ -163,7 +163,7 @@ static void LoadScene(SCNHANDLE scene, int entry) { error("Non-existant scene entry number"); if (ss->hSceneScript) - ProcessCreate(PID_TCODE, SceneTinselProcess, &ss->hSceneScript, sizeof(ss->hSceneScript)); + g_scheduler->createProcess(PID_TCODE, SceneTinselProcess, &ss->hSceneScript, sizeof(ss->hSceneScript)); } // Default refer type @@ -200,14 +200,13 @@ void EndScene(void) { KillAllObjects(); // kill all destructable process - KillMatchingProcess(PID_DESTROY, PID_DESTROY); + g_scheduler->killMatchingProcess(PID_DESTROY, PID_DESTROY); } /** * */ -void PrimeBackground(void) -{ +void PrimeBackground(void) { // structure for playfields static PLAYFIELD playfield[] = { { // FIELD WORLD @@ -257,16 +256,16 @@ void PrimeScene(void) { RestartCursor(); // Restart the cursor EnableTags(); // Next scene with tags enabled - ProcessCreate(PID_SCROLL, ScrollProcess, NULL, 0); - ProcessCreate(PID_SCROLL, EffectPolyProcess, NULL, 0); + g_scheduler->createProcess(PID_SCROLL, ScrollProcess, NULL, 0); + g_scheduler->createProcess(PID_SCROLL, EffectPolyProcess, NULL, 0); #ifdef DEBUG if (ShowPosition) - ProcessCreate(PID_POSITION, CursorPositionProcess, NULL, 0); + g_scheduler->createProcess(PID_POSITION, CursorPositionProcess, NULL, 0); #endif - ProcessCreate(PID_TAG, TagProcess, NULL, 0); - ProcessCreate(PID_TAG, PointProcess, NULL, 0); + g_scheduler->createProcess(PID_TAG, TagProcess, NULL, 0); + g_scheduler->createProcess(PID_TAG, PointProcess, NULL, 0); // init the current background PrimeBackground(); diff --git a/engines/tinsel/sched.cpp b/engines/tinsel/sched.cpp index 0371449eb1..72cfeaf6b0 100644 --- a/engines/tinsel/sched.cpp +++ b/engines/tinsel/sched.cpp @@ -30,36 +30,51 @@ namespace Tinsel { +Scheduler *g_scheduler = 0; -/** list of all processes */ -static PROCESS *processList = 0; +/** process structure */ +struct PROCESS { + PROCESS *pNext; //!< pointer to next process in active or free list -/** active process list - also saves scheduler state */ -static PROCESS active; + CoroContext state; //!< the state of the coroutine + CORO_ADDR coroAddr; //!< the entry point of the coroutine -/** pointer to free process list */ -static PROCESS *pFreeProcesses = 0; + int sleepTime; //!< number of scheduler cycles to sleep + int pid; //!< process ID + char param[PARAM_SIZE]; //!< process specific info +}; -/** the currently active process */ -static PROCESS *pCurrent = 0; + +Scheduler::Scheduler() { + processList = 0; + pFreeProcesses = 0; + pCurrent = 0; #ifdef DEBUG -// diagnostic process counters -static int numProcs = 0; -static int maxProcs = 0; + // diagnostic process counters + numProcs = 0; + maxProcs = 0; #endif -/** - * Called from ProcessKill() to enable other resources - * a process may be allocated to be released. - */ -static VFPTRPP pRCfunction = 0; + pRCfunction = 0; + + active = new PROCESS; + + g_scheduler = this; // FIXME HACK +} +Scheduler::~Scheduler() { + free(processList); + processList = NULL; + + delete active; + active = 0; +} /** * Kills all processes and places them on the free list. */ -void InitScheduler(void) { +void Scheduler::reset() { #ifdef DEBUG // clear number of process in use @@ -80,7 +95,7 @@ void InitScheduler(void) { } // no active processes - pCurrent = active.pNext = NULL; + pCurrent = active->pNext = NULL; // place first process on free list pFreeProcesses = processList; @@ -94,19 +109,12 @@ void InitScheduler(void) { processList[NUM_PROCESS - 1].pNext = NULL; } -void FreeProcessList(void) { - if (processList) { - free(processList); - processList = NULL; - } -} - #ifdef DEBUG /** * Shows the maximum number of process used at once. */ -void ProcessStats(void) { +void Scheduler::printStats(void) { printf("%i process of %i used.\n", maxProcs, NUM_PROCESS); } #endif @@ -115,19 +123,19 @@ void ProcessStats(void) { /** * Give all active processes a chance to run */ -void Scheduler(void) { +void Scheduler::schedule(void) { // start dispatching active process list - PROCESS *pPrevProc = &active; - PROCESS *pProc = active.pNext; + PROCESS *pPrevProc = active; + PROCESS *pProc = active->pNext; while (pProc != NULL) { if (--pProc->sleepTime <= 0) { // process is ready for dispatch, activate it pCurrent = pProc; - pProc->coroAddr(pProc->state); + pProc->coroAddr(pProc->state, pProc->param); pCurrent = NULL; if (!pProc->state || pProc->state->_sleep <= 0) { // Coroutine finished - ProcessKill(pProc); + killProcess(pProc); pProc = pPrevProc; } else { pProc->sleepTime = pProc->state->_sleep; @@ -147,7 +155,7 @@ void Scheduler(void) { * @param pParam process specific info * @param sizeParam size of process specific info */ -PROCESS *ProcessCreate(int pid, CORO_ADDR coroAddr, const void *pParam, int sizeParam) { +PROCESS *Scheduler::createProcess(int pid, CORO_ADDR coroAddr, const void *pParam, int sizeParam) { PROCESS *pProc; // get a free process @@ -172,8 +180,8 @@ PROCESS *ProcessCreate(int pid, CORO_ADDR coroAddr, const void *pParam, int size // make this new process the next active process pCurrent->pNext = pProc; } else { // no active processes, place process at head of list - pProc->pNext = active.pNext; - active.pNext = pProc; + pProc->pNext = active->pNext; + active->pNext = pProc; } // set coroutine entry point @@ -206,13 +214,13 @@ PROCESS *ProcessCreate(int pid, CORO_ADDR coroAddr, const void *pParam, int size * * @param pKillProc which process to kill */ -void ProcessKill(PROCESS *pKillProc) { +void Scheduler::killProcess(PROCESS *pKillProc) { PROCESS *pProc, *pPrev; // process list pointers // make sure a valid process pointer assert(pKillProc >= processList && pKillProc <= processList + NUM_PROCESS - 1); - // can not kill the current process using ProcessKill ! + // can not kill the current process using killProcess ! assert(pCurrent != pKillProc); #ifdef DEBUG @@ -222,7 +230,7 @@ void ProcessKill(PROCESS *pKillProc) { #endif // search the active list for the process - for (pProc = active.pNext, pPrev = &active; pProc != NULL; pPrev = pProc, pProc = pProc->pNext) { + for (pProc = active->pNext, pPrev = active; pProc != NULL; pPrev = pProc, pProc = pProc->pNext) { if (pProc == pKillProc) { // found process in active list @@ -246,7 +254,7 @@ void ProcessKill(PROCESS *pKillProc) { } // process not found in active list if we get to here - error("ProcessKill(): tried to kill a process not in the list of active processes"); + error("killProcess(): tried to kill a process not in the list of active processes"); } @@ -254,25 +262,18 @@ void ProcessKill(PROCESS *pKillProc) { /** * Returns a pointer to the currently running process. */ -PROCESS *CurrentProcess(void) { +PROCESS *Scheduler::getCurrentProcess(void) { return pCurrent; } -char *ProcessGetParamsSelf() { - PROCESS *pProc = pCurrent; - - // make sure a valid process pointer - assert(pProc >= processList && pProc <= processList + NUM_PROCESS - 1); - - return pProc->param; -} - /** * Returns the process identifier of the specified process. * * @param pProc which process */ -int ProcessGetPID(PROCESS *pProc) { +int Scheduler::getCurrentPID() const { + PROCESS *pProc = pCurrent; + // make sure a valid process pointer assert(pProc >= processList && pProc <= processList + NUM_PROCESS - 1); @@ -288,11 +289,11 @@ int ProcessGetPID(PROCESS *pProc) { * @param pidMask mask to apply to process identifiers before comparison * @return The number of processes killed is returned. */ -int KillMatchingProcess(int pidKill, int pidMask) { +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) { + for (pProc = active->pNext, pPrev = active; pProc != NULL; pPrev = pProc, pProc = pProc->pNext) { if ((pProc->pid & pidMask) == pidKill) { // found a matching process @@ -329,15 +330,15 @@ int KillMatchingProcess(int pidKill, int pidMask) { /** - * Set pointer to a function to be called by ProcessKill(). + * Set pointer to a function to be called by killProcess(). * * May be called by a resource allocator, the function supplied is - * called by ProcessKill() to allow the resource allocator to free + * called by killProcess() to allow the resource allocator to free * resources allocated to the dying process. * - * @param pFunc Function to be called by ProcessKill() + * @param pFunc Function to be called by killProcess() */ -void SetResourceCallback(VFPTRPP pFunc) { +void Scheduler::setResourceCallback(VFPTRPP pFunc) { pRCfunction = pFunc; } diff --git a/engines/tinsel/sched.h b/engines/tinsel/sched.h index 51074b5c7d..0d90b3bb9f 100644 --- a/engines/tinsel/sched.h +++ b/engines/tinsel/sched.h @@ -38,62 +38,72 @@ namespace Tinsel { // the maximum number of processes #define NUM_PROCESS 64 -typedef void (*CORO_ADDR)(CoroContext &); +typedef void (*CORO_ADDR)(CoroContext &, const void *); -// process structure +struct PROCESS; -struct PROCESS { - PROCESS *pNext; // pointer to next 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 -}; - - -/*----------------------------------------------------------------------*\ -|* Scheduler Function Prototypes *| -\*----------------------------------------------------------------------*/ - -void InitScheduler(void); // called to init scheduler - kills all processes and places them on free list - -void FreeProcessList(void); - -#ifdef DEBUG -void ProcessStats(void); // Shows the maximum number of process used at once +/** + * 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; #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(); + + 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); + + + void setResourceCallback(VFPTRPP pFunc); -void Scheduler(void); // called to start process dispatching - -PROCESS *ProcessCreate(int pid, CORO_ADDR coroAddr, const void *pParam, int sizeParam); - -void ProcessKill( // kill a process - PROCESS *pKillProc); // which process to kill (must be different from current one) - -PROCESS *CurrentProcess(void); // Returns a pointer to the currently running process - -int ProcessGetPID( // Returns the process identifier of the specified process - PROCESS *pProc); // which process - -char *ProcessGetParamsSelf(); - -int KillMatchingProcess( // kill any process matching the pid parameters - int pidKill, // process identifier of process to kill - int pidMask); // mask to apply to process identifiers before comparison - - -// Pointer to a function of the form "void function(PPROCESS)" -typedef void (*VFPTRPP)(PROCESS *); - -void SetResourceCallback(VFPTRPP pFunc); // May be called by a resource allocator, - // the function supplied is called by ProcessKill() - // to allow the resource allocator to free resources - // allocated to the dying process. +}; +extern Scheduler *g_scheduler; // FIXME: Temporary global var, to be used until everything has been OOifyied } // end of namespace Tinsel diff --git a/engines/tinsel/scroll.cpp b/engines/tinsel/scroll.cpp index 7c0b12730f..aa1bc67298 100644 --- a/engines/tinsel/scroll.cpp +++ b/engines/tinsel/scroll.cpp @@ -352,7 +352,7 @@ static void MonitorScroll(void) { /** * Decide when to scroll and scroll when decided to. */ -void ScrollProcess(CORO_PARAM) { +void ScrollProcess(CORO_PARAM, const void *) { // COROUTINE CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); diff --git a/engines/tinsel/scroll.h b/engines/tinsel/scroll.h index 02ce2afd5b..ac903157f2 100644 --- a/engines/tinsel/scroll.h +++ b/engines/tinsel/scroll.h @@ -62,7 +62,7 @@ void DoScrollCursor(void); void SetNoScroll(int x1, int y1, int x2, int y2); void DropNoScrolls(void); -void ScrollProcess(CORO_PARAM); +void ScrollProcess(CORO_PARAM, const void *); void ScrollFocus(int actor); void ScrollTo(int x, int y, int iter); diff --git a/engines/tinsel/tinlib.cpp b/engines/tinsel/tinlib.cpp index a07a16a205..84904e5138 100644 --- a/engines/tinsel/tinlib.cpp +++ b/engines/tinsel/tinlib.cpp @@ -768,7 +768,7 @@ void newscene(CORO_PARAM, SCNHANDLE scene, int entrance, int transition) { #endif // Prevent code subsequent to this call running before scene changes - if (ProcessGetPID(CurrentProcess()) != PID_MASTER_SCR) + if (g_scheduler->getCurrentPID() != PID_MASTER_SCR) CORO_KILL_SELF(); CORO_END_CODE; } diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp index 76324e8272..8cfc6d7d4d 100644 --- a/engines/tinsel/tinsel.cpp +++ b/engines/tinsel/tinsel.cpp @@ -71,13 +71,13 @@ extern void SetDoFadeIn(bool tf); extern void DropBackground(void); // In CURSOR.CPP -extern void CursorProcess(CORO_PARAM); +extern void CursorProcess(CORO_PARAM, const void *); // In INVENTORY.CPP -extern void InventoryProcess(CORO_PARAM); +extern void InventoryProcess(CORO_PARAM, const void *); // In SCENE.CPP -extern void PrimeBackground( void ); +extern void PrimeBackground(); extern void NewScene(SCNHANDLE scene, int entry); extern SCNHANDLE GetSceneHandle(void); @@ -111,8 +111,6 @@ static Scene DelayedScene = { 0, 0, 0 }; static bool bHookSuspend = false; -static uint32 lastLeftClick = 0, lastRightClick = 0; - static PROCESS *pMouseProcess = 0; static PROCESS *pKeyboardProcess = 0; @@ -127,7 +125,7 @@ Common::List<Common::Event> keypresses; /** * Process to handle keypresses */ -void KeyboardProcess(CORO_PARAM) { +void KeyboardProcess(CORO_PARAM, const void *) { // COROUTINE CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); @@ -275,17 +273,19 @@ void KeyboardProcess(CORO_PARAM) { /** * Process to handle changes in the mouse buttons. */ -void MouseProcess(CORO_PARAM) { +void MouseProcess(CORO_PARAM, const void *) { // COROUTINE CORO_BEGIN_CONTEXT; bool lastLWasDouble; bool lastRWasDouble; + uint32 lastLeftClick, lastRightClick; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); _ctx->lastLWasDouble = false; _ctx->lastRWasDouble = false; + _ctx->lastLeftClick = _ctx->lastRightClick = DwGetCurrentTime(); while (true) { // FIXME: I'm still keeping the ctrl/Alt handling in the ProcessKeyEvent method. @@ -305,7 +305,7 @@ void MouseProcess(CORO_PARAM) { switch (type) { case Common::EVENT_LBUTTONDOWN: // left button press - if (DwGetCurrentTime() - lastLeftClick < (uint32)dclickSpeed) { + if (DwGetCurrentTime() - _ctx->lastLeftClick < (uint32)dclickSpeed) { // signal left drag start ProcessButEvent(BE_LDSTART); @@ -329,9 +329,9 @@ void MouseProcess(CORO_PARAM) { // update click timer if (_ctx->lastLWasDouble == false) - lastLeftClick = DwGetCurrentTime(); + _ctx->lastLeftClick = DwGetCurrentTime(); else - lastLeftClick -= dclickSpeed; + _ctx->lastLeftClick -= dclickSpeed; // signal left drag end ProcessButEvent(BE_LDEND); @@ -340,7 +340,7 @@ void MouseProcess(CORO_PARAM) { case Common::EVENT_RBUTTONDOWN: // right button press - if (DwGetCurrentTime() - lastRightClick < (uint32)dclickSpeed) { + if (DwGetCurrentTime() - _ctx->lastRightClick < (uint32)dclickSpeed) { // signal right drag start ProcessButEvent(BE_RDSTART); @@ -364,9 +364,9 @@ void MouseProcess(CORO_PARAM) { // update click timer if (_ctx->lastRWasDouble == false) - lastRightClick = DwGetCurrentTime(); + _ctx->lastRightClick = DwGetCurrentTime(); else - lastRightClick -= dclickSpeed; + _ctx->lastRightClick -= dclickSpeed; // signal right drag end ProcessButEvent(BE_RDEND); @@ -380,30 +380,10 @@ void MouseProcess(CORO_PARAM) { } /** - * Installs the event driver processes - */ - -void EventsInstall(void) { - lastLeftClick = lastRightClick = DwGetCurrentTime(); - - pMouseProcess = ProcessCreate(PID_MOUSE, MouseProcess, NULL, 0); - pKeyboardProcess = ProcessCreate(PID_KEYBOARD, KeyboardProcess, NULL, 0); -} - -/** - * Removes the event driver processes - */ - -void EventsUninstall(void) { - ProcessKill(pMouseProcess); - ProcessKill(pKeyboardProcess); -} - -/** * Run the master script. * Continues between scenes, or until Interpret() returns. */ -static void MasterScriptProcess(CORO_PARAM) { +static void MasterScriptProcess(CORO_PARAM, const void *) { // COROUTINE CORO_BEGIN_CONTEXT; PINT_CONTEXT pic; @@ -480,7 +460,7 @@ void syncSCdata(Serializer &s) { //----------------------------------------------------------------------- -static void RestoredProcess(CORO_PARAM) { +static void RestoredProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; PINT_CONTEXT pic; @@ -489,7 +469,7 @@ static void RestoredProcess(CORO_PARAM) { CORO_BEGIN_CODE(_ctx); // get the stuff copied to process when it was created - _ctx->pic = *((PINT_CONTEXT *)ProcessGetParamsSelf()); + _ctx->pic = *((PINT_CONTEXT *)param); _ctx->pic = RestoreInterpretContext(_ctx->pic); CORO_INVOKE_1(Interpret, _ctx->pic); @@ -498,11 +478,11 @@ static void RestoredProcess(CORO_PARAM) { } void RestoreProcess(PINT_CONTEXT pic) { - ProcessCreate(PID_TCODE, RestoredProcess, &pic, sizeof(pic)); + g_scheduler->createProcess(PID_TCODE, RestoredProcess, &pic, sizeof(pic)); } void RestoreMasterProcess(PINT_CONTEXT pic) { - ProcessCreate(PID_MASTER_SCR, RestoredProcess, &pic, sizeof(pic)); + g_scheduler->createProcess(PID_MASTER_SCR, RestoredProcess, &pic, sizeof(pic)); } // FIXME: CountOut is used by ChangeScene @@ -670,7 +650,7 @@ TinselEngine::~TinselEngine() { FreeActors(); FreeObjectList(); FreeGlobals(); - FreeProcessList(); + delete _scheduler; } int TinselEngine::init() { @@ -685,6 +665,8 @@ int TinselEngine::init() { g_system->getEventManager()->registerRandomSource(_random, "tinsel"); _console = new Console(); + + _scheduler = new Scheduler(); // init memory manager MemoryInit(); @@ -818,7 +800,7 @@ void TinselEngine::NextGameCycle(void) { ResetEcount(); // schedule process - Scheduler(); + _scheduler->schedule(); // redraw background DrawBackgnd(); @@ -870,11 +852,11 @@ bool TinselEngine::pollEvent() { void TinselEngine::CreateConstProcesses(void) { // Process to run the master script - ProcessCreate(PID_MASTER_SCR, MasterScriptProcess, NULL, 0); + _scheduler->createProcess(PID_MASTER_SCR, MasterScriptProcess, NULL, 0); // Processes to run the cursor and inventory, - ProcessCreate(PID_CURSOR, CursorProcess, NULL, 0); - ProcessCreate(PID_INVENTORY, InventoryProcess, NULL, 0); + _scheduler->createProcess(PID_CURSOR, CursorProcess, NULL, 0); + _scheduler->createProcess(PID_INVENTORY, InventoryProcess, NULL, 0); } /** @@ -926,10 +908,11 @@ void TinselEngine::RestartDrivers(void) { KillAllObjects(); // init the process scheduler - InitScheduler(); + _scheduler->reset(); // init the event handlers - EventsInstall(); + pMouseProcess = _scheduler->createProcess(PID_MOUSE, MouseProcess, NULL, 0); + pKeyboardProcess = _scheduler->createProcess(PID_KEYBOARD, KeyboardProcess, NULL, 0); // install sound driver SoundInit(); @@ -947,7 +930,8 @@ void TinselEngine::ChopDrivers(void) { SoundDeinit(); // remove event drivers - EventsUninstall(); + _scheduler->killProcess(pMouseProcess); + _scheduler->killProcess(pKeyboardProcess); } /** diff --git a/engines/tinsel/tinsel.h b/engines/tinsel/tinsel.h index 9370ba6817..6b838924e8 100644 --- a/engines/tinsel/tinsel.h +++ b/engines/tinsel/tinsel.h @@ -43,6 +43,7 @@ namespace Tinsel { class MusicPlayer; +class Scheduler; class SoundManager; enum TinselGameID { @@ -79,6 +80,8 @@ class TinselEngine : public ::Engine { Common::Point _mousePos; uint8 _dosPlayerDir; Console *_console; + Scheduler *_scheduler; + protected: int init(); diff --git a/engines/tinsel/token.cpp b/engines/tinsel/token.cpp index e50290c3f0..0bdac0d6eb 100644 --- a/engines/tinsel/token.cpp +++ b/engines/tinsel/token.cpp @@ -53,7 +53,7 @@ static void TerminateProcess(PROCESS *tProc) { } // Kill the process - ProcessKill(tProc); + g_scheduler->killProcess(tProc); } /** @@ -63,7 +63,7 @@ void GetControlToken() { const int which = TOKEN_CONTROL; if (tokens[which].proc == NULL) { - tokens[which].proc = CurrentProcess(); + tokens[which].proc = g_scheduler->getCurrentProcess(); } } @@ -88,11 +88,11 @@ void GetToken(int which) { assert(TOKEN_LEAD <= which && which < NUMTOKENS); if (tokens[which].proc != NULL) { - assert(tokens[which].proc != CurrentProcess()); + assert(tokens[which].proc != g_scheduler->getCurrentProcess()); TerminateProcess(tokens[which].proc); } - tokens[which].proc = CurrentProcess(); + tokens[which].proc = g_scheduler->getCurrentProcess(); } /** @@ -102,7 +102,7 @@ void GetToken(int which) { void FreeToken(int which) { assert(TOKEN_LEAD <= which && which < NUMTOKENS); - assert(tokens[which].proc == CurrentProcess()); // we'd have been killed if some other proc had taken this token + assert(tokens[which].proc == g_scheduler->getCurrentProcess()); // we'd have been killed if some other proc had taken this token tokens[which].proc = NULL; } |