aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/tinsel/actors.cpp12
-rw-r--r--engines/tinsel/bg.cpp6
-rw-r--r--engines/tinsel/coroutine.h69
-rw-r--r--engines/tinsel/cursor.cpp2
-rw-r--r--engines/tinsel/effect.cpp8
-rw-r--r--engines/tinsel/events.cpp14
-rw-r--r--engines/tinsel/faders.cpp6
-rw-r--r--engines/tinsel/inventory.cpp14
-rw-r--r--engines/tinsel/pcode.cpp20
-rw-r--r--engines/tinsel/pdisplay.cpp6
-rw-r--r--engines/tinsel/play.cpp10
-rw-r--r--engines/tinsel/rince.cpp10
-rw-r--r--engines/tinsel/savescn.cpp2
-rw-r--r--engines/tinsel/scene.cpp31
-rw-r--r--engines/tinsel/sched.cpp111
-rw-r--r--engines/tinsel/sched.h110
-rw-r--r--engines/tinsel/scroll.cpp2
-rw-r--r--engines/tinsel/scroll.h2
-rw-r--r--engines/tinsel/tinlib.cpp2
-rw-r--r--engines/tinsel/tinsel.cpp76
-rw-r--r--engines/tinsel/tinsel.h3
-rw-r--r--engines/tinsel/token.cpp10
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;
}