From 8527302057052e784c3ea32ca8eebb0220bf15e6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 8 May 2012 08:25:33 +1000 Subject: TONY: Added support for threading events to scheduler, converted more procs to coroutines --- engines/tony/custom.cpp | 610 +++++++++++++++++++++++++++++--------------- engines/tony/loc.cpp | 31 ++- engines/tony/loc.h | 5 +- engines/tony/mpal/mpal.cpp | 27 +- engines/tony/mpal/stubs.cpp | 4 + engines/tony/sched.cpp | 182 ++++++++++++- engines/tony/sched.h | 25 +- engines/tony/tonychar.cpp | 194 +++++++++----- engines/tony/tonychar.h | 18 +- 9 files changed, 771 insertions(+), 325 deletions(-) (limited to 'engines/tony') diff --git a/engines/tony/custom.cpp b/engines/tony/custom.cpp index e7878c5a5d..800b5d8d50 100644 --- a/engines/tony/custom.cpp +++ b/engines/tony/custom.cpp @@ -370,50 +370,62 @@ VoiceHeader *SearchVoiceHeader(uint32 codehi, uint32 codelo) { DECLARE_CUSTOM_FUNCTION(SendTonyMessage)(CORO_PARAM, uint32 dwMessage, uint32 nX, uint32 nY, uint32) { - RMMessage msg(dwMessage); - int i; - int curOffset = 0; + CORO_BEGIN_CONTEXT; + RMMessage *msg; + int i; + int curOffset; + VoiceHeader *curVoc; + FPSFX *voice; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + + _ctx->curOffset = 0; if (bSkipIdle) return; - if (!msg.IsValid()) + _ctx->msg = new RMMessage(dwMessage); + if (!_ctx->msg->IsValid()) { + delete _ctx->msg; return; + } - VoiceHeader *curVoc = SearchVoiceHeader(0, dwMessage); - FPSFX *voice = NULL; - if (curVoc) { + _ctx->curVoc = SearchVoiceHeader(0, dwMessage); + _ctx->voice = NULL; + if (_ctx->curVoc) { // Si posiziona all'interno del database delle voci all'inizio della prima - curOffset = curVoc->offset; + _ctx->curOffset = _ctx->curVoc->offset; // PRIMA VOLTA PREALLOCA g_system->lockMutex(vdb); - //fseek(_vm->m_vdbFP, curOffset, SEEK_SET); - _vm->_vdbFP.seek(curOffset); - _vm->_theSound.CreateSfx(&voice); - voice->LoadVoiceFromVDB(_vm->_vdbFP); -// curOffset = ftell(_vm->m_vdbFP); - curOffset = _vm->_vdbFP.pos(); - - voice->SetLoop(false); + //fseek(_vm->m_vdbFP, _ctx->curOffset, SEEK_SET); + _vm->_vdbFP.seek(_ctx->curOffset); + _vm->_theSound.CreateSfx(&_ctx->voice); + _ctx->voice->LoadVoiceFromVDB(_vm->_vdbFP); +// _ctx->curOffset = ftell(_vm->m_vdbFP); + _ctx->curOffset = _vm->_vdbFP.pos(); + + _ctx->voice->SetLoop(false); g_system->unlockMutex(vdb); } if (nTonyNextTalkType != Tony->TALK_NORMAL) { - Tony->StartTalk(nTonyNextTalkType); + CORO_INVOKE_1(Tony->StartTalk, nTonyNextTalkType); + if (!bStaticTalk) nTonyNextTalkType = Tony->TALK_NORMAL; } else { - if (msg.NumPeriods() > 1) - Tony->StartTalk(Tony->TALK_FIANCHI); + if (_ctx->msg->NumPeriods() > 1) + CORO_INVOKE_1(Tony->StartTalk, Tony->TALK_FIANCHI); else - Tony->StartTalk(Tony->TALK_NORMAL); + CORO_INVOKE_1(Tony->StartTalk, Tony->TALK_NORMAL); } if (curBackText) curBackText->Hide(); bTonyIsSpeaking = true; - 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); @@ -425,7 +437,7 @@ DECLARE_CUSTOM_FUNCTION(SendTonyMessage)(CORO_PARAM, uint32 dwMessage, uint32 nX text.SetColor(0,255,0); // Scrive il testo - text.WriteText(msg[i],0); + text.WriteText((*_ctx->msg)[_ctx->i],0); // Setta la posizione if (nX == 0 && nY == 0) @@ -439,21 +451,21 @@ DECLARE_CUSTOM_FUNCTION(SendTonyMessage)(CORO_PARAM, uint32 dwMessage, uint32 nX // Registra il testo LinkGraphicTask(&text); - if (curVoc) { - if (i == 0) { - voice->Play(); - text.SetCustomSkipHandle2(voice->hEndOfBuffer); + if (_ctx->curVoc) { + if (_ctx->i == 0) { + _ctx->voice->Play(); + text.SetCustomSkipHandle2(_ctx->voice->hEndOfBuffer); } else { g_system->lockMutex(vdb); - // fseek(_vm->m_vdbFP, curOffset, SEEK_SET); - _vm->_vdbFP.seek(curOffset); - _vm->_theSound.CreateSfx(&voice); - voice->LoadVoiceFromVDB(_vm->_vdbFP); - // curOffset = ftell(_vm->m_vdbFP); - curOffset = _vm->_vdbFP.pos(); - voice->SetLoop(false); - voice->Play(); - text.SetCustomSkipHandle2(voice->hEndOfBuffer); + // fseek(_vm->m_vdbFP, _ctx->curOffset, SEEK_SET); + _vm->_vdbFP.seek(_ctx->curOffset); + _vm->_theSound.CreateSfx(&_ctx->voice); + _ctx->voice->LoadVoiceFromVDB(_vm->_vdbFP); + // _ctx->curOffset = ftell(_vm->m_vdbFP); + _ctx->curOffset = _vm->_vdbFP.pos(); + _ctx->voice->SetLoop(false); + _ctx->voice->Play(); + text.SetCustomSkipHandle2(_ctx->voice->hEndOfBuffer); g_system->unlockMutex(vdb); } } @@ -462,10 +474,10 @@ DECLARE_CUSTOM_FUNCTION(SendTonyMessage)(CORO_PARAM, uint32 dwMessage, uint32 nX text.SetCustomSkipHandle(hSkipIdle); text.WaitForEndDisplay(); - if (curVoc) { - voice->Stop(); - voice->Release(); - voice=NULL; + if (_ctx->curVoc) { + _ctx->voice->Stop(); + _ctx->voice->Release(); + _ctx->voice=NULL; } } @@ -473,7 +485,10 @@ DECLARE_CUSTOM_FUNCTION(SendTonyMessage)(CORO_PARAM, uint32 dwMessage, uint32 nX if (curBackText) curBackText->Show(); - Tony->EndTalk(); + CORO_INVOKE_0(Tony->EndTalk); + delete _ctx->msg; + + CORO_END_CODE; } DECLARE_CUSTOM_FUNCTION(ChangeBoxStatus)(CORO_PARAM, uint32 nLoc, uint32 nBox, uint32 nStatus, uint32) { @@ -718,134 +733,164 @@ DECLARE_CUSTOM_FUNCTION(CustEnableGUI)(CORO_PARAM, uint32, uint32, uint32, uint3 EnableGUI(); } -DECLARE_CUSTOM_FUNCTION(CustDisableGUI)(CORO_PARAM, uint32, uint32, uint32, uint32) -{ - DisableGUI(); +DECLARE_CUSTOM_FUNCTION(CustDisableGUI)(CORO_PARAM, uint32, uint32, uint32, uint32) { + DisableGUI(); } -void TonyGenericTake1(uint32 nDirection) { + +void TonyGenericTake1(CORO_PARAM, uint32 nDirection) { + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + Freeze(); - Tony->Take(nDirection,0); + Tony->Take(nDirection, 0); Unfreeze(); if (!bSkipIdle) - Tony->WaitForEndPattern(); + CORO_INVOKE_0(Tony->WaitForEndPattern); + + CORO_END_CODE; } -void TonyGenericTake2(uint32 nDirection) { +void TonyGenericTake2(CORO_PARAM, uint32 nDirection) { + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + Freeze(); - Tony->Take(nDirection,1); + Tony->Take(nDirection, 1); Unfreeze(); if (!bSkipIdle) - Tony->WaitForEndPattern(); + CORO_INVOKE_0(Tony->WaitForEndPattern); Freeze(); Tony->Take(nDirection,2); Unfreeze(); + + CORO_END_CODE; } -void TonyGenericPut1(uint32 nDirection) { +void TonyGenericPut1(CORO_PARAM, uint32 nDirection) { + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + Freeze(); - Tony->Put(nDirection,0); + Tony->Put(nDirection, 0); Unfreeze(); if (!bSkipIdle) - Tony->WaitForEndPattern(); + CORO_INVOKE_0(Tony->WaitForEndPattern); + + CORO_END_CODE; } -void TonyGenericPut2(uint32 nDirection) { +void TonyGenericPut2(CORO_PARAM, uint32 nDirection) { + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + Freeze(); Tony->Put(nDirection,1); Unfreeze(); if (!bSkipIdle) - Tony->WaitForEndPattern(); + CORO_INVOKE_0(Tony->WaitForEndPattern); Freeze(); Tony->Put(nDirection,2); Unfreeze(); + + CORO_END_CODE; } DECLARE_CUSTOM_FUNCTION(TonyTakeUp1)(CORO_PARAM, uint32, uint32, uint32, uint32) { - TonyGenericTake1(0); + TonyGenericTake1(coroParam, 0); } DECLARE_CUSTOM_FUNCTION(TonyTakeMid1)(CORO_PARAM, uint32, uint32, uint32, uint32) { - TonyGenericTake1(1); + TonyGenericTake1(coroParam, 1); } DECLARE_CUSTOM_FUNCTION(TonyTakeDown1)(CORO_PARAM, uint32, uint32, uint32, uint32) { - TonyGenericTake1(2); + TonyGenericTake1(coroParam, 2); } DECLARE_CUSTOM_FUNCTION(TonyTakeUp2)(CORO_PARAM, uint32, uint32, uint32, uint32) { - TonyGenericTake2(0); + TonyGenericTake2(coroParam, 0); } DECLARE_CUSTOM_FUNCTION(TonyTakeMid2)(CORO_PARAM, uint32, uint32, uint32, uint32) { - TonyGenericTake2(1); + TonyGenericTake2(coroParam, 1); } DECLARE_CUSTOM_FUNCTION(TonyTakeDown2)(CORO_PARAM, uint32, uint32, uint32, uint32) { - TonyGenericTake2(2); + TonyGenericTake2(coroParam, 2); } - - - - DECLARE_CUSTOM_FUNCTION(TonyPutUp1)(CORO_PARAM, uint32, uint32, uint32, uint32) { - TonyGenericPut1(0); + TonyGenericPut1(coroParam, 0); } DECLARE_CUSTOM_FUNCTION(TonyPutMid1)(CORO_PARAM, uint32, uint32, uint32, uint32) { - TonyGenericPut1(1); + TonyGenericPut1(coroParam, 1); } DECLARE_CUSTOM_FUNCTION(TonyPutDown1)(CORO_PARAM, uint32, uint32, uint32, uint32) { - TonyGenericPut1(2); + TonyGenericPut1(coroParam, 2); } DECLARE_CUSTOM_FUNCTION(TonyPutUp2)(CORO_PARAM, uint32, uint32, uint32, uint32) { - TonyGenericPut2(0); + TonyGenericPut2(coroParam, 0); } DECLARE_CUSTOM_FUNCTION(TonyPutMid2)(CORO_PARAM, uint32, uint32, uint32, uint32) { - TonyGenericPut2(1); + TonyGenericPut2(coroParam, 1); } DECLARE_CUSTOM_FUNCTION(TonyPutDown2)(CORO_PARAM, uint32, uint32, uint32, uint32) { - TonyGenericPut2(2); + TonyGenericPut2(coroParam, 2); } - DECLARE_CUSTOM_FUNCTION(TonyPerTerra)(CORO_PARAM, uint32 dwParte, uint32, uint32, uint32) { - if (dwParte== 0) + if (dwParte == 0) Tony->SetPattern(Tony->PAT_PERTERRALEFT); else Tony->SetPattern(Tony->PAT_PERTERRARIGHT); } DECLARE_CUSTOM_FUNCTION(TonySiRialza)(CORO_PARAM, uint32 dwParte, uint32, uint32, uint32) { - if (dwParte== 0) + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + + if (dwParte == 0) Tony->SetPattern(Tony->PAT_SIRIALZALEFT); else Tony->SetPattern(Tony->PAT_SIRIALZARIGHT); if (!bSkipIdle) - Tony->WaitForEndPattern(); + CORO_INVOKE_0(Tony->WaitForEndPattern); + + CORO_END_CODE; } DECLARE_CUSTOM_FUNCTION(TonyPastorella)(CORO_PARAM, uint32 bIsPast, uint32, uint32, uint32) { @@ -853,10 +898,18 @@ DECLARE_CUSTOM_FUNCTION(TonyPastorella)(CORO_PARAM, uint32 bIsPast, uint32, uint } DECLARE_CUSTOM_FUNCTION(TonyFischietto)(CORO_PARAM, uint32, uint32, uint32, uint32) { + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + Tony->SetPattern(Tony->PAT_FISCHIETTORIGHT); if (!bSkipIdle) - Tony->WaitForEndPattern(); + CORO_INVOKE_0(Tony->WaitForEndPattern); + Tony->SetPattern(Tony->PAT_STANDRIGHT); + + CORO_END_CODE; } @@ -951,101 +1004,212 @@ DECLARE_CUSTOM_FUNCTION(TonyConPupazzoANIM)(CORO_PARAM, uint32 dwText, uint32, u } DECLARE_CUSTOM_FUNCTION(TonyConPupazzoStart)(CORO_PARAM, uint32, uint32, uint32, uint32) { + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + nTonyNextTalkType = Tony->TALK_CONPUPAZZOSTATIC; bStaticTalk = true; - Tony->StartStatic(Tony->TALK_CONPUPAZZOSTATIC); + CORO_INVOKE_1(Tony->StartStatic, Tony->TALK_CONPUPAZZOSTATIC); + + CORO_END_CODE; } DECLARE_CUSTOM_FUNCTION(TonyConPupazzoEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) { - Tony->EndStatic(Tony->TALK_CONPUPAZZOSTATIC); + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + + CORO_INVOKE_1(Tony->EndStatic, Tony->TALK_CONPUPAZZOSTATIC); bStaticTalk = false; nTonyNextTalkType = Tony->TALK_NORMAL; + + CORO_END_CODE; } DECLARE_CUSTOM_FUNCTION(TonyConConiglioStart)(CORO_PARAM, uint32, uint32, uint32, uint32) { + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + nTonyNextTalkType = Tony->TALK_CONCONIGLIOSTATIC; bStaticTalk = true; - Tony->StartStatic(Tony->TALK_CONCONIGLIOSTATIC); + CORO_INVOKE_1(Tony->StartStatic, Tony->TALK_CONCONIGLIOSTATIC); + + CORO_END_CODE; } DECLARE_CUSTOM_FUNCTION(TonyConConiglioEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) { - Tony->EndStatic(Tony->TALK_CONCONIGLIOSTATIC); + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + + CORO_INVOKE_1(Tony->EndStatic, Tony->TALK_CONCONIGLIOSTATIC); bStaticTalk = false; nTonyNextTalkType = Tony->TALK_NORMAL; + + CORO_END_CODE; } DECLARE_CUSTOM_FUNCTION(TonyConRicettaStart)(CORO_PARAM, uint32, uint32, uint32, uint32) { + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + nTonyNextTalkType = Tony->TALK_CONRICETTASTATIC; bStaticTalk = true; - Tony->StartStatic(Tony->TALK_CONRICETTASTATIC); + CORO_INVOKE_1(Tony->StartStatic, Tony->TALK_CONRICETTASTATIC); + + CORO_END_CODE; } DECLARE_CUSTOM_FUNCTION(TonyConRicettaEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) { - Tony->EndStatic(Tony->TALK_CONRICETTASTATIC); + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + + CORO_INVOKE_1(Tony->EndStatic, Tony->TALK_CONRICETTASTATIC); bStaticTalk = false; nTonyNextTalkType = Tony->TALK_NORMAL; + + CORO_END_CODE; } DECLARE_CUSTOM_FUNCTION(TonyConCarteStart)(CORO_PARAM, uint32, uint32, uint32, uint32) { + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + nTonyNextTalkType = Tony->TALK_CONCARTESTATIC; bStaticTalk = true; - Tony->StartStatic(Tony->TALK_CONCARTESTATIC); + CORO_INVOKE_1(Tony->StartStatic, Tony->TALK_CONCARTESTATIC); + + CORO_END_CODE; } DECLARE_CUSTOM_FUNCTION(TonyConCarteEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) { - Tony->EndStatic(Tony->TALK_CONCARTESTATIC); + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + + CORO_INVOKE_1(Tony->EndStatic, Tony->TALK_CONCARTESTATIC); bStaticTalk = false; nTonyNextTalkType = Tony->TALK_NORMAL; + + CORO_END_CODE; } DECLARE_CUSTOM_FUNCTION(TonyConTaccuinoStart)(CORO_PARAM, uint32, uint32, uint32, uint32) { + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + nTonyNextTalkType = Tony->TALK_CONTACCUINOSTATIC; bStaticTalk = true; - Tony->StartStatic(Tony->TALK_CONTACCUINOSTATIC); + CORO_INVOKE_1(Tony->StartStatic, Tony->TALK_CONTACCUINOSTATIC); + + CORO_END_CODE; } DECLARE_CUSTOM_FUNCTION(TonyConTaccuinoEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) { - Tony->EndStatic(Tony->TALK_CONTACCUINOSTATIC); + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + + CORO_INVOKE_1(Tony->EndStatic, Tony->TALK_CONTACCUINOSTATIC); bStaticTalk = false; nTonyNextTalkType = Tony->TALK_NORMAL; + + CORO_END_CODE; } DECLARE_CUSTOM_FUNCTION(TonyConMegafonoStart)(CORO_PARAM, uint32, uint32, uint32, uint32) { + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + nTonyNextTalkType = Tony->TALK_CONMEGAFONOSTATIC; bStaticTalk = true; - Tony->StartStatic(Tony->TALK_CONMEGAFONOSTATIC); + CORO_INVOKE_1(Tony->StartStatic, Tony->TALK_CONMEGAFONOSTATIC); + + CORO_END_CODE; } DECLARE_CUSTOM_FUNCTION(TonyConMegafonoEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) { - Tony->EndStatic(Tony->TALK_CONMEGAFONOSTATIC); + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + + CORO_INVOKE_1(Tony->EndStatic, Tony->TALK_CONMEGAFONOSTATIC); bStaticTalk = false; nTonyNextTalkType = Tony->TALK_NORMAL; + + CORO_END_CODE; } DECLARE_CUSTOM_FUNCTION(TonyConBarbaStart)(CORO_PARAM, uint32, uint32, uint32, uint32) { + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + nTonyNextTalkType = Tony->TALK_CONBARBASTATIC; bStaticTalk = true; - Tony->StartStatic(Tony->TALK_CONBARBASTATIC); + CORO_INVOKE_1(Tony->StartStatic, Tony->TALK_CONBARBASTATIC); + + CORO_END_CODE; } DECLARE_CUSTOM_FUNCTION(TonyConBarbaEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) { - Tony->EndStatic(Tony->TALK_CONBARBASTATIC); + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + + CORO_INVOKE_1(Tony->EndStatic, Tony->TALK_CONBARBASTATIC); bStaticTalk = false; nTonyNextTalkType = Tony->TALK_NORMAL; + + CORO_END_CODE; } DECLARE_CUSTOM_FUNCTION(TonySpaventatoStart)(CORO_PARAM, uint32, uint32, uint32, uint32) { + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + nTonyNextTalkType = Tony->TALK_SPAVENTATOSTATIC; bStaticTalk = true; - Tony->StartStatic(Tony->TALK_SPAVENTATOSTATIC); + CORO_INVOKE_1(Tony->StartStatic, Tony->TALK_SPAVENTATOSTATIC); + + CORO_END_CODE; } DECLARE_CUSTOM_FUNCTION(TonySpaventatoEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) { - Tony->EndStatic(Tony->TALK_SPAVENTATOSTATIC); + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + + CORO_INVOKE_1(Tony->EndStatic, Tony->TALK_SPAVENTATOSTATIC); bStaticTalk = false; nTonyNextTalkType = Tony->TALK_NORMAL; -} + CORO_END_CODE; +} DECLARE_CUSTOM_FUNCTION(TonySchifato)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) { @@ -1060,7 +1224,7 @@ DECLARE_CUSTOM_FUNCTION(TonySniffaLeft)(CORO_PARAM, uint32, uint32, uint32, uint CORO_BEGIN_CODE(_ctx); Tony->SetPattern(Tony->PAT_SNIFFA_LEFT); - Tony->WaitForEndPattern(); + CORO_INVOKE_0(Tony->WaitForEndPattern); CORO_INVOKE_4(LeftToMe, 0, 0, 0, 0); CORO_END_CODE; @@ -1073,7 +1237,7 @@ DECLARE_CUSTOM_FUNCTION(TonySniffaRight)(CORO_PARAM, uint32, uint32, uint32, uin CORO_BEGIN_CODE(_ctx); Tony->SetPattern(Tony->PAT_SNIFFA_RIGHT); - Tony->WaitForEndPattern(); + CORO_INVOKE_0(Tony->WaitForEndPattern); CORO_INVOKE_4(RightToMe, 0, 0, 0, 0); CORO_END_CODE; @@ -1126,10 +1290,18 @@ DECLARE_CUSTOM_FUNCTION(DisableTony)(CORO_PARAM, uint32 bShowOmbra, uint32, uint } DECLARE_CUSTOM_FUNCTION(WaitForPatternEnd)(CORO_PARAM, uint32 nItem, uint32, uint32, uint32) { - RMItem *item = Loc->GetItemFromCode(nItem); + CORO_BEGIN_CONTEXT; + RMItem *item; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + + _ctx->item = Loc->GetItemFromCode(nItem); - if (!bSkipIdle && item != NULL) - item->WaitForEndPattern(hSkipIdle); + if (!bSkipIdle && _ctx->item != NULL) + CORO_INVOKE_1(_ctx->item->WaitForEndPattern, hSkipIdle); + + CORO_END_CODE; } @@ -1383,106 +1555,119 @@ DECLARE_CUSTOM_FUNCTION(CharSetStartEndTalkPattern)(CORO_PARAM, uint32 nChar, ui } DECLARE_CUSTOM_FUNCTION(CharSendMessage)(CORO_PARAM, uint32 nChar, uint32 dwMessage, uint32 bIsBack, uint32) { - RMMessage msg(dwMessage); - int i; - RMPoint pt; - RMTextDialog *text; - int curOffset = 0; + CORO_BEGIN_CONTEXT; + RMMessage *msg; + int i; + RMPoint pt; + RMTextDialog *text; + int curOffset; + VoiceHeader *curVoc; + FPSFX *voice; + CORO_END_CONTEXT(_ctx); - assert(nChar<16); - pt=Character[nChar].item->CalculatePos()-RMPoint(-60,20)-Loc->ScrollPosition(); + CORO_BEGIN_CODE(_ctx); + + _ctx->msg = new RMMessage(dwMessage); + _ctx->curOffset = 0; + + assert(nChar < 16); + _ctx->pt = Character[nChar].item->CalculatePos() - RMPoint(-60, 20) - Loc->ScrollPosition(); if (Character[nChar].starttalkpattern != 0) { Freeze(); Character[nChar].item->SetPattern(Character[nChar].starttalkpattern); Unfreeze(); - Character[nChar].item->WaitForEndPattern(); + + CORO_INVOKE_0(Character[nChar].item->WaitForEndPattern); } Freeze(); Character[nChar].item->SetPattern(Character[nChar].talkpattern); Unfreeze(); - VoiceHeader *curVoc = SearchVoiceHeader(0, dwMessage); - FPSFX *voice = NULL; - if (curVoc) { + _ctx->curVoc = SearchVoiceHeader(0, dwMessage); + _ctx->voice = NULL; + if (_ctx->curVoc) { // Si posiziona all'interno del database delle voci all'inizio della prima -// fseek(_vm->m_vdbFP, curVoc->offset, SEEK_SET); +// fseek(_vm->m_vdbFP, _ctx->curVoc->offset, SEEK_SET); g_system->lockMutex(vdb); - _vm->_vdbFP.seek(curVoc->offset); - curOffset = curVoc->offset; + _vm->_vdbFP.seek(_ctx->curVoc->offset); + _ctx->curOffset = _ctx->curVoc->offset; g_system->unlockMutex(vdb); } - for (i = 0; ii = 0; _ctx->i<_ctx->msg->NumPeriods() && !bSkipIdle; _ctx->i++) { if (bIsBack) { - curBackText = text = new RMTextDialogScrolling(Loc); + curBackText = _ctx->text = new RMTextDialogScrolling(Loc); if (bTonyIsSpeaking) curBackText->Hide(); } else - text = new RMTextDialog; + _ctx->text = new RMTextDialog; - text->SetInput(Input); + _ctx->text->SetInput(Input); // Skipping - text->SetSkipStatus(!bIsBack); + _ctx->text->SetSkipStatus(!bIsBack); // Allineamento - text->SetAlignType(RMText::HCENTER,RMText::VBOTTOM); + _ctx->text->SetAlignType(RMText::HCENTER,RMText::VBOTTOM); // Colore - text->SetColor(Character[nChar].r,Character[nChar].g,Character[nChar].b); + _ctx->text->SetColor(Character[nChar].r,Character[nChar].g,Character[nChar].b); // Scrive il testo - text->WriteText(msg[i],0); + _ctx->text->WriteText((*_ctx->msg)[_ctx->i],0); // Setta la posizione - text->SetPosition(pt); + _ctx->text->SetPosition(_ctx->pt); // Setta l'always display - if (bAlwaysDisplay) { text->SetAlwaysDisplay(); text->ForceTime(); } + if (bAlwaysDisplay) { _ctx->text->SetAlwaysDisplay(); _ctx->text->ForceTime(); } // Registra il testo - LinkGraphicTask(text); + LinkGraphicTask(_ctx->text); - if (curVoc) { + if (_ctx->curVoc) { g_system->lockMutex(vdb); - _vm->_theSound.CreateSfx(&voice); - _vm->_vdbFP.seek(curOffset); - voice->LoadVoiceFromVDB(_vm->_vdbFP); - voice->SetLoop(false); - if (bIsBack) voice->SetVolume(55); - voice->Play(); - text->SetCustomSkipHandle2(voice->hEndOfBuffer); - curOffset = _vm->_vdbFP.pos(); + _vm->_theSound.CreateSfx(&_ctx->voice); + _vm->_vdbFP.seek(_ctx->curOffset); + _ctx->voice->LoadVoiceFromVDB(_vm->_vdbFP); + _ctx->voice->SetLoop(false); + if (bIsBack) _ctx->voice->SetVolume(55); + _ctx->voice->Play(); + _ctx->text->SetCustomSkipHandle2(_ctx->voice->hEndOfBuffer); + _ctx->curOffset = _vm->_vdbFP.pos(); g_system->unlockMutex(vdb); } // Aspetta la fine della visualizzazione - text->SetCustomSkipHandle(hSkipIdle); - text->WaitForEndDisplay(); + _ctx->text->SetCustomSkipHandle(hSkipIdle); + _ctx->text->WaitForEndDisplay(); - if (curVoc) { - voice->Stop(); - voice->Release(); - voice=NULL; + if (_ctx->curVoc) { + _ctx->voice->Stop(); + _ctx->voice->Release(); + _ctx->voice=NULL; } curBackText=NULL; - delete text; + delete _ctx->text; } if (Character[nChar].endtalkpattern != 0) { Freeze(); Character[nChar].item->SetPattern(Character[nChar].endtalkpattern); Unfreeze(); - Character[nChar].item->WaitForEndPattern(); + CORO_INVOKE_0(Character[nChar].item->WaitForEndPattern); } Freeze(); Character[nChar].item->SetPattern(Character[nChar].standpattern); Unfreeze(); + delete _ctx->msg; + + CORO_END_CODE; } DECLARE_CUSTOM_FUNCTION(AddInventory)(CORO_PARAM, uint32 dwCode, uint32, uint32, uint32) { @@ -1698,97 +1883,104 @@ DECLARE_CUSTOM_FUNCTION(MCharSendMessage)(CORO_PARAM, uint32 nChar, uint32 dwMes int curDialog; DECLARE_CUSTOM_FUNCTION(SendDialogMessage)(CORO_PARAM, uint32 nPers, uint32 nMsg, uint32, uint32) { - LPSTR string; - RMTextDialog *text; - int parm; - HANDLE h; - bool bIsBack = false; + CORO_BEGIN_CONTEXT; + LPSTR string; + RMTextDialog *text; + int parm; + HANDLE h; + bool bIsBack; + VoiceHeader *curVoc; + FPSFX *voice; + RMPoint pt; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + + _ctx->bIsBack = false; // La SendDialogMessage puņ andare in background se č un personaggio in MCHAR settato // con la SetAlwaysBack if (nPers != 0 && IsMChar[nPers] && MCharacter[nPers].bAlwaysBack) - bIsBack = true; + _ctx->bIsBack = true; - VoiceHeader *curVoc = SearchVoiceHeader(curDialog, nMsg); - FPSFX *voice = NULL; + _ctx->curVoc = SearchVoiceHeader(curDialog, nMsg); + _ctx->voice = NULL; - if (curVoc) { + if (_ctx->curVoc) { // Si posiziona all'interno del database delle voci all'inizio della prima g_system->lockMutex(vdb); -// fseek(_vm->m_vdbFP, curVoc->offset, SEEK_SET); - _vm->_vdbFP.seek(curVoc->offset); - _vm->_theSound.CreateSfx(&voice); - voice->LoadVoiceFromVDB(_vm->_vdbFP); - voice->SetLoop(false); - if (bIsBack) voice->SetVolume(55); +// fseek(_vm->m_vdbFP, _ctx->curVoc->offset, SEEK_SET); + _vm->_vdbFP.seek(_ctx->curVoc->offset); + _vm->_theSound.CreateSfx(&_ctx->voice); + _ctx->voice->LoadVoiceFromVDB(_vm->_vdbFP); + _ctx->voice->SetLoop(false); + if (_ctx->bIsBack) _ctx->voice->SetVolume(55); g_system->unlockMutex(vdb); } - string = mpalQueryDialogPeriod(nMsg); + _ctx->string = mpalQueryDialogPeriod(nMsg); if (nPers == 0) { - text = new RMTextDialog; - text->SetColor(0,255,0); - text->SetPosition(Tony->Position()-RMPoint(0,130)-Loc->ScrollPosition()); - text->WriteText(string,0); + _ctx->text = new RMTextDialog; + _ctx->text->SetColor(0,255,0); + _ctx->text->SetPosition(Tony->Position()-RMPoint(0,130)-Loc->ScrollPosition()); + _ctx->text->WriteText(_ctx->string,0); if (dwTonyNumTexts > 0) { if (!bTonyInTexts) { if (nTonyNextTalkType != Tony->TALK_NORMAL) { - Tony->StartTalk(nTonyNextTalkType); + CORO_INVOKE_1(Tony->StartTalk, nTonyNextTalkType); if (!bStaticTalk) nTonyNextTalkType = Tony->TALK_NORMAL; } else - Tony->StartTalk(Tony->TALK_NORMAL); + CORO_INVOKE_1(Tony->StartTalk, Tony->TALK_NORMAL); bTonyInTexts = true; } dwTonyNumTexts--; } else { - Tony->StartTalk(nTonyNextTalkType); + CORO_INVOKE_1(Tony->StartTalk, nTonyNextTalkType); if (!bStaticTalk) nTonyNextTalkType = Tony->TALK_NORMAL; } } else if (!IsMChar[nPers]) { - RMPoint pt; - - text = new RMTextDialog; + _ctx->text = new RMTextDialog; - pt=Character[nPers].item->CalculatePos()-RMPoint(-60,20)-Loc->ScrollPosition(); + _ctx->pt = Character[nPers].item->CalculatePos() - RMPoint(-60, 20) - Loc->ScrollPosition(); if (Character[nPers].starttalkpattern != 0) { Freeze(); Character[nPers].item->SetPattern(Character[nPers].starttalkpattern); Unfreeze(); - Character[nPers].item->WaitForEndPattern(); + CORO_INVOKE_0(Character[nPers].item->WaitForEndPattern); } Character[nPers].item->SetPattern(Character[nPers].talkpattern); - text->SetColor(Character[nPers].r,Character[nPers].g,Character[nPers].b); - text->WriteText(string,0); - text->SetPosition(pt); + _ctx->text->SetColor(Character[nPers].r, Character[nPers].g,Character[nPers].b); + _ctx->text->WriteText(_ctx->string, 0); + _ctx->text->SetPosition(_ctx->pt); } else { RMPoint pt; - if (MCharacter[nPers].x==-1) - pt=MCharacter[nPers].item->CalculatePos()-RMPoint(-60,20)-Loc->ScrollPosition(); + if (MCharacter[nPers].x == -1) + pt = MCharacter[nPers].item->CalculatePos() - RMPoint(-60, 20) - Loc->ScrollPosition(); else - pt=RMPoint(MCharacter[nPers].x,MCharacter[nPers].y); + pt = RMPoint(MCharacter[nPers].x, MCharacter[nPers].y); // Parametro per le azioni speciali: random tra le parlate - parm = (MCharacter[nPers].curgroup * 10) + _vm->_randomSource.getRandomNumber( + _ctx->parm = (MCharacter[nPers].curgroup * 10) + _vm->_randomSource.getRandomNumber( MCharacter[nPers].numtalks[MCharacter[nPers].curgroup] - 1) + 1; if (MCharacter[nPers].numtexts != 0 && MCharacter[nPers].bInTexts) { MCharacter[nPers].numtexts--; } else { // Cerca di eseguire la funzione custom per inizializzare la parlata - h = mpalQueryDoAction(30, MCharacter[nPers].item->MpalCode(), parm); - if (h != INVALID_HANDLE_VALUE) - WaitForSingleObject(h,INFINITE); + _ctx->h = mpalQueryDoAction(30, MCharacter[nPers].item->MpalCode(), _ctx->parm); + if (_ctx->h != INVALID_HANDLE_VALUE) + WaitForSingleObject(_ctx->h,INFINITE); - MCharacter[nPers].curTalk = parm; + MCharacter[nPers].curTalk = _ctx->parm; if (MCharacter[nPers].numtexts != 0) { MCharacter[nPers].bInTexts = true; @@ -1797,39 +1989,39 @@ DECLARE_CUSTOM_FUNCTION(SendDialogMessage)(CORO_PARAM, uint32 nPers, uint32 nMsg } if (MCharacter[nPers].bAlwaysBack) { - text = curBackText = new RMTextDialogScrolling(Loc); + _ctx->text = curBackText = new RMTextDialogScrolling(Loc); if (bTonyIsSpeaking) curBackText->Hide(); - bIsBack = true; + _ctx->bIsBack = true; } else - text = new RMTextDialog; + _ctx->text = new RMTextDialog; - text->SetSkipStatus(!MCharacter[nPers].bAlwaysBack); - text->SetColor(MCharacter[nPers].r,MCharacter[nPers].g,MCharacter[nPers].b); - text->WriteText(string,0); - text->SetPosition(pt); + _ctx->text->SetSkipStatus(!MCharacter[nPers].bAlwaysBack); + _ctx->text->SetColor(MCharacter[nPers].r,MCharacter[nPers].g,MCharacter[nPers].b); + _ctx->text->WriteText(_ctx->string,0); + _ctx->text->SetPosition(pt); } if (!bSkipIdle) { - text->SetInput(Input); - if (bAlwaysDisplay) { text->SetAlwaysDisplay(); text->ForceTime(); } - text->SetAlignType(RMText::HCENTER,RMText::VBOTTOM); - LinkGraphicTask(text); - - if (curVoc) { - voice->Play(); - text->SetCustomSkipHandle2(voice->hEndOfBuffer); + _ctx->text->SetInput(Input); + if (bAlwaysDisplay) { _ctx->text->SetAlwaysDisplay(); _ctx->text->ForceTime(); } + _ctx->text->SetAlignType(RMText::HCENTER,RMText::VBOTTOM); + LinkGraphicTask(_ctx->text); + + if (_ctx->curVoc) { + _ctx->voice->Play(); + _ctx->text->SetCustomSkipHandle2(_ctx->voice->hEndOfBuffer); } // Aspetta la fine della visualizzazione - text->SetCustomSkipHandle(hSkipIdle); - text->WaitForEndDisplay(); + _ctx->text->SetCustomSkipHandle(hSkipIdle); + _ctx->text->WaitForEndDisplay(); } - if (curVoc) { - voice->Stop(); - voice->Release(); - voice=NULL; + if (_ctx->curVoc) { + _ctx->voice->Stop(); + _ctx->voice->Release(); + _ctx->voice=NULL; } if (nPers != 0) { @@ -1838,37 +2030,39 @@ DECLARE_CUSTOM_FUNCTION(SendDialogMessage)(CORO_PARAM, uint32 nPers, uint32 nMsg Freeze(); Character[nPers].item->SetPattern(Character[nPers].endtalkpattern); Unfreeze(); - Character[nPers].item->WaitForEndPattern(); + CORO_INVOKE_0(Character[nPers].item->WaitForEndPattern); } Character[nPers].item->SetPattern(Character[nPers].standpattern); - delete text; + delete _ctx->text; } else { if ((MCharacter[nPers].bInTexts && MCharacter[nPers].numtexts== 0) || !MCharacter[nPers].bInTexts) { // Cerca di eseguire la funzione custom per chiudere la parlata MCharacter[nPers].curTalk = (MCharacter[nPers].curTalk%10) + MCharacter[nPers].curgroup*10; - h = mpalQueryDoAction(31,MCharacter[nPers].item->MpalCode(),MCharacter[nPers].curTalk); - if (h!=INVALID_HANDLE_VALUE) - WaitForSingleObject(h,INFINITE); + _ctx->h = mpalQueryDoAction(31,MCharacter[nPers].item->MpalCode(),MCharacter[nPers].curTalk); + if (_ctx->h!=INVALID_HANDLE_VALUE) + WaitForSingleObject(_ctx->h,INFINITE); MCharacter[nPers].bInTexts = false; MCharacter[nPers].numtexts = 0; } curBackText = NULL; - delete text; + delete _ctx->text; } } else { if ((dwTonyNumTexts== 0 && bTonyInTexts) || !bTonyInTexts) { - Tony->EndTalk(); + CORO_INVOKE_0(Tony->EndTalk); dwTonyNumTexts = 0; bTonyInTexts = false; } - delete text; + delete _ctx->text; } - GlobalFree(string); + GlobalFree(_ctx->string); + + CORO_END_CODE; } diff --git a/engines/tony/loc.cpp b/engines/tony/loc.cpp index 9a2f4cfe6a..e6914ebc87 100644 --- a/engines/tony/loc.cpp +++ b/engines/tony/loc.cpp @@ -705,8 +705,9 @@ bool RMItem::DoFrame(RMGfxTargetBuffer *bigBuf, bool bAddToList) { return false; // Facciamo un update del pattern, che ci ritorna anche il frame corrente + // FIXME: Get rid of HANDLE cast if (m_nCurPattern != 0) - m_nCurSprite=m_patterns[m_nCurPattern].Update(m_hEndPattern,m_bCurFlag, m_sfx); + m_nCurSprite = m_patterns[m_nCurPattern].Update((HANDLE)m_hEndPattern, m_bCurFlag, m_sfx); // Se la funzione ha ritornato -1, vuol dire che il pattern e' finito if (m_nCurSprite == -1) { @@ -831,30 +832,36 @@ RMItem::RMItem() { m_nSprites = 0; m_nSfx = 0; m_nPatterns = 0; - m_hEndPattern = 0; m_bPal = 0; m_nCurSprite = 0; - m_hEndPattern = CreateEvent(NULL, false, false, NULL); + m_hEndPattern = _vm->_scheduler.createEvent(false, false); } RMItem::~RMItem() { - Unload(); - CloseHandle(m_hEndPattern); + Unload(); + _vm->_scheduler.closeEvent(m_hEndPattern); } -void RMItem::WaitForEndPattern(HANDLE hCustomSkip) { +//FIXME: Pass uint32 directly for hCustomSkip +void RMItem::WaitForEndPattern(CORO_PARAM, HANDLE hCustomSkip) { + CORO_BEGIN_CONTEXT; + uint32 h[2]; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + if (m_nCurPattern != 0) { if (hCustomSkip == INVALID_HANDLE_VALUE) - WaitForSingleObject(m_hEndPattern,INFINITE); + CORO_INVOKE_2(_vm->_scheduler.waitForSingleObject, m_hEndPattern, INFINITE); else { - HANDLE h[2]; - - h[0] = hCustomSkip; - h[1] = m_hEndPattern; - WaitForMultipleObjects(2, h, false, INFINITE); + _ctx->h[0] = (uint32)hCustomSkip; + _ctx->h[1] = m_hEndPattern; + CORO_INVOKE_4(_vm->_scheduler.waitForMultipleObjects, 2, &_ctx->h[0], false, INFINITE); } } + + CORO_END_CODE; } void RMItem::ChangeHotspot(RMPoint pt) { diff --git a/engines/tony/loc.h b/engines/tony/loc.h index 9ed1a284d1..3a312a0d3c 100644 --- a/engines/tony/loc.h +++ b/engines/tony/loc.h @@ -52,6 +52,7 @@ #include "common/system.h" #include "common/file.h" #include "tony/mpal/stubs.h" +#include "tony/sched.h" #include "tony/sound.h" #include "tony/utils.h" @@ -245,7 +246,7 @@ private: byte m_bCurFlag; int m_nCurSprite; bool m_bIsActive; - HANDLE m_hEndPattern; + uint32 m_hEndPattern; bool m_bInitCurPattern; public: @@ -291,7 +292,7 @@ public: void Unload(void); // Aspetta la fine del pattern in play - void WaitForEndPattern(HANDLE hCustomSkip = INVALID_HANDLE_VALUE); + void WaitForEndPattern(CORO_PARAM, HANDLE hCustomSkip = INVALID_HANDLE_VALUE); // Setta un nuovo hotspot per l'oggetto void ChangeHotspot(RMPoint pt); diff --git a/engines/tony/mpal/mpal.cpp b/engines/tony/mpal/mpal.cpp index 592c4788df..c5ded67c81 100644 --- a/engines/tony/mpal/mpal.cpp +++ b/engines/tony/mpal/mpal.cpp @@ -141,8 +141,8 @@ uint32 nPollingLocations[MAXPOLLINGLOCATIONS]; HANDLE hEndPollingLocations[MAXPOLLINGLOCATIONS]; uint32 PollingThreads[MAXPOLLINGLOCATIONS]; -HANDLE hAskChoice; -HANDLE hDoneChoice; +uint32 hAskChoice; +uint32 hDoneChoice; uint32 nExecutingAction; @@ -1349,7 +1349,7 @@ void ShutUpDialogThread(CORO_PARAM, const void *param) { nExecutingDialog = 0; nExecutingChoice = 0; - SetEvent(hAskChoice); + _vm->_scheduler.setEvent(hAskChoice); CORO_KILL_SELF(); @@ -1501,9 +1501,9 @@ void DoChoice(CORO_PARAM, uint32 nChoice) { /* Avvertiamo il gioco che c'e' una scelta da far fare all'utente, e restiamo in attesa della risposta */ - ResetEvent(hDoneChoice); - SetEvent(hAskChoice); - WaitForSingleObject(hDoneChoice, INFINITE); + _vm->_scheduler.resetEvent(hDoneChoice); + _vm->_scheduler.setEvent(hAskChoice); + CORO_INVOKE_2(_vm->_scheduler.waitForSingleObject, hDoneChoice, INFINITE); /* Ora che la scelta e' stata effettuata, possiamo eseguire _ctx->i gruppi associati con la scelta */ @@ -1644,8 +1644,8 @@ static uint32 DoDialog(uint32 nDlgOrd, uint32 nGroup) { // Enables the flag to indicate that there is' a running dialogue bExecutingDialog = true; - ResetEvent(hAskChoice); - ResetEvent(hDoneChoice); + _vm->_scheduler.resetEvent(hAskChoice); + _vm->_scheduler.resetEvent(hDoneChoice); // Create a thread that performs the dialogue group @@ -1690,7 +1690,7 @@ bool DoSelection(uint32 i, uint32 dwData) { return false; nSelectedChoice = j; - SetEvent(hDoneChoice); + _vm->_scheduler.setEvent(hDoneChoice); return true; } @@ -1867,8 +1867,8 @@ bool mpalInit(const char *lpszMpcFileName, const char *lpszMprFileName, /* Crea l'evento che verra' utilizzato per avvertire il gioco che c'e' da effettuare una scelta */ - hAskChoice = CreateEvent(NULL, true, false, NULL); - hDoneChoice = CreateEvent(NULL, true, false, NULL); + hAskChoice = _vm->_scheduler.createEvent(true, false); + hDoneChoice = _vm->_scheduler.createEvent(true, false); return true; } @@ -2031,8 +2031,9 @@ void mpalQueryInner(CORO_PARAM, uint16 wQueryType, uint32 *dwRet, va_list v) { /* * void mpalQuery(MPQ_DIALOG_WAITFORCHOICE); */ - WaitForSingleObject(hAskChoice, INFINITE); - ResetEvent(hAskChoice); + CORO_INVOKE_2(_vm->_scheduler.waitForSingleObject, hAskChoice, INFINITE); + + _vm->_scheduler.resetEvent(hAskChoice); if (bExecutingDialog) *dwRet = (uint32)nExecutingChoice; diff --git a/engines/tony/mpal/stubs.cpp b/engines/tony/mpal/stubs.cpp index 0fc01d4d07..58ecc6d6d9 100644 --- a/engines/tony/mpal/stubs.cpp +++ b/engines/tony/mpal/stubs.cpp @@ -90,16 +90,20 @@ uint32 WaitForMultipleObjects(uint32 nCount, const HANDLE *lpHandles, bool bWait } HANDLE CreateEvent(void *lpEventAttributes, bool bManualReset, bool bInitialState, const char *lpName) { + warning("TODO: Refactor call to old style CreateEvent method"); return 0; } void SetEvent(HANDLE hEvent) { + warning("TODO: Refactor call to old style SetEvent method"); } void ResetEvent(HANDLE hEvent) { + warning("TODO: Refactor call to old style ResetEvent method"); } void PulseEvent(HANDLE hEvent) { + warning("TODO: Refactor call to old style PulseEvent method"); } uint16 GetAsyncKeyState(Common::KeyCode kc) { diff --git a/engines/tony/sched.cpp b/engines/tony/sched.cpp index 41531bf225..199f5991ce 100644 --- a/engines/tony/sched.cpp +++ b/engines/tony/sched.cpp @@ -67,6 +67,11 @@ Scheduler::~Scheduler() { delete active; active = 0; + + // Clear the event list + Common::List::iterator i; + for (i = _events.begin(); i != _events.end(); ++i) + delete (*i); } /** @@ -292,39 +297,52 @@ void Scheduler::giveWay(PPROCESS pReSchedProc) { } /** - * Continously makes a given process wait for another process to finish + * Continously makes a given process wait for another process to finish or event to signal. * - * @param pid Process identifier + * @param pid Process/Event identifier * @param duration Duration in milliseconds - * @param expired Set to true if delay period expired + * @param expired If specified, set to true if delay period expired */ -void Scheduler::waitForSingleObject(CORO_PARAM, int pid, int duration, bool *expired) { +void Scheduler::waitForSingleObject(CORO_PARAM, int pid, uint32 duration, bool *expired) { if (!pCurrent) error("Called Scheduler::waitForSingleObject from the main process"); CORO_BEGIN_CONTEXT; uint32 endTime; - PROCESS *pProc; + PROCESS *pProcess; + EVENT *pEvent; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); _ctx->endTime = (duration == INFINITE) ? INFINITE : g_system->getMillis() + duration; if (expired) - *expired = false; + // Presume it will expire + *expired = true; // Outer loop for doing checks until expiry while (g_system->getMillis() < _ctx->endTime) { - // Check to see if a process with the given Id exists - _ctx->pProc = active->pNext; - while ((_ctx->pProc != NULL) && (_ctx->pProc->pid != pid)) - _ctx->pProc = _ctx->pProc->pNext; + // Check to see if a process or event with the given Id exists + _ctx->pProcess = getProcess(pid); + _ctx->pEvent = !_ctx->pProcess ? getEvent(pid) : NULL; - if (_ctx->pProc == NULL) { - // No match process found, so it's okay to break out of loop + // If there's no active process or event, presume it's a process that's finished, + // so the waiting can immediately exit + if ((_ctx->pProcess == NULL) && (_ctx->pEvent == NULL)) { if (expired) - *expired = true; + *expired = false; + break; + } + + // If a process was found, don't go into the if statement, and keep waiting. + // Likewise if it's an event that's not yet signalled + if ((_ctx->pEvent != NULL) && _ctx->pEvent->signalled) { + // Unless the event is flagged for manual reset, reset it now + if (!_ctx->pEvent->manualReset) + _ctx->pEvent->signalled = false; + if (expired) + *expired = false; break; } @@ -335,6 +353,76 @@ void Scheduler::waitForSingleObject(CORO_PARAM, int pid, int duration, bool *exp CORO_END_CODE; } +/** + * Continously makes a given process wait for given prcesses to finished or events to be set + * + * @param nCount Number of Id's being passed + * @param evtList List of pids to wait for + * @param bWaitAll Specifies whether all or any of the processes/events + * @param duration Duration in milliseconds + * @param expired Set to true if delay period expired + */ +void Scheduler::waitForMultipleObjects(CORO_PARAM, int nCount, uint32 *pidList, bool bWaitAll, + uint32 duration, bool *expired) { + if (!pCurrent) + error("Called Scheduler::waitForMultipleEvents from the main process"); + + CORO_BEGIN_CONTEXT; + uint32 endTime; + bool signalled; + bool pidSignalled; + int i; + PROCESS *pProcess; + EVENT *pEvent; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + + _ctx->endTime = (duration == INFINITE) ? INFINITE : g_system->getMillis() + duration; + if (expired) + // Presume that delay will expire + *expired = true; + + // Outer loop for doing checks until expiry + while (g_system->getMillis() < _ctx->endTime) { + _ctx->signalled = bWaitAll; + + for (_ctx->i = 0; _ctx->i < nCount; ++_ctx->i) { + _ctx->pProcess = getProcess(pidList[_ctx->i]); + _ctx->pEvent = !_ctx->pProcess ? getEvent(pidList[_ctx->i]) : NULL; + + // Determine the signalled state + _ctx->pidSignalled = (_ctx->pProcess) || !_ctx->pEvent ? false : _ctx->pEvent->signalled; + + if (bWaitAll && _ctx->pidSignalled) + _ctx->signalled = false; + else if (!bWaitAll & _ctx->pidSignalled) + _ctx->signalled = true; + } + + // At this point, if the signalled variable is set, waiting is finished + if (_ctx->signalled) { + // Automatically reset any events not flagged for manual reset + for (_ctx->i = 0; _ctx->i < nCount; ++_ctx->i) { + _ctx->pEvent = getEvent(pidList[_ctx->i]); + + if (_ctx->pEvent->manualReset) + _ctx->pEvent->signalled = false; + } + + if (expired) + *expired = false; + break; + } + + // Sleep until the next cycle + CORO_SLEEP(1); + } + + CORO_END_CODE; +} + + /** * Creates a new process. * @@ -541,4 +629,72 @@ void Scheduler::setResourceCallback(VFPTRPP pFunc) { pRCfunction = pFunc; } +PROCESS *Scheduler::getProcess(uint32 pid) { + PROCESS *pProc = active->pNext; + while ((pProc != NULL) && (pProc->pid != pid)) + pProc = pProc->pNext; + + return pProc; +} + +EVENT *Scheduler::getEvent(uint32 pid) { + Common::List::iterator i; + for (i = _events.begin(); i != _events.end(); ++i) { + EVENT *evt = *i; + if (evt->pid == pid) + return evt; + } + + return NULL; +} + + +/** + * Creates a new event object + * @param bManualReset Events needs to be manually reset. Otherwise, events + * will be automatically reset after a process waits on the event finishes + * @param bInitialState Specifies whether the event is signalled or not initially + */ +uint32 Scheduler::createEvent(bool bManualReset, bool bInitialState) { + EVENT *evt = new EVENT(); + evt->pid = ++pidCounter; + evt->manualReset = bManualReset; + evt->signalled = bInitialState; + + _events.push_back(evt); + return evt->pid; +} + +/** + * Destroys the given event + * @param pidEvent Event PID + */ +void Scheduler::closeEvent(uint32 pidEvent) { + EVENT *evt = getEvent(pidEvent); + if (evt) { + _events.remove(evt); + delete evt; + } +} + +/** + * Sets the event + * @param pidEvent Event PID + */ +void Scheduler::setEvent(uint32 pidEvent) { + EVENT *evt = getEvent(pidEvent); + if (evt) + evt->signalled = true; +} + +/** + * Resets the event + * @param pidEvent Event PID + */ +void Scheduler::resetEvent(uint32 pidEvent) { + EVENT *evt = getEvent(pidEvent); + if (evt) + evt->signalled = false; +} + } // End of namespace Tony diff --git a/engines/tony/sched.h b/engines/tony/sched.h index 54f44aa5fd..80df1eb942 100644 --- a/engines/tony/sched.h +++ b/engines/tony/sched.h @@ -24,6 +24,7 @@ #ifndef TONY_SCHED_H #define TONY_SCHED_H +#include "common/list.h" #include "tony/coroutine.h" namespace Tony { @@ -48,13 +49,20 @@ struct PROCESS { CORO_ADDR coroAddr; ///< the entry point of the coroutine int sleepTime; ///< number of scheduler cycles to sleep - int pid; ///< process ID + uint32 pid; ///< process ID char param[PARAM_SIZE]; ///< process specific info }; typedef PROCESS *PPROCESS; struct INT_CONTEXT; +/** Event structure */ +struct EVENT { + uint32 pid; + bool manualReset; + bool signalled; +}; + /** * Create and manage "processes" (really coroutines). */ @@ -80,6 +88,8 @@ private: /** Auto-incrementing process Id */ int pidCounter; + /** Event list */ + Common::List _events; #ifdef DEBUG // diagnostic process counters @@ -95,7 +105,8 @@ private: */ VFPTRPP pRCfunction; - + PROCESS *getProcess(uint32 pid); + EVENT *getEvent(uint32 pid); public: Scheduler(); @@ -111,7 +122,9 @@ public: void rescheduleAll(); void reschedule(PPROCESS pReSchedProc = NULL); void giveWay(PPROCESS pReSchedProc = NULL); - void waitForSingleObject(CORO_PARAM, int pid, int duration, bool *delay = NULL); + void waitForSingleObject(CORO_PARAM, int pid, uint32 duration, bool *expired = NULL); + void waitForMultipleObjects(CORO_PARAM, int nCount, uint32 *pidList, bool bWaitAll, + uint32 duration, bool *expired = NULL); uint32 createProcess(CORO_ADDR coroAddr, const void *pParam, int sizeParam); uint32 createProcess(CORO_ADDR coroAddr, const void *pParam) { @@ -123,9 +136,13 @@ public: int getCurrentPID() const; int killMatchingProcess(int pidKill, int pidMask = -1); - void setResourceCallback(VFPTRPP pFunc); + /* Event methods */ + uint32 createEvent(bool bManualReset, bool bInitialState); + void closeEvent(uint32 pidEvent); + void setEvent(uint32 pidEvent); + void resetEvent(uint32 pidEvent); }; extern Scheduler *g_scheduler; // FIXME: Temporary global var, to be used until everything has been OOifyied diff --git a/engines/tony/tonychar.cpp b/engines/tony/tonychar.cpp index de6189876b..073ebf2be4 100644 --- a/engines/tony/tonychar.cpp +++ b/engines/tony/tonychar.cpp @@ -519,10 +519,8 @@ void RMTony::Put(int nWhere, int nPart) { } -void RMTony::StartTalk(TALKTYPE nTalkType) { - int headStartPat = 0, bodyStartPat = 0; - int headLoopPat = 0, bodyLoopPat = 0; - +bool RMTony::StartTalkCalculate(TALKTYPE nTalkType, int &headStartPat, int &bodyStartPat, + int &headLoopPat, int &bodyLoopPat) { assert(!m_bIsTalking); m_bIsTalking = true; @@ -585,7 +583,7 @@ void RMTony::StartTalk(TALKTYPE nTalkType) { break; } MainUnfreeze(); - return; + return false; } headStartPat = bodyStartPat = 0; @@ -1077,35 +1075,47 @@ void RMTony::StartTalk(TALKTYPE nTalkType) { } break; } +} + +void RMTony::StartTalk(CORO_PARAM, TALKTYPE nTalkType) { + CORO_BEGIN_CONTEXT; + int headStartPat, bodyStartPat; + int headLoopPat, bodyLoopPat; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + + _ctx->headStartPat = _ctx->bodyStartPat = 0; + _ctx->headLoopPat = _ctx->bodyLoopPat = 0; + + if (!StartTalkCalculate(nTalkType, _ctx->headStartPat, _ctx->bodyStartPat, + _ctx->headLoopPat, _ctx->bodyLoopPat)) + return; // Esegue il set dei pattern vero e proprio - if (headStartPat != 0 || bodyStartPat != 0) { + if (_ctx->headStartPat != 0 || _ctx->bodyStartPat != 0) { MainFreeze(); - SetPattern(headStartPat); - m_body.SetPattern(bodyStartPat); + SetPattern(_ctx->headStartPat); + m_body.SetPattern(_ctx->bodyStartPat); MainUnfreeze(); - if (bodyStartPat!=0) - m_body.WaitForEndPattern(); - if (headStartPat!=0) - WaitForEndPattern(); + if (_ctx->bodyStartPat != 0) + CORO_INVOKE_0(m_body.WaitForEndPattern); + if (_ctx->headStartPat != 0) + CORO_INVOKE_0(WaitForEndPattern); } MainFreeze(); - SetPattern(headLoopPat); - if (bodyLoopPat) - m_body.SetPattern(bodyLoopPat); + SetPattern(_ctx->headLoopPat); + if (_ctx->bodyLoopPat) + m_body.SetPattern(_ctx->bodyLoopPat); MainUnfreeze(); -} + CORO_END_CODE; +} -void RMTony::EndTalk(void) { - int headStandPat = 0; - int headEndPat = 0; - int bodyEndPat = 0; - int finalPat = 0; - bool bStatic = false; +bool RMTony::EndTalkCalculate(int &headStandPat, int &headEndPat, int &bodyEndPat, int &finalPat, bool &bStatic) { bodyEndPat = 0; headEndPat = 0; @@ -1136,7 +1146,7 @@ void RMTony::EndTalk(void) { SetPattern(finalPat); MainUnfreeze(); m_bIsTalking = false; - return; + return false; } @@ -1379,6 +1389,28 @@ void RMTony::EndTalk(void) { break; } + return true; +} + +void RMTony::EndTalk(CORO_PARAM) { + CORO_BEGIN_CONTEXT; + int headStandPat, headEndPat; + int bodyEndPat, finalPat; + bool bStatic; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + + _ctx->headStandPat = _ctx->headEndPat = 0; + _ctx->bodyEndPat = _ctx->finalPat = 0; + _ctx->bStatic = false; + + _ctx->bodyEndPat = 0; + _ctx->headEndPat = 0; + + if (!EndTalkCalculate(_ctx->headStandPat, _ctx->headEndPat, _ctx->bodyEndPat, _ctx->finalPat, _ctx->bStatic)) + return; + // Gestisce la fine di una animazione static lasciando tutto invariato if (m_bIsStaticTalk) { if (m_nTalkType == TALK_CONBARBASTATIC) { @@ -1394,10 +1426,10 @@ void RMTony::EndTalk(void) { MainUnfreeze(); } else { MainFreeze(); - SetPattern(headStandPat); + SetPattern(_ctx->headStandPat); MainUnfreeze(); - m_body.WaitForEndPattern(); + CORO_INVOKE_0(m_body.WaitForEndPattern); } m_bIsTalking = false; @@ -1405,60 +1437,58 @@ void RMTony::EndTalk(void) { } // Set dei pattern - if (headEndPat != 0 && bodyEndPat != 0) { + if (_ctx->headEndPat != 0 && _ctx->bodyEndPat != 0) { MainFreeze(); - SetPattern(headEndPat); + SetPattern(_ctx->headEndPat); MainUnfreeze(); - m_body.WaitForEndPattern(); + CORO_INVOKE_0(m_body.WaitForEndPattern); MainFreeze(); - m_body.SetPattern(bodyEndPat); + m_body.SetPattern(_ctx->bodyEndPat); MainUnfreeze(); - WaitForEndPattern(); - m_body.WaitForEndPattern(); - } else if (bodyEndPat != 0) { + CORO_INVOKE_0(WaitForEndPattern); + CORO_INVOKE_0(m_body.WaitForEndPattern); + } else if (_ctx->bodyEndPat != 0) { MainFreeze(); - SetPattern(headStandPat); + SetPattern(_ctx->headStandPat); MainUnfreeze(); - m_body.WaitForEndPattern(); + CORO_INVOKE_0(m_body.WaitForEndPattern); MainFreeze(); - m_body.SetPattern(bodyEndPat); + m_body.SetPattern(_ctx->bodyEndPat); MainUnfreeze(); - m_body.WaitForEndPattern(); - } else if (headEndPat != 0) { - m_body.WaitForEndPattern(); + CORO_INVOKE_0(m_body.WaitForEndPattern); + } else if (_ctx->headEndPat != 0) { + CORO_INVOKE_0(m_body.WaitForEndPattern); MainFreeze(); - SetPattern(headEndPat); + SetPattern(_ctx->headEndPat); MainUnfreeze(); - WaitForEndPattern(); + CORO_INVOKE_0(WaitForEndPattern); } else { - m_body.WaitForEndPattern(); + CORO_INVOKE_0(m_body.WaitForEndPattern); } - if (finalPat != 0) { + if (_ctx->finalPat != 0) { MainFreeze(); m_body.SetPattern(0); - SetPattern(finalPat); + SetPattern(_ctx->finalPat); MainUnfreeze(); } m_bIsTalking = false; -} -void RMTony::StartStatic(TALKTYPE nTalk) { - int nPat = 0; - int headPat = 0, headLoopPat = 0; - int bodyStartPat = 0; - int bodyLoopPat = 0; + CORO_END_CODE; +} - nPat = GetCurPattern(); +void RMTony::StartStaticCalculate(TALKTYPE nTalk, int &headPat, int &headLoopPat, + int &bodyStartPat, int &bodyLoopPat) { + int nPat = GetCurPattern(); headLoopPat = -1; @@ -1661,31 +1691,41 @@ void RMTony::StartStatic(TALKTYPE nTalk) { default: break; } +} + +void RMTony::StartStatic(CORO_PARAM, TALKTYPE nTalk) { + CORO_BEGIN_CONTEXT; + int headPat, headLoopPat; + int bodyStartPat, bodyLoopPat; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + + _ctx->headPat = _ctx->headLoopPat = 0; + _ctx->bodyStartPat = _ctx->bodyLoopPat = 0; // e vai con i pattern m_bIsStaticTalk = true; MainFreeze(); - SetPattern(headPat); - m_body.SetPattern(bodyStartPat); + SetPattern(_ctx->headPat); + m_body.SetPattern(_ctx->bodyStartPat); MainUnfreeze(); - m_body.WaitForEndPattern(); - WaitForEndPattern(); + CORO_INVOKE_0(m_body.WaitForEndPattern); + CORO_INVOKE_0(WaitForEndPattern); MainFreeze(); - if (headLoopPat != -1) - SetPattern(headLoopPat); - m_body.SetPattern(bodyLoopPat); + if (_ctx->headLoopPat != -1) + SetPattern(_ctx->headLoopPat); + m_body.SetPattern(_ctx->bodyLoopPat); MainUnfreeze(); -} + CORO_END_CODE; +} -void RMTony::EndStatic(TALKTYPE nTalk) { - int bodyEndPat = 0; - int finalPat = 0; - int headEndPat = 0; +void RMTony::EndStaticCalculate(TALKTYPE nTalk, int &bodyEndPat, int &finalPat, int &headEndPat) { switch (m_TalkDirection) { case UP: case LEFT: @@ -1818,28 +1858,46 @@ void RMTony::EndStatic(TALKTYPE nTalk) { default: break; } +} + +void RMTony::EndStatic(CORO_PARAM, TALKTYPE nTalk) { + CORO_BEGIN_CONTEXT; + int bodyEndPat; + int finalPat; + int headEndPat; + CORO_END_CONTEXT(_ctx); - if (headEndPat != 0) { + CORO_BEGIN_CODE(_ctx); + + _ctx->bodyEndPat = 0; + _ctx->finalPat = 0; + _ctx->headEndPat = 0; + + EndStaticCalculate(nTalk, _ctx->bodyEndPat, _ctx->finalPat, _ctx->headEndPat); + + if (_ctx->headEndPat != 0) { MainFreeze(); - SetPattern(headEndPat); + SetPattern(_ctx->headEndPat); MainUnfreeze(); - WaitForEndPattern(); + CORO_INVOKE_0(WaitForEndPattern); } else { // Play please MainFreeze(); - m_body.SetPattern(bodyEndPat); + m_body.SetPattern(_ctx->bodyEndPat); MainUnfreeze(); - m_body.WaitForEndPattern(); + CORO_INVOKE_0(m_body.WaitForEndPattern); } MainFreeze(); - SetPattern(finalPat); + SetPattern(_ctx->finalPat); m_body.SetPattern(0); MainUnfreeze(); m_bIsStaticTalk = false; + + CORO_END_CODE; } } // End of namespace Tony diff --git a/engines/tony/tonychar.h b/engines/tony/tonychar.h index 266b34e697..2cbcf60a00 100644 --- a/engines/tony/tonychar.h +++ b/engines/tony/tonychar.h @@ -408,7 +408,9 @@ public: int GetCurPattern(); // Attende la fine di un pattern - void WaitForEndPattern(HANDLE hCustomSkip = INVALID_HANDLE_VALUE) { RMCharacter::WaitForEndPattern(hCustomSkip);} + void WaitForEndPattern(CORO_PARAM, HANDLE hCustomSkip = INVALID_HANDLE_VALUE) { + RMCharacter::WaitForEndPattern(coroParam, hCustomSkip); + } // Controlla se si trova in azione bool InAction() { return (m_bActionPending&&m_Action != 0) | m_bAction; } @@ -427,12 +429,18 @@ public: void Put(int nWhere, int nPart); // Start e End Talk - void StartTalk(TALKTYPE nTalkType); - void EndTalk(void); + bool StartTalkCalculate(TALKTYPE nTalkType, int &headStartPat, int &bodyStartPat, + int &headLoopPat, int &bodyLoopPat); + void StartTalk(CORO_PARAM, TALKTYPE nTalkType); + bool EndTalkCalculate(int &headStandPat, int &headEndPat, int &bodyEndPat, int &finalPat, bool &bStatic); + void EndTalk(CORO_PARAM); // Start e End Static - void StartStatic(TALKTYPE nTalkType); - void EndStatic(TALKTYPE nTalkType); + void StartStaticCalculate(TALKTYPE nTalk, int &headPat, int &headLoopPat, + int &bodyStartPat, int &bodyLoopPat); + void StartStatic(CORO_PARAM, TALKTYPE nTalkType); + void EndStaticCalculate(TALKTYPE nTalk, int &bodyEndPat, int &finalPat, int &headEndPat); + void EndStatic(CORO_PARAM, TALKTYPE nTalkType); // Tony si traveste! void SetPastorella(bool bIsPast) { m_bPastorella=bIsPast; } -- cgit v1.2.3