TINSEL: Refactored Tinsel engine to use the Common coroutine scheduler
This commit is contained in:
parent
c6810c174e
commit
41692ef48a
32 changed files with 137 additions and 777 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -361,7 +361,7 @@ byte *LockMem(SCNHANDLE offset) {
|
|||
|
||||
if (TinselV2) {
|
||||
SetCD(pH->flags2 & fAllCds);
|
||||
CdCD(nullContext);
|
||||
CdCD(Common::nullContext);
|
||||
}
|
||||
LoadFile(pH);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ MODULE_OBJS := \
|
|||
bmv.o \
|
||||
cliprect.o \
|
||||
config.o \
|
||||
coroutine.o \
|
||||
cursor.o \
|
||||
debugger.o \
|
||||
detection.o \
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 *|
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue