aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/tony/adv.h3
-rw-r--r--engines/tony/custom.cpp61
-rw-r--r--engines/tony/game.cpp4
-rw-r--r--engines/tony/gfxengine.cpp37
-rw-r--r--engines/tony/gfxengine.h2
-rw-r--r--engines/tony/mpal/mpal.cpp310
-rw-r--r--engines/tony/mpal/mpal.h3
-rw-r--r--engines/tony/sched.cpp19
-rw-r--r--engines/tony/sched.h8
-rw-r--r--engines/tony/tonychar.cpp32
-rw-r--r--engines/tony/tonychar.h5
11 files changed, 284 insertions, 200 deletions
diff --git a/engines/tony/adv.h b/engines/tony/adv.h
index 6d675c2bbe..056934e932 100644
--- a/engines/tony/adv.h
+++ b/engines/tony/adv.h
@@ -49,6 +49,7 @@
#define TONY_ADV_H
#include "tony/mpal/memory.h"
+#include "tony/coroutine.h"
#include "tony/gfxcore.h"
@@ -91,7 +92,7 @@ enum RMTonyAction {
// Funzioni globali
HANDLE MainLoadLocation(int nLoc, RMPoint pt, RMPoint start);
-HANDLE MainUnloadLocation(bool bDoOnExit);
+void MainUnloadLocation(CORO_PARAM, bool bDoOnExit, HANDLE *result);
void MainLinkGraphicTask(RMGfxTask *task);
void MainFreeze(void);
void MainUnfreeze(void);
diff --git a/engines/tony/custom.cpp b/engines/tony/custom.cpp
index 1d28fa9ece..2683634012 100644
--- a/engines/tony/custom.cpp
+++ b/engines/tony/custom.cpp
@@ -72,7 +72,7 @@ RMInventory *Inventory;
RMInput *Input;
HANDLE (*LoadLocation)(int, RMPoint, RMPoint start);
-HANDLE (*UnloadLocation)(bool bDoOnExit);
+void (*UnloadLocation)(CORO_PARAM, bool bDoOnExit, HANDLE *result);
void (*LinkGraphicTask)(RMGfxTask *task);
void (*Freeze)(void);
void (*Unfreeze)(void);
@@ -505,20 +505,27 @@ RMPoint SFM_pt;
int SFM_nLoc;
DECLARE_CUSTOM_FUNCTION(SendFullscreenMsgStart)(CORO_PARAM, uint32 nMsg, uint32 nFont, uint32, uint32) {
- RMMessage msg(nMsg);
- RMGfxClearTask clear;
- int i;
+ CORO_BEGIN_CONTEXT;
+ RMMessage *msg;
+ RMGfxClearTask clear;
+ int i;
+ CORO_END_CONTEXT(_ctx);
+
+ CORO_BEGIN_CODE(_ctx);
+
+ _ctx->msg = new RMMessage(nMsg);
SFM_nLoc = Loc->TEMPGetNumLoc();
SFM_pt = Tony->Position();
- if (bSkipIdle) return;
+ if (bSkipIdle)
+ return;
- UnloadLocation(false);
+ CORO_INVOKE_2(UnloadLocation, false, NULL);
Tony->Hide();
Unfreeze();
- for (i = 0; i < msg.NumPeriods() && !bSkipIdle; i++) {
+ for (_ctx->i = 0; _ctx->i < _ctx->msg->NumPeriods() && !bSkipIdle; _ctx->i++) {
RMTextDialog text;
text.SetInput(Input);
@@ -533,25 +540,29 @@ DECLARE_CUSTOM_FUNCTION(SendFullscreenMsgStart)(CORO_PARAM, uint32 nMsg, uint32
text.SetColor(255,255,255);
// Scrive il testo
- if (nFont== 0)
- text.WriteText(msg[i],1);
- else if (nFont==1)
- text.WriteText(msg[i],0);
+ if (nFont == 0)
+ text.WriteText((*_ctx->msg)[_ctx->i], 1);
+ else if (nFont == 1)
+ text.WriteText((*_ctx->msg)[_ctx->i], 0);
// Setta la posizione
- text.SetPosition(RMPoint(320,240));
+ text.SetPosition(RMPoint(320, 240));
text.SetAlwaysDisplay();
text.ForceTime();
// Registra il testo
- LinkGraphicTask(&clear);
+ LinkGraphicTask(&_ctx->clear);
LinkGraphicTask(&text);
// Aspetta la fine della visualizzazione
text.SetCustomSkipHandle(hSkipIdle);
text.WaitForEndDisplay();
}
+
+ delete _ctx->msg;
+
+ CORO_END_CODE;
}
DECLARE_CUSTOM_FUNCTION(ClearScreen)(CORO_PARAM, uint32, uint32, uint32, uint32) {
@@ -592,6 +603,11 @@ DECLARE_CUSTOM_FUNCTION(NoOcchioDiBue)(CORO_PARAM, uint32, uint32, uint32, uint3
}
DECLARE_CUSTOM_FUNCTION(CloseLocation)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+ CORO_BEGIN_CONTEXT;
+ CORO_END_CONTEXT(_ctx);
+
+ CORO_BEGIN_CODE(_ctx);
+
if (!bNoOcchioDiBue) {
InitWipe(1);
WaitWipeEnd();
@@ -600,13 +616,19 @@ DECLARE_CUSTOM_FUNCTION(CloseLocation)(CORO_PARAM, uint32, uint32, uint32, uint3
_vm->StopMusic(4);
// On Exit e lascia freezzato
- UnloadLocation(true);
+ CORO_INVOKE_2(UnloadLocation, true, NULL);
Unfreeze();
+
+ CORO_END_CODE;
}
DECLARE_CUSTOM_FUNCTION(ChangeLocation)(CORO_PARAM, uint32 nLoc, uint32 tX, uint32 tY, uint32 bUseStartPos) {
- HANDLE h;
+ CORO_BEGIN_CONTEXT;
+ HANDLE h;
+ CORO_END_CONTEXT(_ctx);
+
+ CORO_BEGIN_CODE(_ctx);
if (!bNoOcchioDiBue) {
InitWipe(1);
@@ -618,7 +640,7 @@ DECLARE_CUSTOM_FUNCTION(ChangeLocation)(CORO_PARAM, uint32 nLoc, uint32 tX, uint
}
// On Exit e lascia freezzato
- UnloadLocation(true);
+ CORO_INVOKE_2(UnloadLocation, true, NULL);
curChangedHotspot = 0;
if (bUseStartPos != 0)
@@ -639,7 +661,7 @@ DECLARE_CUSTOM_FUNCTION(ChangeLocation)(CORO_PARAM, uint32 nLoc, uint32 tX, uint
Unfreeze();
- h = mpalQueryDoAction(0, nLoc,0);
+ _ctx->h = mpalQueryDoAction(0, nLoc, 0);
if (!bNoOcchioDiBue) {
WaitWipeEnd();
@@ -649,9 +671,10 @@ DECLARE_CUSTOM_FUNCTION(ChangeLocation)(CORO_PARAM, uint32 nLoc, uint32 tX, uint
bNoOcchioDiBue = false;
// On Enter?
- if (h != INVALID_HANDLE_VALUE)
- WaitForSingleObject(h,INFINITE);
+ if (_ctx->h != INVALID_HANDLE_VALUE)
+ WaitForSingleObject(_ctx->h, INFINITE);
+ CORO_END_CODE;
}
DECLARE_CUSTOM_FUNCTION(SetLocStartPosition)(CORO_PARAM, uint32 nLoc, uint32 lX, uint32 lY, uint32) {
diff --git a/engines/tony/game.cpp b/engines/tony/game.cpp
index 03cc80d93d..4eef8b0c96 100644
--- a/engines/tony/game.cpp
+++ b/engines/tony/game.cpp
@@ -96,8 +96,8 @@ HANDLE MainLoadLocation(int nLoc, RMPoint pt, RMPoint start) {
return _vm->GetEngine()->LoadLocation(nLoc, pt,start);
}
-HANDLE MainUnloadLocation(bool bDoOnExit) {
- return _vm->GetEngine()->UnloadLocation(bDoOnExit);
+void MainUnloadLocation(CORO_PARAM, bool bDoOnExit, HANDLE *result) {
+ _vm->GetEngine()->UnloadLocation(coroParam, bDoOnExit, result);
}
void MainLinkGraphicTask(RMGfxTask *task) {
diff --git a/engines/tony/gfxengine.cpp b/engines/tony/gfxengine.cpp
index f98942403d..1858221350 100644
--- a/engines/tony/gfxengine.cpp
+++ b/engines/tony/gfxengine.cpp
@@ -65,13 +65,21 @@ extern bool bSkipSfxNoLoop;
bool bIdleExited;
-void ExitAllIdles(int nCurLoc) {
+void ExitAllIdles(CORO_PARAM, int nCurLoc) {
+ CORO_BEGIN_CONTEXT;
+ CORO_END_CONTEXT(_ctx);
+
+ CORO_BEGIN_CODE(_ctx);
+
// Chiude le idle
bSkipSfxNoLoop = true;
- mpalEndIdlePoll(nCurLoc);
+
+ CORO_INVOKE_2(mpalEndIdlePoll, nCurLoc, NULL);
+
bIdleExited = true;
bSkipSfxNoLoop = false;
- ExitThread(0);
+
+ CORO_END_CODE;
}
RMGfxEngine::RMGfxEngine() {
@@ -514,17 +522,21 @@ HANDLE RMGfxEngine::LoadLocation(int nLoc, RMPoint ptTonyStart, RMPoint start) {
return INVALID_HANDLE_VALUE; //mpalQueryDoAction(0,m_nCurLoc,0);
}
-HANDLE RMGfxEngine::UnloadLocation(bool bDoOnExit) {
- HANDLE h;
+void RMGfxEngine::UnloadLocation(CORO_PARAM, bool bDoOnExit, HANDLE *result) {
+ CORO_BEGIN_CONTEXT;
+ HANDLE h;
+ CORO_END_CONTEXT(_ctx);
+
+ CORO_BEGIN_CODE(_ctx);
// Scarica tutta la memoria della locazione
- mpalEndIdlePoll(m_nCurLoc);
+ CORO_INVOKE_2(mpalEndIdlePoll, m_nCurLoc, NULL);
// On Exit?
if (bDoOnExit) {
- h = mpalQueryDoAction(1, m_nCurLoc, 0);
- if (h != INVALID_HANDLE_VALUE)
- WaitForSingleObject(h, INFINITE);
+ _ctx->h = mpalQueryDoAction(1, m_nCurLoc, 0);
+ if (_ctx->h != INVALID_HANDLE_VALUE)
+ WaitForSingleObject(_ctx->h, INFINITE);
}
MainFreeze();
@@ -534,7 +546,10 @@ HANDLE RMGfxEngine::UnloadLocation(bool bDoOnExit) {
m_bigBuf.ClearOT();
m_loc.Unload();
- return INVALID_HANDLE_VALUE;
+ if (result != NULL)
+ *result = INVALID_HANDLE_VALUE;
+
+ CORO_END_CODE;
}
void RMGfxEngine::Init(/*HINSTANCE hInst*/) {
@@ -930,7 +945,7 @@ void RMGfxEngine::LoadState(const char *fn) {
delete f;
- UnloadLocation(false);
+ UnloadLocation(nullContext, false, NULL);
LoadLocation(loc,tp,RMPoint(-1, -1));
m_tony.SetPattern(RMTony::PAT_STANDRIGHT);
MainUnfreeze();
diff --git a/engines/tony/gfxengine.h b/engines/tony/gfxengine.h
index 2019cf01c9..42b2050046 100644
--- a/engines/tony/gfxengine.h
+++ b/engines/tony/gfxengine.h
@@ -138,7 +138,7 @@ public:
// Manage a location
HANDLE LoadLocation(int nLoc, RMPoint ptTonyStart, RMPoint start);
- HANDLE UnloadLocation(bool bDoOnExit=true);
+ void UnloadLocation(CORO_PARAM, bool bDoOnExit, HANDLE *result);
// Freeze and unfreeze
void Freeze(void);
diff --git a/engines/tony/mpal/mpal.cpp b/engines/tony/mpal/mpal.cpp
index 78111753ce..851de7cb0c 100644
--- a/engines/tony/mpal/mpal.cpp
+++ b/engines/tony/mpal/mpal.cpp
@@ -138,7 +138,7 @@ bool bExecutingDialog;
uint32 nPollingLocations[MAXPOLLINGLOCATIONS];
HANDLE hEndPollingLocations[MAXPOLLINGLOCATIONS];
-HANDLE PollingThreads[MAXPOLLINGLOCATIONS];
+uint32 PollingThreads[MAXPOLLINGLOCATIONS];
HANDLE hAskChoice;
HANDLE hDoneChoice;
@@ -996,7 +996,7 @@ void ShutUpActionThread(CORO_PARAM, const void *param) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
- int pid = *(const int *)param;
+ uint32 pid = *(const uint32 *)param;
CORO_BEGIN_CODE(_ctx);
@@ -1021,17 +1021,7 @@ void ShutUpActionThread(CORO_PARAM, const void *param) {
*
\****************************************************************************/
-void PASCAL LocationPollThread(uint32 id) {
- uint32 *il;
- int i,j,k;
- int numitems;
- int nRealItems;
- LPMPALITEM curItem,newItem;
- int nIdleActions;
- uint32 curTime;
- uint32 dwSleepTime;
- uint32 dwId;
-
+void LocationPollThread(CORO_PARAM, const void *param) {
typedef struct {
uint32 nItem, nAction;
@@ -1046,59 +1036,77 @@ void PASCAL LocationPollThread(uint32 id) {
typedef struct {
uint32 nItem;
- HANDLE hThread;
+ uint32 hThread;
} MYTHREAD;
- MYACTION *MyActions;
- MYTHREAD *MyThreads;
+ CORO_BEGIN_CONTEXT;
+ uint32 *il;
+ int i, j, k;
+ int numitems;
+ int nRealItems;
+ LPMPALITEM curItem,newItem;
+ int nIdleActions;
+ uint32 curTime;
+ uint32 dwSleepTime;
+ uint32 dwId;
+ int ord;
+ bool delayExpired;
+
+ MYACTION *MyActions;
+ MYTHREAD *MyThreads;
+ CORO_END_CONTEXT(_ctx);
+
+ uint32 id = *((const uint32 *)param);
+
+ CORO_BEGIN_CODE(_ctx);
/* Tanto per cominciare, e' necessario richiedere la lista degli item
presenti nella locazione. */
- il = mpalQueryItemList(nPollingLocations[id]);
+ _ctx->il = mpalQueryItemList(nPollingLocations[id]);
/* Contiamo gli items */
- for (numitems = 0; il[numitems] != 0; numitems++)
+ for (_ctx->numitems = 0; _ctx->il[_ctx->numitems] != 0; _ctx->numitems++)
;
/* Cerchiamo gli items della locazione senza idle actions e li eliminiamo
dalla lista */
LockItems();
- nIdleActions = 0;
- nRealItems = 0;
- for (i = 0; i < numitems; i++) {
- int ord = itemGetOrderFromNum(il[i]);
+ _ctx->nIdleActions = 0;
+ _ctx->nRealItems = 0;
+ for (_ctx->i = 0; _ctx->i < _ctx->numitems; _ctx->i++) {
+ _ctx->ord = itemGetOrderFromNum(_ctx->il[_ctx->i]);
- if (ord == -1) continue;
+ if (_ctx->ord == -1) continue;
- curItem = lpmiItems + ord;
+ _ctx->curItem = lpmiItems + _ctx->ord;
- k = 0;
- for (j = 0; j < curItem->nActions; j++)
- if (curItem->Action[j].num == 0xFF)
- k++;
+ _ctx->k = 0;
+ for (_ctx->j = 0; _ctx->j < _ctx->curItem->nActions; _ctx->j++)
+ if (_ctx->curItem->Action[_ctx->j].num == 0xFF)
+ _ctx->k++;
- nIdleActions += k;
+ _ctx->nIdleActions += _ctx->k;
- if (k == 0)
+ if (_ctx->k == 0)
/* Possiamo eliminare questo item dalla lista */
- il[i] = (uint32)NULL;
+ _ctx->il[_ctx->i] = (uint32)NULL;
else
- nRealItems++;
+ _ctx->nRealItems++;
}
UnlockItems();
/* Se non e' rimasto nessuno possiamo uscire */
- if (nRealItems == 0) {
- GlobalFree(il);
- ExitThread(0);
-// _endthread();
+ if (_ctx->nRealItems == 0) {
+ GlobalFree(_ctx->il);
+ CORO_KILL_SELF();
+ return;
}
- MyThreads=(MYTHREAD *)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, nRealItems * sizeof(MYTHREAD));
- if (MyThreads == NULL) {
- GlobalFree(il);
- ExitThread(0);
-// _endthread();
+ _ctx->MyThreads = (MYTHREAD *)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, _ctx->nRealItems * sizeof(MYTHREAD));
+ if (_ctx->MyThreads == NULL) {
+ GlobalFree(_ctx->il);
+ CORO_KILL_SELF();
+ return;
}
/* Inizializziamo le routine random */
@@ -1108,142 +1116,147 @@ void PASCAL LocationPollThread(uint32 id) {
/* Abbiamo appurato che esiste almeno un item che contiene idle actions.
Ora creaiamo le copie speculari delle idle actions */
- MyActions = (MYACTION *)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, nIdleActions * sizeof(MYACTION));
- if (MyActions == NULL) {
- GlobalFree(MyThreads);
- GlobalFree(il);
- ExitThread(0);
-// _endthread();
+ _ctx->MyActions = (MYACTION *)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, _ctx->nIdleActions * sizeof(MYACTION));
+ if (_ctx->MyActions == NULL) {
+ GlobalFree(_ctx->MyThreads);
+ GlobalFree(_ctx->il);
+ CORO_KILL_SELF();
+ return;
}
LockItems();
- k = 0;
+ _ctx->k = 0;
- for (i = 0; i < numitems; i++) {
- if (il[i] == 0)
+ for (_ctx->i = 0; _ctx->i < _ctx->numitems; _ctx->i++) {
+ if (_ctx->il[_ctx->i] == 0)
continue;
- curItem = lpmiItems + itemGetOrderFromNum(il[i]);
+ _ctx->curItem = lpmiItems + itemGetOrderFromNum(_ctx->il[_ctx->i]);
- for (j = 0; j < curItem->nActions; j++)
- if (curItem->Action[j].num == 0xFF) {
- MyActions[k].nItem = il[i];
- MyActions[k].nAction = j;
+ for (_ctx->j = 0; _ctx->j < _ctx->curItem->nActions; _ctx->j++)
+ if (_ctx->curItem->Action[_ctx->j].num == 0xFF) {
+ _ctx->MyActions[_ctx->k].nItem = _ctx->il[_ctx->i];
+ _ctx->MyActions[_ctx->k].nAction = _ctx->j;
- MyActions[k].wTime = curItem->Action[j].wTime;
- MyActions[k].perc = curItem->Action[j].perc;
- MyActions[k].when = curItem->Action[j].when;
- MyActions[k].nCmds = curItem->Action[j].nCmds;
- CopyMemory(MyActions[k].CmdNum, curItem->Action[j].CmdNum,
+ _ctx->MyActions[_ctx->k].wTime = _ctx->curItem->Action[_ctx->j].wTime;
+ _ctx->MyActions[_ctx->k].perc = _ctx->curItem->Action[_ctx->j].perc;
+ _ctx->MyActions[_ctx->k].when = _ctx->curItem->Action[_ctx->j].when;
+ _ctx->MyActions[_ctx->k].nCmds = _ctx->curItem->Action[_ctx->j].nCmds;
+ CopyMemory(_ctx->MyActions[_ctx->k].CmdNum, _ctx->curItem->Action[_ctx->j].CmdNum,
MAX_COMMANDS_PER_ACTION * sizeof(uint16));
- MyActions[k].dwLastTime = timeGetTime();
- k++;
+ _ctx->MyActions[_ctx->k].dwLastTime = timeGetTime();
+ _ctx->k++;
}
}
UnlockItems();
/* La item list non ci serve piu' */
- GlobalFree(il);
+ GlobalFree(_ctx->il);
/* Eccoci al ciclo principale. */
while (1) {
/* Cerchiamo tra tutte le idle actions quella a cui manca meno tempo per
l'esecuzione */
- curTime = timeGetTime();
- dwSleepTime=(uint32) - 1L;
+ _ctx->curTime = timeGetTime();
+ _ctx->dwSleepTime = (uint32)-1L;
- for (k = 0;k<nIdleActions;k++)
- if (curTime >= MyActions[k].dwLastTime + MyActions[k].wTime) {
- dwSleepTime = 0;
+ for (_ctx->k = 0;_ctx->k<_ctx->nIdleActions;_ctx->k++)
+ if (_ctx->curTime >= _ctx->MyActions[_ctx->k].dwLastTime + _ctx->MyActions[_ctx->k].wTime) {
+ _ctx->dwSleepTime = 0;
break;
} else
- dwSleepTime = MIN(dwSleepTime,MyActions[k].dwLastTime+MyActions[k].wTime-curTime);
+ _ctx->dwSleepTime = MIN(_ctx->dwSleepTime, _ctx->MyActions[_ctx->k].dwLastTime + _ctx->MyActions[_ctx->k].wTime - _ctx->curTime);
/* Ci addormentiamo, ma controllando sempre l'evento che viene settato
quando viene richiesta la nostra chiusura */
- k = WaitForSingleObject(hEndPollingLocations[id], dwSleepTime);
- if (k == WAIT_OBJECT_0)
+ _ctx->k = WaitForSingleObject(hEndPollingLocations[id], _ctx->dwSleepTime);
+ if (_ctx->k == WAIT_OBJECT_0)
break;
- for (i = 0; i < nRealItems; i++)
- if (MyThreads[i].nItem != 0) {
- if (WaitForSingleObject(MyThreads[i].hThread, 0) == WAIT_OBJECT_0)
- MyThreads[i].nItem = 0;
+ for (_ctx->i = 0; _ctx->i < _ctx->nRealItems; _ctx->i++)
+ if (_ctx->MyThreads[_ctx->i].nItem != 0) {
+ CORO_INVOKE_3(_vm->_scheduler.waitForSingleObject, _ctx->MyThreads[_ctx->i].hThread, 0, &_ctx->delayExpired);
+
+ // if result ) == WAIT_OBJECT_0)
+ if (!_ctx->delayExpired)
+ _ctx->MyThreads[_ctx->i].nItem = 0;
}
- curTime = timeGetTime();
+ _ctx->curTime = timeGetTime();
/* Cerchiamo all'interno delle idle actions quale e' necessario eseguire */
- for (k = 0; k < nIdleActions; k++)
- if (curTime >= MyActions[k].dwLastTime + MyActions[k].wTime) {
- MyActions[k].dwLastTime += MyActions[k].wTime;
+ for (_ctx->k = 0; _ctx->k < _ctx->nIdleActions; _ctx->k++)
+ if (_ctx->curTime >= _ctx->MyActions[_ctx->k].dwLastTime + _ctx->MyActions[_ctx->k].wTime) {
+ _ctx->MyActions[_ctx->k].dwLastTime += _ctx->MyActions[_ctx->k].wTime;
- /* E' il momento di tirare il nostro dado virtuale, e controllare
+ /* E' _ctx->il momento di tirare _ctx->il nostro dado virtuale, e controllare
se la sorte e' dalla parte della idle action */
byte randomVal = (byte)_vm->_randomSource.getRandomNumber(99);
- if (randomVal < MyActions[k].perc) {
+ if (randomVal < _ctx->MyActions[_ctx->k].perc) {
/* Controlliamo se c'e' una action in esecuzione sull'item */
- if ((bExecutingAction) && (nExecutingAction == MyActions[k].nItem))
+ if ((bExecutingAction) && (nExecutingAction == _ctx->MyActions[_ctx->k].nItem))
continue;
/* Controlliamo se c'e' gia' un'altra idle function in esecuzione
sullo stesso item */
- for (i = 0; i < nRealItems; i++)
- if (MyThreads[i].nItem == MyActions[k].nItem)
+ for (_ctx->i = 0; _ctx->i < _ctx->nRealItems; _ctx->i++)
+ if (_ctx->MyThreads[_ctx->i].nItem == _ctx->MyActions[_ctx->k].nItem)
break;
- if (i < nRealItems)
+ if (_ctx->i < _ctx->nRealItems)
continue;
/* Ok, siamo gli unici :) */
LockItems();
- curItem=lpmiItems+itemGetOrderFromNum(MyActions[k].nItem);
+ _ctx->curItem=lpmiItems+itemGetOrderFromNum(_ctx->MyActions[_ctx->k].nItem);
/* Controlliamo se c'e' un esperessione WhenExecute */
- j=MyActions[k].nAction;
- if (curItem->Action[j].when != NULL)
- if (!EvaluateExpression(curItem->Action[j].when)) {
+ _ctx->j=_ctx->MyActions[_ctx->k].nAction;
+ if (_ctx->curItem->Action[_ctx->j].when != NULL)
+ if (!EvaluateExpression(_ctx->curItem->Action[_ctx->j].when)) {
UnlockItems();
continue;
}
/* Ok, possiamo eseguire la azione. Per comodita' lo facciamo in
un nuovo thread */
- newItem=(LPMPALITEM)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(MPALITEM));
- if (newItem == false) {
- GlobalFree(MyThreads);
- GlobalFree(MyActions);
- ExitThread(0);
-// _endthread();
+ _ctx->newItem = (LPMPALITEM)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(MPALITEM));
+ if (_ctx->newItem == false) {
+ GlobalFree(_ctx->MyThreads);
+ GlobalFree(_ctx->MyActions);
+
+ CORO_KILL_SELF();
+ return;
}
- CopyMemory(newItem,curItem, sizeof(MPALITEM));
+ CopyMemory(_ctx->newItem,_ctx->curItem, sizeof(MPALITEM));
UnlockItems();
/* Copiamo l'azione nella #0 */
-// newItem->Action[0].nCmds = curItem->Action[j].nCmds;
-// CopyMemory(newItem->Action[0].CmdNum,curItem->Action[j].CmdNum,newItem->Action[0].nCmds*sizeof(newItem->Action[0].CmdNum[0]));
- newItem->dwRes=j;
+// _ctx->newItem->Action[0].nCmds = _ctx->curItem->Action[_ctx->j].nCmds;
+// CopyMemory(_ctx->newItem->Action[0].CmdNum,_ctx->curItem->Action[_ctx->j].CmdNum,_ctx->newItem->Action[0].nCmds*sizeof(_ctx->newItem->Action[0].CmdNum[0]));
+ _ctx->newItem->dwRes=_ctx->j;
/* Creaiamo l'action thread. Provvedera' lui a liberare la memoria
- allocata per il nuovo item */
- for (i = 0; i < nRealItems; i++)
- if (MyThreads[i].nItem == 0)
+ allocata per _ctx->il nuovo item */
+ for (_ctx->i = 0; _ctx->i < _ctx->nRealItems; _ctx->i++)
+ if (_ctx->MyThreads[_ctx->i].nItem == 0)
break;
- MyThreads[i].nItem=MyActions[k].nItem;
+ _ctx->MyThreads[_ctx->i].nItem = _ctx->MyActions[_ctx->k].nItem;
// !!! Nuova gestione dei thread
- if ((MyThreads[i].hThread = CreateThread(NULL, 10240, (LPTHREAD_START_ROUTINE)ActionThread,(void *)newItem, 0, &dwId)) == NULL) {
- //if ((MyThreads[i].hThread=(void*)_beginthread(ActionThread, 10240,(void *)newItem))==(void*)-1)
- GlobalFree(newItem);
- GlobalFree(MyThreads);
- GlobalFree(MyActions);
- ExitThread(0);
-// _endthread();
+ if ((_ctx->MyThreads[_ctx->i].hThread = _vm->_scheduler.createProcess(ActionThread, &_ctx->newItem, sizeof(LPMPALITEM))) == 0) {
+ //if ((_ctx->MyThreads[_ctx->i].hThread=(void*)_beginthread(ActionThread, 10240,(void *)_ctx->newItem))==(void*)-1)
+ GlobalFree(_ctx->newItem);
+ GlobalFree(_ctx->MyThreads);
+ GlobalFree(_ctx->MyActions);
+
+ CORO_KILL_SELF();
+ return;
}
/* Skippa tutte le idle action dello stesso item */
@@ -1251,16 +1264,16 @@ void PASCAL LocationPollThread(uint32 id) {
}
}
- /* Chiude tutti i thread interni */
+ /* Chiude tutti _ctx->i thread interni */
/*
CODICE OBSOLETO: ANDIAMO DI SKIP CHE RULLA
- for (i = 0; i < nRealItems; i++)
- if (MyThreads[i].nItem != 0) {
- TerminateThread(MyThreads[i].hThread, 0);
- CloseHandle(MyThreads[i].hThread);
+ for (_ctx->i = 0; _ctx->i < _ctx->nRealItems; _ctx->i++)
+ if (_ctx->MyThreads[_ctx->i].nItem != 0) {
+ TerminateThread(_ctx->MyThreads[_ctx->i].hThread, 0);
+ CloseHandle(_ctx->MyThreads[_ctx->i].hThread);
}
*/
@@ -1268,23 +1281,28 @@ void PASCAL LocationPollThread(uint32 id) {
// FIXME: Convert to co-routine
lplpFunctions[200](nullContext, 0, 0, 0, 0);
- for (i = 0; i < nRealItems; i++)
- if (MyThreads[i].nItem != 0) {
- if (WaitForSingleObject(MyThreads[i].hThread,5000) != WAIT_OBJECT_0)
- TerminateThread(MyThreads[i].hThread, 0);
+ for (_ctx->i = 0; _ctx->i < _ctx->nRealItems; _ctx->i++)
+ if (_ctx->MyThreads[_ctx->i].nItem != 0) {
+ CORO_INVOKE_3(_vm->_scheduler.waitForSingleObject, _ctx->MyThreads[_ctx->i].hThread, 5000, &_ctx->delayExpired);
- CloseHandle(MyThreads[i].hThread);
+/*
+ //if (result != WAIT_OBJECT_0)
+ if (_ctx->delayExpired)
+ TerminateThread(_ctx->MyThreads[_ctx->i].hThread, 0);
+*/
+ _vm->_scheduler.killMatchingProcess(_ctx->MyThreads[_ctx->i].hThread);
}
// Set idle skip off
- // FIXME: Convert to co-routine
- lplpFunctions[201](nullContext, 0, 0, 0, 0);
+ CORO_INVOKE_4(lplpFunctions[201], 0, 0, 0, 0);
/* Abbiamo finito */
- GlobalFree(MyThreads);
- GlobalFree(MyActions);
- ExitThread(1);
-//endthread();
+ GlobalFree(_ctx->MyThreads);
+ GlobalFree(_ctx->MyActions);
+
+ CORO_KILL_SELF();
+
+ CORO_END_CODE;
}
@@ -1516,7 +1534,7 @@ static HANDLE DoAction(uint32 nAction, uint32 ordItem, uint32 dwParam) {
LPMPALITEM item = lpmiItems;
int i;
LPMPALITEM newitem;
- PROCESS *h;
+ uint32 h;
item+=ordItem;
Common::String buf = Common::String::format("Status.%u", item->nObj);
@@ -1552,10 +1570,10 @@ static HANDLE DoAction(uint32 nAction, uint32 ordItem, uint32 dwParam) {
// 0 dell'item, e poi liberera' la memoria con la GlobalFree()
// !!! New thread management
- if ((h = g_scheduler->createProcess(ActionThread, newitem)) == NULL)
+ if ((h = g_scheduler->createProcess(ActionThread, &newitem, sizeof(LPMPALITEM))) == NULL)
return INVALID_HANDLE_VALUE;
- if ((h = g_scheduler->createProcess(ShutUpActionThread, &h->pid, sizeof(int))) == NULL)
+ if ((h = g_scheduler->createProcess(ShutUpActionThread, &h, sizeof(uint32))) == NULL)
return INVALID_HANDLE_VALUE;
/*
@@ -2182,7 +2200,7 @@ void EXPORT mpalInstallItemIrq(LPITEMIRQFUNCTION lpiifCus) {
*
\****************************************************************************/
-bool EXPORT mpalStartIdlePoll(int nLoc) {
+bool mpalStartIdlePoll(int nLoc) {
uint32 i;
uint32 dwId;
@@ -2196,7 +2214,7 @@ bool EXPORT mpalStartIdlePoll(int nLoc) {
hEndPollingLocations[i] = CreateEvent(NULL, true, false, NULL);
// !!! Nuova gestione dei thread
- if ((PollingThreads[i] = CreateThread(NULL, 10240, (LPTHREAD_START_ROUTINE)LocationPollThread,(void *)i, 0, &dwId)) == NULL)
+ if ((PollingThreads[i] = _vm->_scheduler.createProcess(LocationPollThread, &i, sizeof(uint32))) == 0)
// if ((hEndPollingLocations[i]=(void*)_beginthread(LocationPollThread, 10240,(void *)i))==(void*)-1)
return false;
@@ -2222,22 +2240,32 @@ bool EXPORT mpalStartIdlePoll(int nLoc) {
*
\****************************************************************************/
-bool EXPORT mpalEndIdlePoll(int nLoc) {
- uint32 i;
+void mpalEndIdlePoll(CORO_PARAM, int nLoc, bool *result) {
+ CORO_BEGIN_CONTEXT;
+ int i;
+ CORO_END_CONTEXT(_ctx);
- for (i = 0; i < MAXPOLLINGLOCATIONS; i++)
- if (nPollingLocations[i] == (uint32)nLoc) {
- SetEvent(hEndPollingLocations[i]);
+ CORO_BEGIN_CODE(_ctx);
+
+ for (_ctx->i = 0; _ctx->i < MAXPOLLINGLOCATIONS; _ctx->i++) {
+ if (nPollingLocations[_ctx->i] == (uint32)nLoc) {
+ SetEvent(hEndPollingLocations[_ctx->i]);
- WaitForSingleObject(PollingThreads[i], INFINITE);
+ CORO_INVOKE_2(_vm->_scheduler.waitForSingleObject, PollingThreads[_ctx->i], INFINITE);
- CloseHandle(hEndPollingLocations[i]);
- nPollingLocations[i] = 0;
+ CloseHandle(hEndPollingLocations[_ctx->i]);
+ nPollingLocations[_ctx->i] = 0;
- return true;
+ if (result)
+ *result = true;
+ return;
+ }
}
- return false;
+ if (result)
+ *result = false;
+
+ CORO_END_CODE;
}
diff --git a/engines/tony/mpal/mpal.h b/engines/tony/mpal/mpal.h
index 3c2e62d992..9da963d39e 100644
--- a/engines/tony/mpal/mpal.h
+++ b/engines/tony/mpal/mpal.h
@@ -704,8 +704,7 @@ bool EXPORT mpalStartIdlePoll(int nLoc);
*
\****************************************************************************/
-bool EXPORT mpalEndIdlePoll(int nLoc);
-
+void mpalEndIdlePoll(CORO_PARAM, int nLoc, bool *result);
/****************************************************************************\
diff --git a/engines/tony/sched.cpp b/engines/tony/sched.cpp
index 0f397316f6..421f4d1ac7 100644
--- a/engines/tony/sched.cpp
+++ b/engines/tony/sched.cpp
@@ -294,10 +294,11 @@ void Scheduler::giveWay(PPROCESS pReSchedProc) {
/**
* Continously makes a given process wait for another process to finish
*
- * @param pid Process identifier
- * @param duration Duration in milliseconds
+ * @param pid Process identifier
+ * @param duration Duration in milliseconds
+ * @param expired Set to true if delay period expired
*/
-void Scheduler::waitForSingleObject(CORO_PARAM, int pid, int duration) {
+void Scheduler::waitForSingleObject(CORO_PARAM, int pid, int duration, bool *expired) {
CORO_BEGIN_CONTEXT;
uint32 endTime;
PROCESS *pProc;
@@ -306,6 +307,8 @@ void Scheduler::waitForSingleObject(CORO_PARAM, int pid, int duration) {
CORO_BEGIN_CODE(_ctx);
_ctx->endTime = (duration == INFINITE) ? INFINITE : g_system->getMillis() + duration;
+ if (expired)
+ *expired = false;
// Outer loop for doing checks until expiry
while (g_system->getMillis() < _ctx->endTime) {
@@ -314,9 +317,13 @@ void Scheduler::waitForSingleObject(CORO_PARAM, int pid, int duration) {
while ((_ctx->pProc != NULL) && (_ctx->pProc->pid == pid))
_ctx->pProc = _ctx->pProc->pNext;
- if (_ctx->pProc == NULL)
+ if (_ctx->pProc == NULL) {
// No match process found, so it's okay to break out of loop
+ if (expired)
+ *expired = true;
+
break;
+ }
// Sleep until the next cycle
CORO_SLEEP(1);
@@ -333,7 +340,7 @@ void Scheduler::waitForSingleObject(CORO_PARAM, int pid, int duration) {
* @param pParam process specific info
* @param sizeParam size of process specific info
*/
-PROCESS *Scheduler::createProcess(CORO_ADDR coroAddr, const void *pParam, int sizeParam) {
+uint32 Scheduler::createProcess(CORO_ADDR coroAddr, const void *pParam, int sizeParam) {
PROCESS *pProc;
// get a free process
@@ -394,7 +401,7 @@ PROCESS *Scheduler::createProcess(CORO_ADDR coroAddr, const void *pParam, int si
}
// return created process
- return pProc;
+ return pProc->pid;
}
/**
diff --git a/engines/tony/sched.h b/engines/tony/sched.h
index cffa0f9328..54f44aa5fd 100644
--- a/engines/tony/sched.h
+++ b/engines/tony/sched.h
@@ -41,7 +41,7 @@ typedef void (*CORO_ADDR)(CoroContext &, const void *);
/** process structure */
struct PROCESS {
- PROCESS *pNext; ///< pointer to next process in active or free list
+ 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
@@ -111,10 +111,10 @@ public:
void rescheduleAll();
void reschedule(PPROCESS pReSchedProc = NULL);
void giveWay(PPROCESS pReSchedProc = NULL);
- void waitForSingleObject(CORO_PARAM, int pid, int duration);
+ void waitForSingleObject(CORO_PARAM, int pid, int duration, bool *delay = NULL);
- PROCESS *createProcess(CORO_ADDR coroAddr, const void *pParam, int sizeParam);
- PROCESS *createProcess(CORO_ADDR coroAddr, const void *pParam) {
+ uint32 createProcess(CORO_ADDR coroAddr, const void *pParam, int sizeParam);
+ uint32 createProcess(CORO_ADDR coroAddr, const void *pParam) {
return createProcess(coroAddr, &pParam, sizeof(void *));
}
void killProcess(PROCESS *pKillProc);
diff --git a/engines/tony/tonychar.cpp b/engines/tony/tonychar.cpp
index e4f334d0e5..de6189876b 100644
--- a/engines/tony/tonychar.cpp
+++ b/engines/tony/tonychar.cpp
@@ -59,11 +59,19 @@ namespace Tony {
bool RMTony::m_bAction = false;
-uint32 RMTony::WaitEndOfAction(HANDLE hThread) {
- WaitForSingleObject(hThread, INFINITE);
+void RMTony::WaitEndOfAction(CORO_PARAM, const void *param) {
+ CORO_BEGIN_CONTEXT;
+ CORO_END_CONTEXT(_ctx);
+
+ uint32 pid = *(const uint32 *)param;
+
+ CORO_BEGIN_CODE(_ctx);
+
+ CORO_INVOKE_2(_vm->_scheduler.waitForSingleObject, pid, INFINITE);
+
m_bAction = false;
- return 1;
+ CORO_END_CODE;
}
RMGfxSourceBuffer *RMTony::NewItemSpriteBuffer(int dimx, int dimy, bool bPreRLE) {
@@ -205,6 +213,7 @@ void RMTony::MoveAndDoAction(RMPoint dst, RMItem *item, int nAction, int nAction
void RMTony::ExecuteAction(int nAction, int nActionItem, int nParm) {
HANDLE hThread;
+ uint32 pid;
if (nAction == TA_COMBINE) {
hThread = mpalQueryDoAction(TA_COMBINE, nParm, nActionItem);
@@ -229,27 +238,28 @@ void RMTony::ExecuteAction(int nAction, int nActionItem, int nParm) {
}
if (hThread != INVALID_HANDLE_VALUE) {
- uint32 id;
m_bAction = true;
- CreateThread(NULL, 10240,(LPTHREAD_START_ROUTINE)WaitEndOfAction, (void *)hThread, 0, &id);
+ pid = (uint32)hThread;
+ _vm->_scheduler.createProcess(WaitEndOfAction, &pid, sizeof(uint32));
hActionThread = hThread;
} else if (nAction != TA_GOTO) {
- uint32 id;
-
if (nAction == TA_TALK) {
hThread = mpalQueryDoAction(6, 1, 0);
m_bAction = true;
- CreateThread(NULL,10240,(LPTHREAD_START_ROUTINE)WaitEndOfAction, (void *)hThread,0,&id);
- hActionThread=hThread;
+ pid = (uint32)hThread;
+ _vm->_scheduler.createProcess(WaitEndOfAction, &pid, sizeof(uint32));
+ hActionThread = hThread;
} else if (nAction == TA_PALESATI) {
hThread = mpalQueryDoAction(7, 1, 0);
m_bAction = true;
- CreateThread(NULL,10240,(LPTHREAD_START_ROUTINE)WaitEndOfAction,(void *)hThread, 0, &id);
+ pid = (uint32)hThread;
+ _vm->_scheduler.createProcess(WaitEndOfAction, &pid, sizeof(uint32));
hActionThread=hThread;
} else {
hThread = mpalQueryDoAction(5, 1, 0);
m_bAction = true;
- CreateThread(NULL, 10240, (LPTHREAD_START_ROUTINE)WaitEndOfAction, (void *)hThread, 0, &id);
+ pid = (uint32)hThread;
+ _vm->_scheduler.createProcess(WaitEndOfAction, &pid, sizeof(uint32));
hActionThread = hThread;
}
}
diff --git a/engines/tony/tonychar.h b/engines/tony/tonychar.h
index 9806fd5e58..266b34e697 100644
--- a/engines/tony/tonychar.h
+++ b/engines/tony/tonychar.h
@@ -49,6 +49,7 @@
#define TONY_TONYCHAR_H
#include "tony/mpal/stubs.h"
+#include "tony/coroutine.h"
#include "tony/loc.h"
namespace Tony {
@@ -128,8 +129,8 @@ protected:
// Overload dell'allocazione degli sprites per cambiare il tipo
virtual RMGfxSourceBuffer* NewItemSpriteBuffer(int dimx, int dimy, bool bPreRLE);
- // Thread che aspetta la fine di un azione
- static uint32 WaitEndOfAction(HANDLE hThread);
+ // Thread which waits for the end of an action
+ static void WaitEndOfAction(CORO_PARAM, const void *param);
public: // per farlo rialzare, altrimenti private
enum PATTERNS {