diff options
-rw-r--r-- | engines/tony/adv.h | 3 | ||||
-rw-r--r-- | engines/tony/custom.cpp | 61 | ||||
-rw-r--r-- | engines/tony/game.cpp | 4 | ||||
-rw-r--r-- | engines/tony/gfxengine.cpp | 37 | ||||
-rw-r--r-- | engines/tony/gfxengine.h | 2 | ||||
-rw-r--r-- | engines/tony/mpal/mpal.cpp | 310 | ||||
-rw-r--r-- | engines/tony/mpal/mpal.h | 3 | ||||
-rw-r--r-- | engines/tony/sched.cpp | 19 | ||||
-rw-r--r-- | engines/tony/sched.h | 8 | ||||
-rw-r--r-- | engines/tony/tonychar.cpp | 32 | ||||
-rw-r--r-- | engines/tony/tonychar.h | 5 |
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 { |