diff options
| -rw-r--r-- | engines/tony/custom.cpp | 9 | ||||
| -rw-r--r-- | engines/tony/loc.cpp | 30 | ||||
| -rw-r--r-- | engines/tony/loc.h | 4 | ||||
| -rw-r--r-- | engines/tony/mpal/mpal.cpp | 50 | ||||
| -rw-r--r-- | engines/tony/sched.cpp | 71 | ||||
| -rw-r--r-- | engines/tony/sched.h | 4 | ||||
| -rw-r--r-- | engines/tony/tony.cpp | 2 | ||||
| -rw-r--r-- | engines/tony/tonychar.cpp | 14 | 
8 files changed, 137 insertions, 47 deletions
| diff --git a/engines/tony/custom.cpp b/engines/tony/custom.cpp index 800b5d8d50..18a92899df 100644 --- a/engines/tony/custom.cpp +++ b/engines/tony/custom.cpp @@ -1310,10 +1310,17 @@ DECLARE_CUSTOM_FUNCTION(SetTonyPosition)(CORO_PARAM, uint32 nX, uint32 nY, uint3  }  DECLARE_CUSTOM_FUNCTION(MoveTonyAndWait)(CORO_PARAM, uint32 nX, uint32 nY, uint32, uint32) { +	CORO_BEGIN_CONTEXT; +	CORO_END_CONTEXT(_ctx); + +	CORO_BEGIN_CODE(_ctx); +  	Tony->Move(RMPoint(nX, nY));  	if (!bSkipIdle) -		Tony->WaitForEndMovement(); +		CORO_INVOKE_0(Tony->WaitForEndMovement); + +	CORO_END_CODE;  }  DECLARE_CUSTOM_FUNCTION(MoveTony)(CORO_PARAM, uint32 nX, uint32 nY, uint32, uint32) { diff --git a/engines/tony/loc.cpp b/engines/tony/loc.cpp index e6914ebc87..4eced3fbd5 100644 --- a/engines/tony/loc.cpp +++ b/engines/tony/loc.cpp @@ -835,12 +835,12 @@ RMItem::RMItem() {  	m_bPal = 0;  	m_nCurSprite = 0; -	m_hEndPattern = _vm->_scheduler.createEvent(false, false); +	m_hEndPattern = g_scheduler->createEvent(false, false);  }  RMItem::~RMItem() {  	Unload(); -	_vm->_scheduler.closeEvent(m_hEndPattern); +	g_scheduler->closeEvent(m_hEndPattern);  }  //FIXME: Pass uint32 directly for hCustomSkip @@ -853,11 +853,11 @@ void RMItem::WaitForEndPattern(CORO_PARAM, HANDLE hCustomSkip) {  	if (m_nCurPattern != 0) {  		if (hCustomSkip == INVALID_HANDLE_VALUE) -			CORO_INVOKE_2(_vm->_scheduler.waitForSingleObject, m_hEndPattern, INFINITE); +			CORO_INVOKE_2(g_scheduler->waitForSingleObject, m_hEndPattern, INFINITE);  		else {  			_ctx->h[0] = (uint32)hCustomSkip;  			_ctx->h[1] = m_hEndPattern; -			CORO_INVOKE_4(_vm->_scheduler.waitForMultipleObjects, 2, &_ctx->h[0], false, INFINITE); +			CORO_INVOKE_4(g_scheduler->waitForMultipleObjects, 2, &_ctx->h[0], false, INFINITE);  		}  	} @@ -1082,7 +1082,7 @@ void RMCharacter::GoTo(RMPoint destcoord, bool bReversed) {  	if (m_pos == destcoord) {  		if (minpath == 0) {  			Stop(); -			PulseEvent(hEndOfPath); +			g_scheduler->pulseEvent(hEndOfPath);  			return;  		}  	} @@ -1458,7 +1458,7 @@ void RMCharacter::DoFrame(RMGfxTargetBuffer* bigBuf, int loc) {  			if (!bEndOfPath)  				Stop();  			bEndOfPath = true; -			PulseEvent(hEndOfPath); +			g_scheduler->pulseEvent(hEndOfPath);  		}  		walkcount++; @@ -1496,7 +1496,7 @@ void RMCharacter::DoFrame(RMGfxTargetBuffer* bigBuf, int loc) {  					if (!bEndOfPath)  						Stop();  					bEndOfPath = true; -					PulseEvent(hEndOfPath); +					g_scheduler->pulseEvent(hEndOfPath);  				}  			} else {  				// Se siamo già entrati nell'ultimo box, dobbiamo solo muoverci in linea retta verso il @@ -1636,6 +1636,18 @@ void RMCharacter::SetPosition(RMPoint pt, int newloc) {  	bRemoveFromOT = true;  } +void RMCharacter::WaitForEndMovement(CORO_PARAM) {  +	CORO_BEGIN_CONTEXT; +	CORO_END_CONTEXT(_ctx); + +	CORO_BEGIN_CODE(_ctx); + +	if (bMoving)  +		CORO_INVOKE_2(g_scheduler->waitForSingleObject, hEndOfPath, INFINITE);  + +	CORO_END_CODE; +} +  bool RMCharacter::RemoveThis(void) {  	if (bRemoveFromOT)  		return true; @@ -1645,7 +1657,7 @@ bool RMCharacter::RemoveThis(void) {  RMCharacter::RMCharacter() {  	csMove = g_system->createMutex(); -	hEndOfPath = CreateEvent(NULL, false, false, NULL); +	hEndOfPath = g_scheduler->createEvent(false, false);  	minpath = 0;  	curSpeed = 3;  	bRemoveFromOT = false; @@ -1666,7 +1678,7 @@ RMCharacter::RMCharacter() {  RMCharacter::~RMCharacter() {  	g_system->deleteMutex(csMove); -	CloseHandle(hEndOfPath); +	g_scheduler->closeEvent(hEndOfPath);  }  void RMCharacter::LinkToBoxes(RMGameBoxes *boxes) { diff --git a/engines/tony/loc.h b/engines/tony/loc.h index 3a312a0d3c..153ef7f18c 100644 --- a/engines/tony/loc.h +++ b/engines/tony/loc.h @@ -423,7 +423,7 @@ private:  	STATUS status;  	int curSpeed;  	bool bEndOfPath; -	HANDLE hEndOfPath; +	uint32 hEndOfPath;  	OSystem::MutexRef csMove;  	int curLocation;  	bool bRemoveFromOT; @@ -482,7 +482,7 @@ public:  	void SetPosition(RMPoint pt, int newloc=-1);  	// Aspetta la fine del movimento -	void WaitForEndMovement(void) { if (bMoving) WaitForSingleObject(hEndOfPath, INFINITE); } +	void WaitForEndMovement(CORO_PARAM);  	void SetFixedScroll(RMPoint fix) { m_fixedScroll = fix; }  	void SetSpeed(int speed) { curSpeed=speed; } diff --git a/engines/tony/mpal/mpal.cpp b/engines/tony/mpal/mpal.cpp index c5ded67c81..0cea50a3d3 100644 --- a/engines/tony/mpal/mpal.cpp +++ b/engines/tony/mpal/mpal.cpp @@ -961,7 +961,7 @@ void ActionThread(CORO_PARAM, const void *param) {  		if (item->Command[_ctx->k].type == 1) {  			// Custom function  			debugC(DEBUG_DETAILED, kTonyDebugActions, "Action Process %d Call=%s params=%d,%d,%d,%d", -				_vm->_scheduler.getCurrentPID(), lplpFunctionStrings[item->Command[_ctx->k].nCf].c_str(), +				g_scheduler->getCurrentPID(), lplpFunctionStrings[item->Command[_ctx->k].nCf].c_str(),  				item->Command[_ctx->k].arg1, item->Command[_ctx->k].arg2,  				item->Command[_ctx->k].arg3, item->Command[_ctx->k].arg4  			); @@ -976,7 +976,7 @@ void ActionThread(CORO_PARAM, const void *param) {  		} else if (item->Command[_ctx->k].type == 2) {  			// Variable assign  			debugC(DEBUG_DETAILED, kTonyDebugActions, "Action Process %d Variable=%s", -				_vm->_scheduler.getCurrentPID(), item->Command[_ctx->k].lpszVarName); +				g_scheduler->getCurrentPID(), item->Command[_ctx->k].lpszVarName);  			LockVar();  			varSetValue(item->Command[_ctx->k].lpszVarName, EvaluateExpression(item->Command[_ctx->k].expr)); @@ -991,7 +991,7 @@ void ActionThread(CORO_PARAM, const void *param) {  	GlobalFree(item); -	debugC(DEBUG_DETAILED, kTonyDebugActions, "Action Process %d ended", _vm->_scheduler.getCurrentPID()); +	debugC(DEBUG_DETAILED, kTonyDebugActions, "Action Process %d ended", g_scheduler->getCurrentPID());  	CORO_KILL_SELF(); @@ -1012,7 +1012,7 @@ void ShutUpActionThread(CORO_PARAM, const void *param) {  	CORO_BEGIN_CODE(_ctx); -	CORO_INVOKE_2(_vm->_scheduler.waitForSingleObject, pid, INFINITE); +	CORO_INVOKE_2(g_scheduler->waitForSingleObject, pid, INFINITE);  	bExecutingAction = false; @@ -1190,7 +1190,7 @@ void LocationPollThread(CORO_PARAM, const void *param) {  		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); +				CORO_INVOKE_3(g_scheduler->waitForSingleObject, _ctx->MyThreads[_ctx->i].hThread, 0, &_ctx->delayExpired);  				// if result ) == WAIT_OBJECT_0)  				if (!_ctx->delayExpired) @@ -1261,7 +1261,7 @@ void LocationPollThread(CORO_PARAM, const void *param) {  					_ctx->MyThreads[_ctx->i].nItem = _ctx->MyActions[_ctx->k].nItem;  					// !!! Nuova gestione dei thread -					if ((_ctx->MyThreads[_ctx->i].hThread = _vm->_scheduler.createProcess(ActionThread, &_ctx->newItem, sizeof(LPMPALITEM))) == 0) { +					if ((_ctx->MyThreads[_ctx->i].hThread = g_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); @@ -1295,14 +1295,14 @@ void LocationPollThread(CORO_PARAM, const void *param) {  	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); +			CORO_INVOKE_3(g_scheduler->waitForSingleObject, _ctx->MyThreads[_ctx->i].hThread, 5000, &_ctx->delayExpired);  /*  			//if (result != WAIT_OBJECT_0)  			if (_ctx->delayExpired)  				TerminateThread(_ctx->MyThreads[_ctx->i].hThread, 0);  */ -			_vm->_scheduler.killMatchingProcess(_ctx->MyThreads[_ctx->i].hThread); +			g_scheduler->killMatchingProcess(_ctx->MyThreads[_ctx->i].hThread);  		}  	// Set idle skip off @@ -1343,13 +1343,13 @@ void ShutUpDialogThread(CORO_PARAM, const void *param) {  	CORO_BEGIN_CODE(_ctx); -	CORO_INVOKE_2(_vm->_scheduler.waitForSingleObject, pid, INFINITE); +	CORO_INVOKE_2(g_scheduler->waitForSingleObject, pid, INFINITE);  	bExecutingDialog = false;  	nExecutingDialog = 0;  	nExecutingChoice = 0; -	_vm->_scheduler.setEvent(hAskChoice); +	g_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 */ -		_vm->_scheduler.resetEvent(hDoneChoice); -		_vm->_scheduler.setEvent(hAskChoice); -		CORO_INVOKE_2(_vm->_scheduler.waitForSingleObject, hDoneChoice, INFINITE); +		g_scheduler->resetEvent(hDoneChoice); +		g_scheduler->setEvent(hAskChoice); +		CORO_INVOKE_2(g_scheduler->waitForSingleObject, hDoneChoice, INFINITE);  		/* Ora che la scelta e' stata effettuata, possiamo eseguire _ctx->i gruppi  			associati con la scelta */ @@ -1644,19 +1644,19 @@ static uint32 DoDialog(uint32 nDlgOrd, uint32 nGroup) {  	// Enables the flag to indicate that there is' a running dialogue  	bExecutingDialog = true; -	_vm->_scheduler.resetEvent(hAskChoice); -	_vm->_scheduler.resetEvent(hDoneChoice); +	g_scheduler->resetEvent(hAskChoice); +	g_scheduler->resetEvent(hDoneChoice);  	// Create a thread that performs the dialogue group  	// Create the process -	if ((h = _vm->_scheduler.createProcess(GroupThread, &nGroup, sizeof(uint32))) == 0) +	if ((h = g_scheduler->createProcess(GroupThread, &nGroup, sizeof(uint32))) == 0)  		return 0;  	// Create a thread that waits until the end of the dialog process, and will restore the global variables -	if (_vm->_scheduler.createProcess(ShutUpDialogThread, &h, sizeof(uint32)) == 0) { +	if (g_scheduler->createProcess(ShutUpDialogThread, &h, sizeof(uint32)) == 0) {  		// Something went wrong, so kill the previously started dialog process -		_vm->_scheduler.killMatchingProcess(h); +		g_scheduler->killMatchingProcess(h);  		return 0;  	} @@ -1690,7 +1690,7 @@ bool DoSelection(uint32 i, uint32 dwData) {  		return false;  	nSelectedChoice = j; -	_vm->_scheduler.setEvent(hDoneChoice); +	g_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 = _vm->_scheduler.createEvent(true, false); -	hDoneChoice = _vm->_scheduler.createEvent(true, false); +	hAskChoice = g_scheduler->createEvent(true, false); +	hDoneChoice = g_scheduler->createEvent(true, false);  	return true;  } @@ -2031,9 +2031,9 @@ void mpalQueryInner(CORO_PARAM, uint16 wQueryType, uint32 *dwRet, va_list v) {  		/*  		 *  void mpalQuery(MPQ_DIALOG_WAITFORCHOICE);  		 */ -		CORO_INVOKE_2(_vm->_scheduler.waitForSingleObject, hAskChoice, INFINITE); +		CORO_INVOKE_2(g_scheduler->waitForSingleObject, hAskChoice, INFINITE); -		_vm->_scheduler.resetEvent(hAskChoice); +		g_scheduler->resetEvent(hAskChoice);  		if (bExecutingDialog)  			*dwRet = (uint32)nExecutingChoice; @@ -2217,7 +2217,7 @@ bool mpalStartIdlePoll(int nLoc) {  			hEndPollingLocations[i] = CreateEvent(NULL, true, false, NULL);  // !!! Nuova gestione dei thread -			if ((PollingThreads[i] = _vm->_scheduler.createProcess(LocationPollThread, &i, sizeof(uint32))) == 0) +			if ((PollingThreads[i] = g_scheduler->createProcess(LocationPollThread, &i, sizeof(uint32))) == 0)  //			 if ((hEndPollingLocations[i]=(void*)_beginthread(LocationPollThread, 10240,(void *)i))==(void*)-1)  				return false; @@ -2254,7 +2254,7 @@ void mpalEndIdlePoll(CORO_PARAM, int nLoc, bool *result) {  		if (nPollingLocations[_ctx->i] == (uint32)nLoc) {  			SetEvent(hEndPollingLocations[_ctx->i]); -			CORO_INVOKE_2(_vm->_scheduler.waitForSingleObject, PollingThreads[_ctx->i], INFINITE); +			CORO_INVOKE_2(g_scheduler->waitForSingleObject, PollingThreads[_ctx->i], INFINITE);  			CloseHandle(hEndPollingLocations[_ctx->i]);  			nPollingLocations[_ctx->i] = 0; diff --git a/engines/tony/sched.cpp b/engines/tony/sched.cpp index 199f5991ce..2671b01b7f 100644 --- a/engines/tony/sched.cpp +++ b/engines/tony/sched.cpp @@ -51,6 +51,8 @@ Scheduler::Scheduler() {  	active->pNext = NULL;  	g_scheduler = this;	// FIXME HACK + +	reset();  }  Scheduler::~Scheduler() { @@ -102,6 +104,7 @@ void Scheduler::reset() {  	while (pProc != NULL) {  		delete pProc->state;  		pProc->state = 0; +		pProc->waiting = false;  		pProc = pProc->pNext;  	} @@ -315,6 +318,9 @@ void Scheduler::waitForSingleObject(CORO_PARAM, int pid, uint32 duration, bool *  	CORO_BEGIN_CODE(_ctx); +	// Signal as waiting +	pCurrent->waiting = true; +  	_ctx->endTime = (duration == INFINITE) ? INFINITE : g_system->getMillis() + duration;  	if (expired)  		// Presume it will expire @@ -350,6 +356,9 @@ void Scheduler::waitForSingleObject(CORO_PARAM, int pid, uint32 duration, bool *  		CORO_SLEEP(1);  	} +	// Signal waiting is done +	pCurrent->waiting = false; +  	CORO_END_CODE;  } @@ -378,6 +387,9 @@ void Scheduler::waitForMultipleObjects(CORO_PARAM, int nCount, uint32 *pidList,  	CORO_BEGIN_CODE(_ctx); +	// Signal as waiting +	pCurrent->waiting = true; +  	_ctx->endTime = (duration == INFINITE) ? INFINITE : g_system->getMillis() + duration;  	if (expired)  		// Presume that delay will expire @@ -419,6 +431,9 @@ void Scheduler::waitForMultipleObjects(CORO_PARAM, int nCount, uint32 *pidList,  		CORO_SLEEP(1);  	} +	// Signal waiting is done +	pCurrent->waiting = false; +  	CORO_END_CODE;  } @@ -567,12 +582,12 @@ int Scheduler::getCurrentPID() const {   * @param pidMask	mask to apply to process identifiers before comparison   * @return The number of processes killed is returned.   */ -int Scheduler::killMatchingProcess(int pidKill, int pidMask) { +int Scheduler::killMatchingProcess(uint32 pidKill, int pidMask) {  	int numKilled = 0;  	PROCESS *pProc, *pPrev;	// process list pointers  	for (pProc = active->pNext, pPrev = active; pProc != NULL; pPrev = pProc, pProc = pProc->pNext) { -		if ((pProc->pid & pidMask) == pidKill) { +		if ((pProc->pid & (uint32)pidMask) == pidKill) {  			// found a matching process  			// dont kill the current process @@ -697,4 +712,56 @@ void Scheduler::resetEvent(uint32 pidEvent) {  		evt->signalled = false;  } +/** + * Temporarily sets a given event to true, and then runs all waiting processes, allowing any + * processes waiting on the event to be fired. It then immediately resets the event again. + * @param pidEvent						Event PID + * + * @remarks		Should not be run inside of another process + */ +void Scheduler::pulseEvent(uint32 pidEvent) { +	EVENT *evt = getEvent(pidEvent); +	if (!evt) +		return; +	 +	// Set the event as true +	evt->signalled = true; +	 +	// start dispatching active process list for any processes that are currently waiting +	PROCESS *pOriginal = pCurrent; +	PROCESS *pNext; +	PROCESS *pProc = active->pNext; +	while (pProc != NULL) { +		pNext = pProc->pNext; + +		// Only call processes that are currently waiting (either in waitForSingleObject or +		// waitForMultipleObjects). If one is found, execute it immediately +		if (pProc->waiting) { +			// Dispatch the process +			pCurrent = pProc; +			pProc->coroAddr(pProc->state, pProc->param); + +			if (!pProc->state || pProc->state->_sleep <= 0) { +				// Coroutine finished +				pCurrent = pCurrent->pPrevious; +				killProcess(pProc); +			} else { +				pProc->sleepTime = pProc->state->_sleep; +			} + +			// pCurrent may have been changed +			pNext = pCurrent->pNext; +			pCurrent = NULL; +		} + +		pProc = pNext; +	} + +	// Restore the original current process (if one was active) +	pCurrent = pOriginal; + +	// Reset the event back to non-signalled +	evt->signalled = false; +} +  } // End of namespace Tony diff --git a/engines/tony/sched.h b/engines/tony/sched.h index 80df1eb942..3997cb2c47 100644 --- a/engines/tony/sched.h +++ b/engines/tony/sched.h @@ -50,6 +50,7 @@ struct PROCESS {  	int sleepTime;		///< number of scheduler cycles to sleep  	uint32 pid;			///< process ID +	bool waiting;		///< process is currently in a waiting state  	char param[PARAM_SIZE];	///< process specific info  };  typedef PROCESS *PPROCESS; @@ -134,7 +135,7 @@ public:  	PROCESS *getCurrentProcess();  	int getCurrentPID() const; -	int killMatchingProcess(int pidKill, int pidMask = -1); +	int killMatchingProcess(uint32 pidKill, int pidMask = -1);  	void setResourceCallback(VFPTRPP pFunc); @@ -143,6 +144,7 @@ public:  	void closeEvent(uint32 pidEvent);  	void setEvent(uint32 pidEvent);  	void resetEvent(uint32 pidEvent); +	void pulseEvent(uint32 pidEvent);  };  extern Scheduler *g_scheduler;	// FIXME: Temporary global var, to be used until everything has been OOifyied diff --git a/engines/tony/tony.cpp b/engines/tony/tony.cpp index a4a478d40d..d0bce68c3b 100644 --- a/engines/tony/tony.cpp +++ b/engines/tony/tony.cpp @@ -36,7 +36,7 @@ namespace Tony {  TonyEngine *_vm;  TonyEngine::TonyEngine(OSystem *syst, const TonyGameDescription *gameDesc) : Engine(syst),  -		_gameDescription(gameDesc), _randomSource("tony") { +		_gameDescription(gameDesc), _randomSource("tony"), _scheduler() {  	_vm = this;  	DebugMan.addDebugChannel(kTonyDebugAnimations, "animations", "Animations debugging"); diff --git a/engines/tony/tonychar.cpp b/engines/tony/tonychar.cpp index 073ebf2be4..ad13d49d54 100644 --- a/engines/tony/tonychar.cpp +++ b/engines/tony/tonychar.cpp @@ -67,7 +67,7 @@ void RMTony::WaitEndOfAction(CORO_PARAM, const void *param) {  	CORO_BEGIN_CODE(_ctx); -	CORO_INVOKE_2(_vm->_scheduler.waitForSingleObject, pid, INFINITE); +	CORO_INVOKE_2(g_scheduler->waitForSingleObject, pid, INFINITE);  	m_bAction = false; @@ -240,26 +240,26 @@ void RMTony::ExecuteAction(int nAction, int nActionItem, int nParm) {  	if (hThread != INVALID_HANDLE_VALUE) {  		m_bAction = true;  		pid = (uint32)hThread; -		_vm->_scheduler.createProcess(WaitEndOfAction, &pid, sizeof(uint32)); +		g_scheduler->createProcess(WaitEndOfAction, &pid, sizeof(uint32));  		hActionThread = hThread;  	} else if (nAction != TA_GOTO) {  		if (nAction == TA_TALK) {  			hThread = mpalQueryDoAction(6, 1, 0);   			m_bAction = true;  			pid = (uint32)hThread; -			_vm->_scheduler.createProcess(WaitEndOfAction, &pid, sizeof(uint32)); +			g_scheduler->createProcess(WaitEndOfAction, &pid, sizeof(uint32));    			hActionThread = hThread;  		} else if (nAction == TA_PALESATI) {  			hThread = mpalQueryDoAction(7, 1, 0);  			m_bAction = true;   			pid = (uint32)hThread; -			_vm->_scheduler.createProcess(WaitEndOfAction, &pid, sizeof(uint32)); +			g_scheduler->createProcess(WaitEndOfAction, &pid, sizeof(uint32));    			hActionThread=hThread;  		} else {  			hThread = mpalQueryDoAction(5, 1, 0);   			m_bAction = true;  			pid = (uint32)hThread; -			_vm->_scheduler.createProcess(WaitEndOfAction, &pid, sizeof(uint32)); +			g_scheduler->createProcess(WaitEndOfAction, &pid, sizeof(uint32));  			hActionThread = hThread;  		}  	} @@ -1074,7 +1074,9 @@ bool RMTony::StartTalkCalculate(TALKTYPE nTalkType, int &headStartPat, int &body  			break;  		}  		break; -	}			 +	} + +	return true;  }  void RMTony::StartTalk(CORO_PARAM, TALKTYPE nTalkType) { | 
