From 10deebed553fc5d458a20756d963835aa1a86afe Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 6 May 2012 12:21:29 +1000 Subject: TONY: Beginnings of refactoring Tony engine's threads to use coroutines --- engines/tony/coroutine.cpp | 82 ++++++++ engines/tony/coroutine.h | 271 ++++++++++++++++++++++++ engines/tony/custom.cpp | 335 +++++++++++++++++------------- engines/tony/custom.h | 14 +- engines/tony/module.mk | 2 + engines/tony/mpal/mpal.cpp | 107 ++++++---- engines/tony/mpal/mpal.h | 3 +- engines/tony/sched.cpp | 498 +++++++++++++++++++++++++++++++++++++++++++++ engines/tony/sched.h | 128 ++++++++++++ engines/tony/tony.cpp | 15 +- engines/tony/tony.h | 6 +- engines/tony/tonychar.cpp | 2 +- 12 files changed, 1262 insertions(+), 201 deletions(-) create mode 100644 engines/tony/coroutine.cpp create mode 100644 engines/tony/coroutine.h create mode 100644 engines/tony/sched.cpp create mode 100644 engines/tony/sched.h (limited to 'engines') diff --git a/engines/tony/coroutine.cpp b/engines/tony/coroutine.cpp new file mode 100644 index 0000000000..504dc2a3fd --- /dev/null +++ b/engines/tony/coroutine.cpp @@ -0,0 +1,82 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "tony/coroutine.h" +#include "common/hashmap.h" +#include "common/hash-str.h" + +namespace Tony { + + +CoroContext nullContext = NULL; // FIXME: Avoid non-const global vars + + +#if COROUTINE_DEBUG +namespace { +static int s_coroCount = 0; + +typedef Common::HashMap CoroHashMap; +static CoroHashMap *s_coroFuncs = 0; + +static void changeCoroStats(const char *func, int change) { + if (!s_coroFuncs) + s_coroFuncs = new CoroHashMap(); + + (*s_coroFuncs)[func] += change; +} + +static void displayCoroStats() { + debug("%d active coros", s_coroCount); + + // Loop over s_coroFuncs and print info about active coros + if (!s_coroFuncs) + return; + for (CoroHashMap::const_iterator it = s_coroFuncs->begin(); + it != s_coroFuncs->end(); ++it) { + if (it->_value != 0) + debug(" %3d x %s", it->_value, it->_key.c_str()); + } +} + +} +#endif + +CoroBaseContext::CoroBaseContext(const char *func) + : _line(0), _sleep(0), _subctx(0) { +#if COROUTINE_DEBUG + _funcName = func; + changeCoroStats(_funcName, +1); + s_coroCount++; +#endif +} + +CoroBaseContext::~CoroBaseContext() { +#if COROUTINE_DEBUG + s_coroCount--; + changeCoroStats(_funcName, -1); + debug("Deleting coro in %s at %p (subctx %p)", + _funcName, (void *)this, (void *)_subctx); + displayCoroStats(); +#endif + delete _subctx; +} + +} // End of namespace Tony diff --git a/engines/tony/coroutine.h b/engines/tony/coroutine.h new file mode 100644 index 0000000000..24742a22f9 --- /dev/null +++ b/engines/tony/coroutine.h @@ -0,0 +1,271 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef TONY_COROUTINE_H +#define TONY_COROUTINE_H + +#include "common/scummsys.h" +#include "common/util.h" // for SCUMMVM_CURRENT_FUNCTION + +namespace Tony { + +/** + * @defgroup TonyCoroutines Coroutine support for Tony engine + * + * The following is loosely based on an article by Simon Tatham: + * . + * However, many improvements and tweaks have been made, in particular + * by taking advantage of C++ features not available in C. + */ +//@{ + + +// Enable this macro to enable some debugging support in the coroutine code. +//#define COROUTINE_DEBUG 1 + +/** + * The core of any coroutine context which captures the 'state' of a coroutine. + * Private use only. + */ +struct CoroBaseContext { + int _line; + int _sleep; + CoroBaseContext *_subctx; +#if COROUTINE_DEBUG + const char *_funcName; +#endif + CoroBaseContext(const char *func); + ~CoroBaseContext(); +}; + +typedef CoroBaseContext *CoroContext; + + +// FIXME: Document this! +extern CoroContext nullContext; + +/** + * Wrapper class which holds a pointer to a pointer to a CoroBaseContext. + * The interesting part is the destructor, which kills the context being held, + * but ONLY if the _sleep val of that context is zero. This way, a coroutine + * can just 'return' w/o having to worry about freeing the allocated context + * (in Simon Tatham's original code, one had to use a special macro to + * return from a coroutine). + */ +class CoroContextHolder { + CoroContext &_ctx; +public: + CoroContextHolder(CoroContext &ctx) : _ctx(ctx) { + assert(ctx); + assert(ctx->_sleep >= 0); + ctx->_sleep = 0; + } + ~CoroContextHolder() { + if (_ctx && _ctx->_sleep == 0) { + delete _ctx; + _ctx = 0; + } + } +}; + + +#define CORO_PARAM CoroContext &coroParam + + +/** + * Begin the declaration of a coroutine context. + * This allows declaring variables which are 'persistent' during the + * lifetime of the coroutine. An example use would be: + * + * CORO_BEGIN_CONTEXT; + * int var; + * char *foo; + * CORO_END_CONTEXT(_ctx); + * + * It is not possible to initialize variables here, due to the way this + * macro is implemented. Furthermore, to use the variables declared in + * the coroutine context, you have to access them via the context variable + * name that was specified as parameter to CORO_END_CONTEXT, e.g. + * _ctx->var = 0; + * + * @see CORO_END_CONTEXT + * + * @note We declare a variable 'DUMMY' to allow the user to specify an 'empty' + * context, and so compilers won't complain about ";" following the macro. + */ +#define CORO_BEGIN_CONTEXT \ + struct CoroContextTag : CoroBaseContext { \ + CoroContextTag() : CoroBaseContext(SCUMMVM_CURRENT_FUNCTION) {} \ + int DUMMY + +/** + * End the declaration of a coroutine context. + * @param x name of the coroutine context + * @see CORO_BEGIN_CONTEXT + */ +#define CORO_END_CONTEXT(x) } *x = (CoroContextTag *)coroParam + +/** + * Begin the code section of a coroutine. + * @param x name of the coroutine context + * @see CORO_BEGIN_CODE + */ +#define CORO_BEGIN_CODE(x) \ + if (&coroParam == &nullContext) assert(!nullContext);\ + if (!x) {coroParam = x = new CoroContextTag();}\ + CoroContextHolder tmpHolder(coroParam);\ + switch (coroParam->_line) { case 0:; + +/** + * End the code section of a coroutine. + * @see CORO_END_CODE + */ +#define CORO_END_CODE \ + if (&coroParam == &nullContext) { \ + delete nullContext; \ + nullContext = NULL; \ + } \ + } + +/** + * Sleep for the specified number of scheduler cycles. + */ +#define CORO_SLEEP(delay) do {\ + coroParam->_line = __LINE__;\ + coroParam->_sleep = delay;\ + assert(&coroParam != &nullContext);\ + return; case __LINE__:;\ + } while (0) + +#define CORO_GIVE_WAY do { g_scheduler->giveWay(); CORO_SLEEP(1); } while (0) +#define CORO_RESCHEDULE do { g_scheduler->reschedule(); CORO_SLEEP(1); } while (0) + +/** + * Stop the currently running coroutine and all calling coroutines. + * + * This sets _sleep to -1 rather than 0 so that the context doesn't get + * deleted by CoroContextHolder, since we want CORO_INVOKE_ARGS to + * propogate the _sleep value and return immediately (the scheduler will + * then delete the entire coroutine's state, including all subcontexts). + */ +#define CORO_KILL_SELF() \ + do { if (&coroParam != &nullContext) { coroParam->_sleep = -1; } return; } while (0) + + +/** + * This macro is to be used in conjunction with CORO_INVOKE_ARGS and + * similar macros for calling coroutines-enabled subroutines. + */ +#define CORO_SUBCTX coroParam->_subctx + +/** + * Invoke another coroutine. + * + * If the subcontext still exists after the coroutine is invoked, it has + * either yielded/slept or killed itself, and so we copy the _sleep value + * to our own context and return (execution will continue at the case + * statement below, where we loop and call the coroutine again). + * If the subcontext is null, the coroutine ended normally, and we can + * simply break out of the loop and continue execution. + * + * @param subCoro name of the coroutine-enabled function to invoke + * @param ARGS list of arguments to pass to subCoro + * + * @note ARGS must be surrounded by parentheses, and the first argument + * in this list must always be CORO_SUBCTX. For example, the + * regular function call + * myFunc(a, b); + * becomes the following: + * CORO_INVOKE_ARGS(myFunc, (CORO_SUBCTX, a, b)); + */ +#define CORO_INVOKE_ARGS(subCoro, ARGS) \ + do {\ + coroParam->_line = __LINE__;\ + coroParam->_subctx = 0;\ + do {\ + subCoro ARGS;\ + if (!coroParam->_subctx) break;\ + coroParam->_sleep = coroParam->_subctx->_sleep;\ + assert(&coroParam != &nullContext);\ + return; case __LINE__:;\ + } while (1);\ + } while (0) + +/** + * Invoke another coroutine. Similar to CORO_INVOKE_ARGS, + * but allows specifying a return value which is returned + * if invoked coroutine yields (thus causing the current + * coroutine to yield, too). + */ +#define CORO_INVOKE_ARGS_V(subCoro, RESULT, ARGS) \ + do {\ + coroParam->_line = __LINE__;\ + coroParam->_subctx = 0;\ + do {\ + subCoro ARGS;\ + if (!coroParam->_subctx) break;\ + coroParam->_sleep = coroParam->_subctx->_sleep;\ + assert(&coroParam != &nullContext);\ + return RESULT; case __LINE__:;\ + } while (1);\ + } while (0) + +/** + * Convenience wrapper for CORO_INVOKE_ARGS for invoking a coroutine + * with no parameters. + */ +#define CORO_INVOKE_0(subCoroutine) \ + CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX)) + +/** + * Convenience wrapper for CORO_INVOKE_ARGS for invoking a coroutine + * with one parameter. + */ +#define CORO_INVOKE_1(subCoroutine, a0) \ + CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX,a0)) + +/** + * Convenience wrapper for CORO_INVOKE_ARGS for invoking a coroutine + * with two parameters. + */ +#define CORO_INVOKE_2(subCoroutine, a0,a1) \ + CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX,a0,a1)) + +/** + * Convenience wrapper for CORO_INVOKE_ARGS for invoking a coroutine + * with three parameters. + */ +#define CORO_INVOKE_3(subCoroutine, a0,a1,a2) \ + CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX,a0,a1,a2)) + +/** + * Convenience wrapper for CORO_INVOKE_ARGS for invoking a coroutine + * with four parameters. + */ +#define CORO_INVOKE_4(subCoroutine, a0,a1,a2,a3) \ + CORO_INVOKE_ARGS(subCoroutine,(CORO_SUBCTX,a0,a1,a2,a3)) + +//@} + +} // End of namespace Tony + +#endif // TONY_COROUTINE_H diff --git a/engines/tony/custom.cpp b/engines/tony/custom.cpp index 3400235563..1d28fa9ece 100644 --- a/engines/tony/custom.cpp +++ b/engines/tony/custom.cpp @@ -297,38 +297,38 @@ void CharsLoadAll(Common::InSaveFile *f) { } } -DECLARE_CUSTOM_FUNCTION(FaceToMe)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(FaceToMe)(CORO_PARAM, uint32, uint32, uint32, uint32) { Tony->SetPattern(Tony->PAT_STANDDOWN); } -DECLARE_CUSTOM_FUNCTION(BackToMe)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(BackToMe)(CORO_PARAM, uint32, uint32, uint32, uint32) { Tony->SetPattern(Tony->PAT_STANDUP); } -DECLARE_CUSTOM_FUNCTION(LeftToMe)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(LeftToMe)(CORO_PARAM, uint32, uint32, uint32, uint32) { Tony->SetPattern(Tony->PAT_STANDLEFT); } -DECLARE_CUSTOM_FUNCTION(RightToMe)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(RightToMe)(CORO_PARAM, uint32, uint32, uint32, uint32) { Tony->SetPattern(Tony->PAT_STANDRIGHT); } -DECLARE_CUSTOM_FUNCTION(TonySetPalesati)(uint32 bStatus, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonySetPalesati)(CORO_PARAM, uint32 bStatus, uint32, uint32, uint32) { SetPalesati(bStatus); } -DECLARE_CUSTOM_FUNCTION(MySleep)(uint32 dwTime, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(MySleep)(CORO_PARAM, uint32 dwTime, uint32, uint32, uint32) { if (bSkipIdle) return; Sleep(dwTime); } -DECLARE_CUSTOM_FUNCTION(SetAlwaysDisplay)(uint32 val, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(SetAlwaysDisplay)(CORO_PARAM, uint32 val, uint32, uint32, uint32) { bAlwaysDisplay = (val != 0); } -DECLARE_CUSTOM_FUNCTION(SetPointer)(uint32 dwPointer, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(SetPointer)(CORO_PARAM, uint32 dwPointer, uint32, uint32, uint32) { switch (dwPointer) { case 1: Pointer->SetSpecialPointer(Pointer->PTR_FRECCIASU); @@ -369,7 +369,7 @@ VoiceHeader *SearchVoiceHeader(uint32 codehi, uint32 codelo) { } -DECLARE_CUSTOM_FUNCTION(SendTonyMessage)(uint32 dwMessage, uint32 nX, uint32 nY, uint32) { +DECLARE_CUSTOM_FUNCTION(SendTonyMessage)(CORO_PARAM, uint32 dwMessage, uint32 nX, uint32 nY, uint32) { RMMessage msg(dwMessage); int i; int curOffset = 0; @@ -476,12 +476,12 @@ DECLARE_CUSTOM_FUNCTION(SendTonyMessage)(uint32 dwMessage, uint32 nX, uint32 nY, Tony->EndTalk(); } -DECLARE_CUSTOM_FUNCTION(ChangeBoxStatus)(uint32 nLoc, uint32 nBox, uint32 nStatus, uint32) { +DECLARE_CUSTOM_FUNCTION(ChangeBoxStatus)(CORO_PARAM, uint32 nLoc, uint32 nBox, uint32 nStatus, uint32) { Boxes->ChangeBoxStatus(nLoc,nBox,nStatus); } -DECLARE_CUSTOM_FUNCTION(CustLoadLocation)(uint32 nLoc, uint32 tX, uint32 tY, uint32 bUseStartPos) { +DECLARE_CUSTOM_FUNCTION(CustLoadLocation)(CORO_PARAM, uint32 nLoc, uint32 tX, uint32 tY, uint32 bUseStartPos) { HANDLE h; Freeze(); @@ -504,7 +504,7 @@ DECLARE_CUSTOM_FUNCTION(CustLoadLocation)(uint32 nLoc, uint32 tX, uint32 tY, uin RMPoint SFM_pt; int SFM_nLoc; -DECLARE_CUSTOM_FUNCTION(SendFullscreenMsgStart)(uint32 nMsg, uint32 nFont, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(SendFullscreenMsgStart)(CORO_PARAM, uint32 nMsg, uint32 nFont, uint32, uint32) { RMMessage msg(nMsg); RMGfxClearTask clear; int i; @@ -554,14 +554,14 @@ DECLARE_CUSTOM_FUNCTION(SendFullscreenMsgStart)(uint32 nMsg, uint32 nFont, uint3 } } -DECLARE_CUSTOM_FUNCTION(ClearScreen)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(ClearScreen)(CORO_PARAM, uint32, uint32, uint32, uint32) { RMGfxClearTask clear; LinkGraphicTask(&clear); WaitFrame(); } -DECLARE_CUSTOM_FUNCTION(SendFullscreenMsgEnd)(uint32 bNotEnableTony, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(SendFullscreenMsgEnd)(CORO_PARAM, uint32 bNotEnableTony, uint32, uint32, uint32) { Freeze(); LoadLocation(SFM_nLoc,RMPoint(SFM_pt.x,SFM_pt.y),RMPoint(-1,-1)); if (!bNotEnableTony) @@ -573,18 +573,25 @@ DECLARE_CUSTOM_FUNCTION(SendFullscreenMsgEnd)(uint32 bNotEnableTony, uint32, uin } -DECLARE_CUSTOM_FUNCTION(SendFullscreenMessage)(uint32 nMsg, uint32 nFont, uint32, uint32) { - SendFullscreenMsgStart(nMsg,nFont,0,0); - SendFullscreenMsgEnd(0, 0, 0, 0); +DECLARE_CUSTOM_FUNCTION(SendFullscreenMessage)(CORO_PARAM, uint32 nMsg, uint32 nFont, uint32, uint32) { + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + + CORO_INVOKE_4(SendFullscreenMsgStart, nMsg, nFont, 0, 0); + CORO_INVOKE_4(SendFullscreenMsgEnd, 0, 0, 0, 0); + + CORO_END_CODE; } bool bNoOcchioDiBue = false; -DECLARE_CUSTOM_FUNCTION(NoOcchioDiBue)(uint32, uint32, uint32, uint32) { - bNoOcchioDiBue = true; +DECLARE_CUSTOM_FUNCTION(NoOcchioDiBue)(CORO_PARAM, uint32, uint32, uint32, uint32) { + bNoOcchioDiBue = true; } -DECLARE_CUSTOM_FUNCTION(CloseLocation)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(CloseLocation)(CORO_PARAM, uint32, uint32, uint32, uint32) { if (!bNoOcchioDiBue) { InitWipe(1); WaitWipeEnd(); @@ -598,7 +605,7 @@ DECLARE_CUSTOM_FUNCTION(CloseLocation)(uint32, uint32, uint32, uint32) { } -DECLARE_CUSTOM_FUNCTION(ChangeLocation)(uint32 nLoc, uint32 tX, uint32 tY, uint32 bUseStartPos) { +DECLARE_CUSTOM_FUNCTION(ChangeLocation)(CORO_PARAM, uint32 nLoc, uint32 tX, uint32 tY, uint32 bUseStartPos) { HANDLE h; if (!bNoOcchioDiBue) { @@ -647,40 +654,48 @@ DECLARE_CUSTOM_FUNCTION(ChangeLocation)(uint32 nLoc, uint32 tX, uint32 tY, uint3 } -DECLARE_CUSTOM_FUNCTION(SetLocStartPosition)(uint32 nLoc, uint32 lX, uint32 lY, uint32) { +DECLARE_CUSTOM_FUNCTION(SetLocStartPosition)(CORO_PARAM, uint32 nLoc, uint32 lX, uint32 lY, uint32) { StartLocPos[nLoc].Set(lX,lY); } -DECLARE_CUSTOM_FUNCTION(SaveTonyPosition)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(SaveTonyPosition)(CORO_PARAM, uint32, uint32, uint32, uint32) { saveTonyPos = Tony->Position(); saveTonyLoc = Loc->TEMPGetNumLoc(); } -DECLARE_CUSTOM_FUNCTION(RestoreTonyPosition)(uint32, uint32, uint32, uint32) { - ChangeLocation(saveTonyLoc, saveTonyPos.x, saveTonyPos.y, 0); +DECLARE_CUSTOM_FUNCTION(RestoreTonyPosition)(CORO_PARAM, uint32, uint32, uint32, uint32) { + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + + CORO_INVOKE_4(ChangeLocation, saveTonyLoc, saveTonyPos.x, saveTonyPos.y, 0); + MCharResetCodes(); + + CORO_END_CODE; } -DECLARE_CUSTOM_FUNCTION(DisableInput)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(DisableInput)(CORO_PARAM, uint32, uint32, uint32, uint32) { MainDisableInput(); } -DECLARE_CUSTOM_FUNCTION(EnableInput)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(EnableInput)(CORO_PARAM, uint32, uint32, uint32, uint32) { MainEnableInput(); } -DECLARE_CUSTOM_FUNCTION(StopTony)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(StopTony)(CORO_PARAM, uint32, uint32, uint32, uint32) { Tony->StopNoAction(); } -DECLARE_CUSTOM_FUNCTION(CustEnableGUI)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(CustEnableGUI)(CORO_PARAM, uint32, uint32, uint32, uint32) { EnableGUI(); } -DECLARE_CUSTOM_FUNCTION(CustDisableGUI)(uint32, uint32, uint32, uint32) +DECLARE_CUSTOM_FUNCTION(CustDisableGUI)(CORO_PARAM, uint32, uint32, uint32, uint32) { DisableGUI(); } @@ -731,31 +746,31 @@ void TonyGenericPut2(uint32 nDirection) { } -DECLARE_CUSTOM_FUNCTION(TonyTakeUp1)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyTakeUp1)(CORO_PARAM, uint32, uint32, uint32, uint32) { TonyGenericTake1(0); } -DECLARE_CUSTOM_FUNCTION(TonyTakeMid1)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyTakeMid1)(CORO_PARAM, uint32, uint32, uint32, uint32) { TonyGenericTake1(1); } -DECLARE_CUSTOM_FUNCTION(TonyTakeDown1)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyTakeDown1)(CORO_PARAM, uint32, uint32, uint32, uint32) { TonyGenericTake1(2); } -DECLARE_CUSTOM_FUNCTION(TonyTakeUp2)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyTakeUp2)(CORO_PARAM, uint32, uint32, uint32, uint32) { TonyGenericTake2(0); } -DECLARE_CUSTOM_FUNCTION(TonyTakeMid2)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyTakeMid2)(CORO_PARAM, uint32, uint32, uint32, uint32) { TonyGenericTake2(1); } -DECLARE_CUSTOM_FUNCTION(TonyTakeDown2)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyTakeDown2)(CORO_PARAM, uint32, uint32, uint32, uint32) { TonyGenericTake2(2); } @@ -765,42 +780,42 @@ DECLARE_CUSTOM_FUNCTION(TonyTakeDown2)(uint32, uint32, uint32, uint32) { -DECLARE_CUSTOM_FUNCTION(TonyPutUp1)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyPutUp1)(CORO_PARAM, uint32, uint32, uint32, uint32) { TonyGenericPut1(0); } -DECLARE_CUSTOM_FUNCTION(TonyPutMid1)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyPutMid1)(CORO_PARAM, uint32, uint32, uint32, uint32) { TonyGenericPut1(1); } -DECLARE_CUSTOM_FUNCTION(TonyPutDown1)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyPutDown1)(CORO_PARAM, uint32, uint32, uint32, uint32) { TonyGenericPut1(2); } -DECLARE_CUSTOM_FUNCTION(TonyPutUp2)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyPutUp2)(CORO_PARAM, uint32, uint32, uint32, uint32) { TonyGenericPut2(0); } -DECLARE_CUSTOM_FUNCTION(TonyPutMid2)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyPutMid2)(CORO_PARAM, uint32, uint32, uint32, uint32) { TonyGenericPut2(1); } -DECLARE_CUSTOM_FUNCTION(TonyPutDown2)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyPutDown2)(CORO_PARAM, uint32, uint32, uint32, uint32) { TonyGenericPut2(2); } -DECLARE_CUSTOM_FUNCTION(TonyPerTerra)(uint32 dwParte, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyPerTerra)(CORO_PARAM, uint32 dwParte, uint32, uint32, uint32) { if (dwParte== 0) Tony->SetPattern(Tony->PAT_PERTERRALEFT); else Tony->SetPattern(Tony->PAT_PERTERRARIGHT); } -DECLARE_CUSTOM_FUNCTION(TonySiRialza)(uint32 dwParte, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonySiRialza)(CORO_PARAM, uint32 dwParte, uint32, uint32, uint32) { if (dwParte== 0) Tony->SetPattern(Tony->PAT_SIRIALZALEFT); else @@ -810,11 +825,11 @@ DECLARE_CUSTOM_FUNCTION(TonySiRialza)(uint32 dwParte, uint32, uint32, uint32) { Tony->WaitForEndPattern(); } -DECLARE_CUSTOM_FUNCTION(TonyPastorella)(uint32 bIsPast, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyPastorella)(CORO_PARAM, uint32 bIsPast, uint32, uint32, uint32) { Tony->SetPastorella(bIsPast); } -DECLARE_CUSTOM_FUNCTION(TonyFischietto)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyFischietto)(CORO_PARAM, uint32, uint32, uint32, uint32) { Tony->SetPattern(Tony->PAT_FISCHIETTORIGHT); if (!bSkipIdle) Tony->WaitForEndPattern(); @@ -827,182 +842,182 @@ void TonySetNumTexts(uint32 dwText) { bTonyInTexts = false; } -DECLARE_CUSTOM_FUNCTION(TonyRide)(uint32 dwText, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyRide)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) { TonySetNumTexts(dwText); nTonyNextTalkType = Tony->TALK_RIDE; } -DECLARE_CUSTOM_FUNCTION(TonyRidacchia)(uint32 dwText, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyRidacchia)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) { TonySetNumTexts(dwText); nTonyNextTalkType = Tony->TALK_RIDE2; } -DECLARE_CUSTOM_FUNCTION(TonyFianchi)(uint32 dwText, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyFianchi)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) { TonySetNumTexts(dwText); nTonyNextTalkType = Tony->TALK_FIANCHI; } -DECLARE_CUSTOM_FUNCTION(TonyCanta)(uint32 dwText, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyCanta)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) { TonySetNumTexts(dwText); nTonyNextTalkType = Tony->TALK_CANTA; } -DECLARE_CUSTOM_FUNCTION(TonySiIndica)(uint32 dwText, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonySiIndica)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) { TonySetNumTexts(dwText); nTonyNextTalkType = Tony->TALK_SIINDICA; } -DECLARE_CUSTOM_FUNCTION(TonySpaventatoConMani)(uint32 dwText, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonySpaventatoConMani)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) { TonySetNumTexts(dwText); nTonyNextTalkType = Tony->TALK_SPAVENTATO; } -DECLARE_CUSTOM_FUNCTION(TonySpaventatoSenzaMani)(uint32 dwText, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonySpaventatoSenzaMani)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) { TonySetNumTexts(dwText); nTonyNextTalkType = Tony->TALK_SPAVENTATO2; } -DECLARE_CUSTOM_FUNCTION(TonyConMartello)(uint32 dwText, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConMartello)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) { TonySetNumTexts(dwText); nTonyNextTalkType = Tony->TALK_CONMARTELLO; Tony->SetPattern(Tony->PAT_CONMARTELLO); } -DECLARE_CUSTOM_FUNCTION(TonyConBicchiere)(uint32 dwText, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConBicchiere)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) { TonySetNumTexts(dwText); nTonyNextTalkType = Tony->TALK_CONBICCHIERE; Tony->SetPattern(Tony->PAT_CONBICCHIERE); } -DECLARE_CUSTOM_FUNCTION(TonyConVerme)(uint32 dwText, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConVerme)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) { TonySetNumTexts(dwText); nTonyNextTalkType = Tony->TALK_CONVERME; Tony->SetPattern(Tony->PAT_CONVERME); } -DECLARE_CUSTOM_FUNCTION(TonyConCorda)(uint32 dwText, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConCorda)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) { TonySetNumTexts(dwText); nTonyNextTalkType = Tony->TALK_CONCORDA; Tony->SetPattern(Tony->PAT_CONCORDA); } -DECLARE_CUSTOM_FUNCTION(TonyConSegretaria)(uint32 dwText, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConSegretaria)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) { TonySetNumTexts(dwText); nTonyNextTalkType = Tony->TALK_CONSEGRETARIA; Tony->SetPattern(Tony->PAT_CONSEGRETARIA); } -DECLARE_CUSTOM_FUNCTION(TonyConConiglioANIM)(uint32 dwText, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConConiglioANIM)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) { TonySetNumTexts(dwText); nTonyNextTalkType = Tony->TALK_CONCONIGLIO; } -DECLARE_CUSTOM_FUNCTION(TonyConRicettaANIM)(uint32 dwText, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConRicettaANIM)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) { TonySetNumTexts(dwText); nTonyNextTalkType = Tony->TALK_CONRICETTA; } -DECLARE_CUSTOM_FUNCTION(TonyConCarteANIM)(uint32 dwText, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConCarteANIM)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) { TonySetNumTexts(dwText); nTonyNextTalkType = Tony->TALK_CONCARTE; } -DECLARE_CUSTOM_FUNCTION(TonyConPupazzoANIM)(uint32 dwText, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConPupazzoANIM)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) { TonySetNumTexts(dwText); nTonyNextTalkType = Tony->TALK_CONPUPAZZO; } -DECLARE_CUSTOM_FUNCTION(TonyConPupazzoStart)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConPupazzoStart)(CORO_PARAM, uint32, uint32, uint32, uint32) { nTonyNextTalkType = Tony->TALK_CONPUPAZZOSTATIC; bStaticTalk = true; Tony->StartStatic(Tony->TALK_CONPUPAZZOSTATIC); } -DECLARE_CUSTOM_FUNCTION(TonyConPupazzoEnd)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConPupazzoEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) { Tony->EndStatic(Tony->TALK_CONPUPAZZOSTATIC); bStaticTalk = false; nTonyNextTalkType = Tony->TALK_NORMAL; } -DECLARE_CUSTOM_FUNCTION(TonyConConiglioStart)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConConiglioStart)(CORO_PARAM, uint32, uint32, uint32, uint32) { nTonyNextTalkType = Tony->TALK_CONCONIGLIOSTATIC; bStaticTalk = true; Tony->StartStatic(Tony->TALK_CONCONIGLIOSTATIC); } -DECLARE_CUSTOM_FUNCTION(TonyConConiglioEnd)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConConiglioEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) { Tony->EndStatic(Tony->TALK_CONCONIGLIOSTATIC); bStaticTalk = false; nTonyNextTalkType = Tony->TALK_NORMAL; } -DECLARE_CUSTOM_FUNCTION(TonyConRicettaStart)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConRicettaStart)(CORO_PARAM, uint32, uint32, uint32, uint32) { nTonyNextTalkType = Tony->TALK_CONRICETTASTATIC; bStaticTalk = true; Tony->StartStatic(Tony->TALK_CONRICETTASTATIC); } -DECLARE_CUSTOM_FUNCTION(TonyConRicettaEnd)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConRicettaEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) { Tony->EndStatic(Tony->TALK_CONRICETTASTATIC); bStaticTalk = false; nTonyNextTalkType = Tony->TALK_NORMAL; } -DECLARE_CUSTOM_FUNCTION(TonyConCarteStart)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConCarteStart)(CORO_PARAM, uint32, uint32, uint32, uint32) { nTonyNextTalkType = Tony->TALK_CONCARTESTATIC; bStaticTalk = true; Tony->StartStatic(Tony->TALK_CONCARTESTATIC); } -DECLARE_CUSTOM_FUNCTION(TonyConCarteEnd)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConCarteEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) { Tony->EndStatic(Tony->TALK_CONCARTESTATIC); bStaticTalk = false; nTonyNextTalkType = Tony->TALK_NORMAL; } -DECLARE_CUSTOM_FUNCTION(TonyConTaccuinoStart)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConTaccuinoStart)(CORO_PARAM, uint32, uint32, uint32, uint32) { nTonyNextTalkType = Tony->TALK_CONTACCUINOSTATIC; bStaticTalk = true; Tony->StartStatic(Tony->TALK_CONTACCUINOSTATIC); } -DECLARE_CUSTOM_FUNCTION(TonyConTaccuinoEnd)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConTaccuinoEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) { Tony->EndStatic(Tony->TALK_CONTACCUINOSTATIC); bStaticTalk = false; nTonyNextTalkType = Tony->TALK_NORMAL; } -DECLARE_CUSTOM_FUNCTION(TonyConMegafonoStart)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConMegafonoStart)(CORO_PARAM, uint32, uint32, uint32, uint32) { nTonyNextTalkType = Tony->TALK_CONMEGAFONOSTATIC; bStaticTalk = true; Tony->StartStatic(Tony->TALK_CONMEGAFONOSTATIC); } -DECLARE_CUSTOM_FUNCTION(TonyConMegafonoEnd)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConMegafonoEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) { Tony->EndStatic(Tony->TALK_CONMEGAFONOSTATIC); bStaticTalk = false; nTonyNextTalkType = Tony->TALK_NORMAL; } -DECLARE_CUSTOM_FUNCTION(TonyConBarbaStart)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConBarbaStart)(CORO_PARAM, uint32, uint32, uint32, uint32) { nTonyNextTalkType = Tony->TALK_CONBARBASTATIC; bStaticTalk = true; Tony->StartStatic(Tony->TALK_CONBARBASTATIC); } -DECLARE_CUSTOM_FUNCTION(TonyConBarbaEnd)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyConBarbaEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) { Tony->EndStatic(Tony->TALK_CONBARBASTATIC); bStaticTalk = false; nTonyNextTalkType = Tony->TALK_NORMAL; } -DECLARE_CUSTOM_FUNCTION(TonySpaventatoStart)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonySpaventatoStart)(CORO_PARAM, uint32, uint32, uint32, uint32) { nTonyNextTalkType = Tony->TALK_SPAVENTATOSTATIC; bStaticTalk = true; Tony->StartStatic(Tony->TALK_SPAVENTATOSTATIC); } -DECLARE_CUSTOM_FUNCTION(TonySpaventatoEnd)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonySpaventatoEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) { Tony->EndStatic(Tony->TALK_SPAVENTATOSTATIC); bStaticTalk = false; nTonyNextTalkType = Tony->TALK_NORMAL; @@ -1010,29 +1025,43 @@ DECLARE_CUSTOM_FUNCTION(TonySpaventatoEnd)(uint32, uint32, uint32, uint32) { -DECLARE_CUSTOM_FUNCTION(TonySchifato)(uint32 dwText, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonySchifato)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) { TonySetNumTexts(dwText); nTonyNextTalkType = Tony->TALK_SCHIFATO; } -DECLARE_CUSTOM_FUNCTION(TonySniffaLeft)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonySniffaLeft)(CORO_PARAM, uint32, uint32, uint32, uint32) { + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + Tony->SetPattern(Tony->PAT_SNIFFA_LEFT); Tony->WaitForEndPattern(); - LeftToMe(0, 0, 0, 0); + CORO_INVOKE_4(LeftToMe, 0, 0, 0, 0); + + CORO_END_CODE; } -DECLARE_CUSTOM_FUNCTION(TonySniffaRight)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonySniffaRight)(CORO_PARAM, uint32, uint32, uint32, uint32) { + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + Tony->SetPattern(Tony->PAT_SNIFFA_RIGHT); Tony->WaitForEndPattern(); - RightToMe(0, 0, 0, 0); + CORO_INVOKE_4(RightToMe, 0, 0, 0, 0); + + CORO_END_CODE; } -DECLARE_CUSTOM_FUNCTION(TonyNaah)(uint32 dwText, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyNaah)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) { TonySetNumTexts(dwText); nTonyNextTalkType = Tony->TALK_NAAH; } -DECLARE_CUSTOM_FUNCTION(TonyMacbeth)(uint32 nPos, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TonyMacbeth)(CORO_PARAM, uint32 nPos, uint32, uint32, uint32) { switch (nPos) { case 1: nTonyNextTalkType = Tony->TALK_MACBETH1; @@ -1065,15 +1094,15 @@ DECLARE_CUSTOM_FUNCTION(TonyMacbeth)(uint32 nPos, uint32, uint32, uint32) { } -DECLARE_CUSTOM_FUNCTION(EnableTony)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(EnableTony)(CORO_PARAM, uint32, uint32, uint32, uint32) { Tony->Show(); } -DECLARE_CUSTOM_FUNCTION(DisableTony)(uint32 bShowOmbra, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(DisableTony)(CORO_PARAM, uint32 bShowOmbra, uint32, uint32, uint32) { Tony->Hide(bShowOmbra); } -DECLARE_CUSTOM_FUNCTION(WaitForPatternEnd)(uint32 nItem, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(WaitForPatternEnd)(CORO_PARAM, uint32 nItem, uint32, uint32, uint32) { RMItem *item = Loc->GetItemFromCode(nItem); if (!bSkipIdle && item != NULL) @@ -1081,22 +1110,22 @@ DECLARE_CUSTOM_FUNCTION(WaitForPatternEnd)(uint32 nItem, uint32, uint32, uint32) } -DECLARE_CUSTOM_FUNCTION(SetTonyPosition)(uint32 nX, uint32 nY, uint32 nLoc, uint32) { +DECLARE_CUSTOM_FUNCTION(SetTonyPosition)(CORO_PARAM, uint32 nX, uint32 nY, uint32 nLoc, uint32) { Tony->SetPosition(RMPoint(nX, nY), nLoc); } -DECLARE_CUSTOM_FUNCTION(MoveTonyAndWait)(uint32 nX, uint32 nY, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(MoveTonyAndWait)(CORO_PARAM, uint32 nX, uint32 nY, uint32, uint32) { Tony->Move(RMPoint(nX, nY)); if (!bSkipIdle) Tony->WaitForEndMovement(); } -DECLARE_CUSTOM_FUNCTION(MoveTony)(uint32 nX, uint32 nY, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(MoveTony)(CORO_PARAM, uint32 nX, uint32 nY, uint32, uint32) { Tony->Move(RMPoint(nX, nY)); } -DECLARE_CUSTOM_FUNCTION(ScrollLocation)(uint32 nX, uint32 nY, uint32 sX, uint32 sY) { +DECLARE_CUSTOM_FUNCTION(ScrollLocation)(CORO_PARAM, uint32 nX, uint32 nY, uint32 sX, uint32 sY) { int lx, ly; RMPoint pt; @@ -1133,7 +1162,7 @@ DECLARE_CUSTOM_FUNCTION(ScrollLocation)(uint32 nX, uint32 nY, uint32 sX, uint32 } } -DECLARE_CUSTOM_FUNCTION(SyncScrollLocation)(uint32 nX, uint32 nY, uint32 sX, uint32 sY) { +DECLARE_CUSTOM_FUNCTION(SyncScrollLocation)(CORO_PARAM, uint32 nX, uint32 nY, uint32 sX, uint32 sY) { int lx, ly; RMPoint pt, startpt; uint32 dwStartTime, dwCurTime, dwTotalTime; @@ -1231,7 +1260,7 @@ DECLARE_CUSTOM_FUNCTION(SyncScrollLocation)(uint32 nX, uint32 nY, uint32 sX, uin } -DECLARE_CUSTOM_FUNCTION(ChangeHotspot)(uint32 dwCode, uint32 nX, uint32 nY, uint32) { +DECLARE_CUSTOM_FUNCTION(ChangeHotspot)(CORO_PARAM, uint32 dwCode, uint32 nX, uint32 nY, uint32) { int i; for (i = 0; i < curChangedHotspot; i++) @@ -1252,15 +1281,15 @@ DECLARE_CUSTOM_FUNCTION(ChangeHotspot)(uint32 dwCode, uint32 nX, uint32 nY, uint } -DECLARE_CUSTOM_FUNCTION(AutoSave)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(AutoSave)(CORO_PARAM, uint32, uint32, uint32, uint32) { _vm->AutoSave(); } -DECLARE_CUSTOM_FUNCTION(Abort)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(Abort)(CORO_PARAM, uint32, uint32, uint32, uint32) { _vm->Abort(); } -DECLARE_CUSTOM_FUNCTION(TremaSchermo)(uint32 nScosse, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TremaSchermo)(CORO_PARAM, uint32 nScosse, uint32, uint32, uint32) { uint32 i; uint32 curTime = _vm->GetTime(); int dirx,diry; @@ -1296,7 +1325,7 @@ DECLARE_CUSTOM_FUNCTION(TremaSchermo)(uint32 nScosse, uint32, uint32, uint32) { * Personaggi */ -DECLARE_CUSTOM_FUNCTION(CharSetCode)(uint32 nChar, uint32 nCode, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(CharSetCode)(CORO_PARAM, uint32 nChar, uint32 nCode, uint32, uint32) { assert(nChar < 16); Character[nChar].code = nCode; Character[nChar].item = Loc->GetItemFromCode(nCode); @@ -1311,26 +1340,26 @@ DECLARE_CUSTOM_FUNCTION(CharSetCode)(uint32 nChar, uint32 nCode, uint32, uint32) IsMChar[nChar] = false; } -DECLARE_CUSTOM_FUNCTION(CharSetColor)(uint32 nChar, uint32 r, uint32 g, uint32 b) { +DECLARE_CUSTOM_FUNCTION(CharSetColor)(CORO_PARAM, uint32 nChar, uint32 r, uint32 g, uint32 b) { assert(nChar<16); Character[nChar].r = r; Character[nChar].g = g; Character[nChar].b = b; } -DECLARE_CUSTOM_FUNCTION(CharSetTalkPattern)(uint32 nChar, uint32 tp, uint32 sp, uint32) { +DECLARE_CUSTOM_FUNCTION(CharSetTalkPattern)(CORO_PARAM, uint32 nChar, uint32 tp, uint32 sp, uint32) { assert(nChar<16); Character[nChar].talkpattern = tp; Character[nChar].standpattern = sp; } -DECLARE_CUSTOM_FUNCTION(CharSetStartEndTalkPattern)(uint32 nChar, uint32 sp, uint32 ep, uint32) { +DECLARE_CUSTOM_FUNCTION(CharSetStartEndTalkPattern)(CORO_PARAM, uint32 nChar, uint32 sp, uint32 ep, uint32) { assert(nChar<16); Character[nChar].starttalkpattern=sp; Character[nChar].endtalkpattern=ep; } -DECLARE_CUSTOM_FUNCTION(CharSendMessage)(uint32 nChar, uint32 dwMessage, uint32 bIsBack, uint32) { +DECLARE_CUSTOM_FUNCTION(CharSendMessage)(CORO_PARAM, uint32 nChar, uint32 dwMessage, uint32 bIsBack, uint32) { RMMessage msg(dwMessage); int i; RMPoint pt; @@ -1433,15 +1462,15 @@ DECLARE_CUSTOM_FUNCTION(CharSendMessage)(uint32 nChar, uint32 dwMessage, uint32 Unfreeze(); } -DECLARE_CUSTOM_FUNCTION(AddInventory)(uint32 dwCode, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(AddInventory)(CORO_PARAM, uint32 dwCode, uint32, uint32, uint32) { Inventory->AddItem(dwCode); } -DECLARE_CUSTOM_FUNCTION(RemoveInventory)(uint32 dwCode, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(RemoveInventory)(CORO_PARAM, uint32 dwCode, uint32, uint32, uint32) { Inventory->RemoveItem(dwCode); } -DECLARE_CUSTOM_FUNCTION(ChangeInventoryStatus)(uint32 dwCode, uint32 dwStatus, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(ChangeInventoryStatus)(CORO_PARAM, uint32 dwCode, uint32 dwStatus, uint32, uint32) { Inventory->ChangeItemStatus(dwCode,dwStatus); } @@ -1452,7 +1481,7 @@ DECLARE_CUSTOM_FUNCTION(ChangeInventoryStatus)(uint32 dwCode, uint32 dwStatus, u * Mastri Personaggi */ -DECLARE_CUSTOM_FUNCTION(MCharSetCode)(uint32 nChar, uint32 nCode, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(MCharSetCode)(CORO_PARAM, uint32 nChar, uint32 nCode, uint32, uint32) { assert(nChar < 10); MCharacter[nChar].code=nCode; if (nCode== 0) @@ -1474,19 +1503,19 @@ DECLARE_CUSTOM_FUNCTION(MCharSetCode)(uint32 nChar, uint32 nCode, uint32, uint32 IsMChar[nChar] = true; } -DECLARE_CUSTOM_FUNCTION(MCharResetCode)(uint32 nChar, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(MCharResetCode)(CORO_PARAM, uint32 nChar, uint32, uint32, uint32) { MCharacter[nChar].item=Loc->GetItemFromCode(MCharacter[nChar].code); } -DECLARE_CUSTOM_FUNCTION(MCharSetPosition)(uint32 nChar, uint32 nX, uint32 nY, uint32) { +DECLARE_CUSTOM_FUNCTION(MCharSetPosition)(CORO_PARAM, uint32 nChar, uint32 nX, uint32 nY, uint32) { assert(nChar < 10); MCharacter[nChar].x=nX; MCharacter[nChar].y=nY; } -DECLARE_CUSTOM_FUNCTION(MCharSetColor)(uint32 nChar, uint32 r, uint32 g, uint32 b) { +DECLARE_CUSTOM_FUNCTION(MCharSetColor)(CORO_PARAM, uint32 nChar, uint32 r, uint32 g, uint32 b) { assert(nChar < 10); MCharacter[nChar].r=r; MCharacter[nChar].g=g; @@ -1494,7 +1523,7 @@ DECLARE_CUSTOM_FUNCTION(MCharSetColor)(uint32 nChar, uint32 r, uint32 g, uint32 } -DECLARE_CUSTOM_FUNCTION(MCharSetNumTalksInGroup)(uint32 nChar, uint32 nGroup, uint32 nTalks, uint32) { +DECLARE_CUSTOM_FUNCTION(MCharSetNumTalksInGroup)(CORO_PARAM, uint32 nChar, uint32 nGroup, uint32 nTalks, uint32) { assert(nChar < 10); assert(nGroup < 10); @@ -1502,7 +1531,7 @@ DECLARE_CUSTOM_FUNCTION(MCharSetNumTalksInGroup)(uint32 nChar, uint32 nGroup, ui } -DECLARE_CUSTOM_FUNCTION(MCharSetCurrentGroup)(uint32 nChar, uint32 nGroup, uint32, uint32) +DECLARE_CUSTOM_FUNCTION(MCharSetCurrentGroup)(CORO_PARAM, uint32 nChar, uint32 nGroup, uint32, uint32) { assert(nChar < 10); assert(nGroup < 10); @@ -1510,21 +1539,21 @@ DECLARE_CUSTOM_FUNCTION(MCharSetCurrentGroup)(uint32 nChar, uint32 nGroup, uint3 MCharacter[nChar].curgroup = nGroup; } -DECLARE_CUSTOM_FUNCTION(MCharSetNumTexts)(uint32 nChar, uint32 nTexts, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(MCharSetNumTexts)(CORO_PARAM, uint32 nChar, uint32 nTexts, uint32, uint32) { assert(nChar < 10); MCharacter[nChar].numtexts=nTexts-1; MCharacter[nChar].bInTexts = false; } -DECLARE_CUSTOM_FUNCTION(MCharSetAlwaysBack)(uint32 nChar, uint32 bAlwaysBack, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(MCharSetAlwaysBack)(CORO_PARAM, uint32 nChar, uint32 bAlwaysBack, uint32, uint32) { assert(nChar < 10); MCharacter[nChar].bAlwaysBack=bAlwaysBack; } -DECLARE_CUSTOM_FUNCTION(MCharSendMessage)(uint32 nChar, uint32 dwMessage, uint32 bIsBack, uint32 nFont) { +DECLARE_CUSTOM_FUNCTION(MCharSendMessage)(CORO_PARAM, uint32 nChar, uint32 dwMessage, uint32 bIsBack, uint32 nFont) { RMMessage msg(dwMessage); int i; int parm; @@ -1645,7 +1674,7 @@ DECLARE_CUSTOM_FUNCTION(MCharSendMessage)(uint32 nChar, uint32 dwMessage, uint32 int curDialog; -DECLARE_CUSTOM_FUNCTION(SendDialogMessage)(uint32 nPers, uint32 nMsg, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(SendDialogMessage)(CORO_PARAM, uint32 nPers, uint32 nMsg, uint32, uint32) { LPSTR string; RMTextDialog* text; int parm; @@ -1822,7 +1851,7 @@ DECLARE_CUSTOM_FUNCTION(SendDialogMessage)(uint32 nPers, uint32 nMsg, uint32, ui // @@@@ QUESTA NON SI PUO' SKIPPARE!!!!!!!!!!!!!!!!!!! -DECLARE_CUSTOM_FUNCTION(StartDialog)(uint32 nDialog, uint32 nStartGroup, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(StartDialog)(CORO_PARAM, uint32 nDialog, uint32 nStartGroup, uint32, uint32) { int nChoice; uint32 *sl; int i,num; @@ -1897,12 +1926,12 @@ DECLARE_CUSTOM_FUNCTION(StartDialog)(uint32 nDialog, uint32 nStartGroup, uint32, * Sync tra idle e mpal */ -DECLARE_CUSTOM_FUNCTION(TakeOwnership)(uint32 num, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(TakeOwnership)(CORO_PARAM, uint32 num, uint32, uint32, uint32) { // EnterCriticalSection(&cs[num]); WaitForSingleObject(mut[num],INFINITE); } -DECLARE_CUSTOM_FUNCTION(ReleaseOwnership)(uint32 num, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(ReleaseOwnership)(CORO_PARAM, uint32 num, uint32, uint32, uint32) { // LeaveCriticalSection(&cs[num]); // g_system->unlockMutex(mut[num]); warning("TODO: ReleaseOwnership"); @@ -1975,46 +2004,46 @@ void ThreadFadeOutMusic(void *nMusic) { _endthread(); } -DECLARE_CUSTOM_FUNCTION(FadeInSonoriz)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(FadeInSonoriz)(CORO_PARAM, uint32, uint32, uint32, uint32) { _beginthread(ThreadFadeInMusic, 10240, (void*)curSonoriz); } -DECLARE_CUSTOM_FUNCTION(FadeOutSonoriz)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(FadeOutSonoriz)(CORO_PARAM, uint32, uint32, uint32, uint32) { bFadeOutStop = false; _beginthread(ThreadFadeOutMusic, 10240, (void *)curSonoriz); } -DECLARE_CUSTOM_FUNCTION(FadeOutStacchetto)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(FadeOutStacchetto)(CORO_PARAM, uint32, uint32, uint32, uint32) { bFadeOutStop = false; _beginthread(ThreadFadeOutMusic, 10240, (void*)2); } -DECLARE_CUSTOM_FUNCTION(FadeInStacchetto)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(FadeInStacchetto)(CORO_PARAM, uint32, uint32, uint32, uint32) { _beginthread(ThreadFadeInMusic, 10240, (void*)2); } -DECLARE_CUSTOM_FUNCTION(StopSonoriz)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(StopSonoriz)(CORO_PARAM, uint32, uint32, uint32, uint32) { _vm->StopMusic(curSonoriz); } -DECLARE_CUSTOM_FUNCTION(StopStacchetto)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(StopStacchetto)(CORO_PARAM, uint32, uint32, uint32, uint32) { _vm->StopMusic(2); } -DECLARE_CUSTOM_FUNCTION(MuteSonoriz)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(MuteSonoriz)(CORO_PARAM, uint32, uint32, uint32, uint32) { _vm->SetMusicVolume(curSonoriz, 0); } -DECLARE_CUSTOM_FUNCTION(DemuteSonoriz)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(DemuteSonoriz)(CORO_PARAM, uint32, uint32, uint32, uint32) { bFadeOutStop = true; _vm->SetMusicVolume(curSonoriz, 64); } -DECLARE_CUSTOM_FUNCTION(MuteStacchetto)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(MuteStacchetto)(CORO_PARAM, uint32, uint32, uint32, uint32) { _vm->SetMusicVolume(2, 0); } -DECLARE_CUSTOM_FUNCTION(DemuteStacchetto)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(DemuteStacchetto)(CORO_PARAM, uint32, uint32, uint32, uint32) { _vm->SetMusicVolume(2, 64); } @@ -2139,7 +2168,7 @@ void CustPlayMusic(uint32 nChannel, const char *mFN, uint32 nFX, bool bLoop, int debug("End CustPlayMusic\n"); } -DECLARE_CUSTOM_FUNCTION(PlaySonoriz)(uint32 nMusic, uint32 nFX, uint32 bNoLoop, uint32) { +DECLARE_CUSTOM_FUNCTION(PlaySonoriz)(CORO_PARAM, uint32 nMusic, uint32 nFX, uint32 bNoLoop, uint32) { if (nFX == 0 || nFX == 1 || nFX==2) { debug("PlaySonoriz stop fadeout\n"); bFadeOutStop = true; @@ -2149,11 +2178,11 @@ DECLARE_CUSTOM_FUNCTION(PlaySonoriz)(uint32 nMusic, uint32 nFX, uint32 bNoLoop, CustPlayMusic(curSonoriz, musicFiles[nMusic].name, nFX, bNoLoop ? false : true, musicFiles[nMusic].sync); } -DECLARE_CUSTOM_FUNCTION(PlayStacchetto)(uint32 nMusic, uint32 nFX, uint32 bLoop, uint32) { +DECLARE_CUSTOM_FUNCTION(PlayStacchetto)(CORO_PARAM, uint32 nMusic, uint32 nFX, uint32 bLoop, uint32) { CustPlayMusic(2,staccFileNames[nMusic],nFX,bLoop); } -DECLARE_CUSTOM_FUNCTION(PlayItemSfx)(uint32 nItem, uint32 nSFX, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(PlayItemSfx)(CORO_PARAM, uint32 nItem, uint32 nSFX, uint32, uint32) { if (nItem== 0) { Tony->PlaySfx(nSFX); } else { @@ -2165,7 +2194,7 @@ DECLARE_CUSTOM_FUNCTION(PlayItemSfx)(uint32 nItem, uint32 nSFX, uint32, uint32) void RestoreMusic(void) { - PlaySonoriz(lastMusic, 0, 0, 0); + PlaySonoriz(nullContext, lastMusic, 0, 0, 0); if (lastTappeto != 0) CustPlayMusic(4, tappetiFile[lastTappeto], 0, true); } @@ -2181,49 +2210,63 @@ void LoadMusic(Common::InSaveFile *f) { } -DECLARE_CUSTOM_FUNCTION(StacchettoFadeStart)(uint32 nStacc, uint32 bLoop, uint32, uint32) { - FadeOutSonoriz(0, 0, 0, 0); - MuteStacchetto(0, 0, 0, 0); - PlayStacchetto(nStacc, 0, bLoop, 0); - FadeInStacchetto(0, 0, 0, 0); +DECLARE_CUSTOM_FUNCTION(StacchettoFadeStart)(CORO_PARAM, uint32 nStacc, uint32 bLoop, uint32, uint32) { + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + + CORO_INVOKE_4(FadeOutSonoriz, 0, 0, 0, 0); + CORO_INVOKE_4(MuteStacchetto, 0, 0, 0, 0); + CORO_INVOKE_4(PlayStacchetto, nStacc, 0, bLoop, 0); + CORO_INVOKE_4(FadeInStacchetto, 0, 0, 0, 0); + + CORO_END_CODE; } -DECLARE_CUSTOM_FUNCTION(StacchettoFadeEnd)(uint32 nStacc, uint32 bLoop, uint32, uint32) { - FadeOutStacchetto(0, 0, 0, 0); - FadeInSonoriz(0, 0, 0, 0); +DECLARE_CUSTOM_FUNCTION(StacchettoFadeEnd)(CORO_PARAM, uint32 nStacc, uint32 bLoop, uint32, uint32) { + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + CORO_BEGIN_CODE(_ctx); + + CORO_INVOKE_4(FadeOutStacchetto, 0, 0, 0, 0); + CORO_INVOKE_4(FadeInSonoriz, 0, 0, 0, 0); + + CORO_END_CODE; } -DECLARE_CUSTOM_FUNCTION(MustSkipIdleStart)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(MustSkipIdleStart)(CORO_PARAM, uint32, uint32, uint32, uint32) { bSkipIdle = true; SetEvent(hSkipIdle); } -DECLARE_CUSTOM_FUNCTION(MustSkipIdleEnd)(uint32, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(MustSkipIdleEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) { bSkipIdle = false; ResetEvent(hSkipIdle); } -DECLARE_CUSTOM_FUNCTION(PatIrqFreeze)(uint32 bStatus, uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(PatIrqFreeze)(CORO_PARAM, uint32 bStatus, uint32, uint32, uint32) { bPatIrqFreeze = bStatus; } -DECLARE_CUSTOM_FUNCTION(OpenInitLoadMenu)(uint32 , uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(OpenInitLoadMenu)(CORO_PARAM, uint32, uint32, uint32, uint32) { Freeze(); _vm->OpenInitLoadMenu(); Unfreeze(); } -DECLARE_CUSTOM_FUNCTION(OpenInitOptions)(uint32 , uint32, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(OpenInitOptions)(CORO_PARAM, uint32, uint32, uint32, uint32) { Freeze(); _vm->OpenInitOptions(); Unfreeze(); } -DECLARE_CUSTOM_FUNCTION(DoCredits)(uint32 nMsg, uint32 dwTime, uint32, uint32) { +DECLARE_CUSTOM_FUNCTION(DoCredits)(CORO_PARAM, uint32 nMsg, uint32 dwTime, uint32, uint32) { RMMessage msg(nMsg); RMTextDialog *text; HANDLE hDisable = CreateEvent(NULL, true, false, NULL); diff --git a/engines/tony/custom.h b/engines/tony/custom.h index 57d726f70e..a9f4ac2aab 100644 --- a/engines/tony/custom.h +++ b/engines/tony/custom.h @@ -67,10 +67,10 @@ typedef uint32 HWND; #define DECLARE_CUSTOM_FUNCTION(x) void x #define BEGIN_CUSTOM_FUNCTION_MAP() \ - static void AssignError(HWND hWnd, int num) { \ + static void AssignError(int num) { \ error("Custom function %u has been already assigned!", num); \ } \ - void INIT_CUSTOM_FUNCTION(HWND hWnd, LPCUSTOMFUNCTION *lpMap) \ + void INIT_CUSTOM_FUNCTION(LPCUSTOMFUNCTION *lpMap) \ { @@ -78,10 +78,10 @@ typedef uint32 HWND; } -#define ASSIGN(num,func) \ - if (lpMap[num]!=NULL) \ - AssignError(hWnd,num); \ - lpMap[num]=func; +#define ASSIGN(num, func) \ + if (lpMap[num] != NULL) \ + AssignError(num); \ + lpMap[num] = func; class RMTony; class RMPointer; @@ -90,7 +90,7 @@ class RMLocation; class RMInventory; class RMInput; -void INIT_CUSTOM_FUNCTION(HWND hWnd, LPCUSTOMFUNCTION *lpMap); +void INIT_CUSTOM_FUNCTION(LPCUSTOMFUNCTION *lpMap); void SetupGlobalVars(RMTony *tony, RMPointer *ptr, RMGameBoxes *box, RMLocation *loc, RMInventory *inv, RMInput *input); #endif diff --git a/engines/tony/module.mk b/engines/tony/module.mk index af0b3acd2c..24e7f70557 100644 --- a/engines/tony/module.mk +++ b/engines/tony/module.mk @@ -1,6 +1,7 @@ MODULE := engines/tony MODULE_OBJS := \ + coroutine.o \ custom.o \ detection.o \ font.o \ @@ -10,6 +11,7 @@ MODULE_OBJS := \ input.o \ inventory.o \ loc.o \ + sched.o \ sound.o \ tony.o \ tonychar.o \ diff --git a/engines/tony/mpal/mpal.cpp b/engines/tony/mpal/mpal.cpp index b977feb03b..3757cdddcf 100644 --- a/engines/tony/mpal/mpal.cpp +++ b/engines/tony/mpal/mpal.cpp @@ -51,11 +51,12 @@ #include "common/file.h" #include "common/savefile.h" #include "common/system.h" +#include "tony/sched.h" #include "tony/tony.h" -#include "lzo.h" -#include "mpal.h" -#include "mpaldll.h" -#include "stubs.h" +#include "tony/mpal/lzo.h" +#include "tony/mpal/mpal.h" +#include "tony/mpal/mpaldll.h" +#include "tony/mpal/stubs.h" namespace Tony { @@ -829,7 +830,10 @@ static LPITEM GetItemData(uint32 nOrdItem) { \****************************************************************************/ void PASCAL CustomThread(LPCFCALL p) { - lplpFunctions[p->nCf](p->arg1, p->arg2, p->arg3, p->arg4); + // FIXME: Convert to proper corotuine call + warning("FIXME: CustomThread call"); + + lplpFunctions[p->nCf](nullContext, p->arg1, p->arg2, p->arg3, p->arg4); GlobalFree(p); ExitThread(1); // _endthread(); @@ -939,50 +943,69 @@ void PASCAL ScriptThread(LPMPALSCRIPT s) { * \****************************************************************************/ -void PASCAL ActionThread(LPMPALITEM item) { - int j, k; +void ActionThread(CORO_PARAM, const void *param) { + // COROUTINE + CORO_BEGIN_CONTEXT; + int j, k; + CORO_END_CONTEXT(_ctx); - for (j = 0;jAction[item->dwRes].nCmds; j++) { - k=item->Action[item->dwRes].CmdNum[j]; + const LPMPALITEM item = *(const LPMPALITEM *)param; - switch (item->Command[k].type) { - case 1: - // Funzione custom - lplpFunctions[item->Command[k].nCf]( - item->Command[k].arg1, - item->Command[k].arg2, - item->Command[k].arg3, - item->Command[k].arg4 - ); - break; + CORO_BEGIN_CODE(_ctx); + + mpalError = 0; + for (_ctx->j = 0; _ctx->j < item->Action[item->dwRes].nCmds; _ctx->j++) { + _ctx->k = item->Action[item->dwRes].CmdNum[_ctx->j]; + + if (item->Command[_ctx->k].type == 1) { + // Custom function + CORO_INVOKE_4(lplpFunctions[item->Command[_ctx->k].nCf], + item->Command[_ctx->k].arg1, + item->Command[_ctx->k].arg2, + item->Command[_ctx->k].arg3, + item->Command[_ctx->k].arg4 - case 2: + ); + } else if (item->Command[_ctx->k].type == 2) { // Variable assign LockVar(); - varSetValue(item->Command[k].lpszVarName, EvaluateExpression(item->Command[k].expr)); + varSetValue(item->Command[_ctx->k].lpszVarName, EvaluateExpression(item->Command[_ctx->k].expr)); UnlockVar(); break; - default: + } else { mpalError = 1; - ExitThread(0); -// _endthread(); + break; } } GlobalFree(item); - //bExecutingAction = false; + + CORO_KILL_SELF(); - ExitThread(1); -// _endthread(); + CORO_END_CODE; } -void PASCAL ShutUpActionThread(HANDLE hThread) { +/** + * This thread monitors a created action to detect when it ends. + * @remarks Since actions can spawn sub-actions, this needs to be a + * separate thread to determine when the outer action is done + */ +void ShutUpActionThread(CORO_PARAM, const void *param) { + // COROUTINE + CORO_BEGIN_CONTEXT; + CORO_END_CONTEXT(_ctx); + + HANDLE hThread = *(const HANDLE *)param; + + CORO_BEGIN_CODE(_ctx); + WaitForSingleObject(hThread, INFINITE); bExecutingAction = false; - ExitThread(1); -// _endthread(); + CORO_KILL_SELF(); + + CORO_END_CODE; } /****************************************************************************\ @@ -1241,7 +1264,8 @@ void PASCAL LocationPollThread(uint32 id) { */ // Set idle skip on - lplpFunctions[200](0, 0, 0, 0); + // FIXME: Convert to co-routine + lplpFunctions[200](nullContext, 0, 0, 0, 0); for (i = 0; i < nRealItems; i++) if (MyThreads[i].nItem != 0) { @@ -1252,7 +1276,8 @@ void PASCAL LocationPollThread(uint32 id) { } // Set idle skip off - lplpFunctions[201](0, 0, 0, 0); + // FIXME: Convert to co-routine + lplpFunctions[201](nullContext, 0, 0, 0, 0); /* Abbiamo finito */ GlobalFree(MyThreads); @@ -1324,7 +1349,9 @@ void PASCAL GroupThread(uint32 nGroup) { switch (dialog->Command[k].type) { /* Funzione custom: la richiama */ case 1: + // FIXME: Convert to co-routine lplpFunctions[dialog->Command[k].nCf]( + nullContext, dialog->Command[k].arg1, dialog->Command[k].arg2, dialog->Command[k].arg3, @@ -1488,8 +1515,7 @@ static HANDLE DoAction(uint32 nAction, uint32 ordItem, uint32 dwParam) { LPMPALITEM item = lpmiItems; int i; LPMPALITEM newitem; - uint32 dwId; - HANDLE h; + PROCESS *h; item+=ordItem; Common::String buf = Common::String::format("Status.%u", item->nObj); @@ -1510,7 +1536,7 @@ static HANDLE DoAction(uint32 nAction, uint32 ordItem, uint32 dwParam) { // Ora abbiamo trova l'azione giusta che deve essere eseguita. // Duplichiamo l'item corrente e copiamo la azione #i nella #0 - newitem=(LPMPALITEM)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(MPALITEM)); + newitem = (LPMPALITEM)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(MPALITEM)); if (newitem == NULL) return INVALID_HANDLE_VALUE; @@ -1524,12 +1550,11 @@ static HANDLE DoAction(uint32 nAction, uint32 ordItem, uint32 dwParam) { // E finalmente possiamo richiamare il thread, che eseguira' l'azione // 0 dell'item, e poi liberera' la memoria con la GlobalFree() -/* !!! Nuova gestione dei thread -*/ - if ((h = CreateThread(NULL, 10240, (LPTHREAD_START_ROUTINE)ActionThread, (void *)newitem, 0, &dwId)) == NULL) + // !!! New thread management + if ((h = g_scheduler->createProcess(ActionThread, newitem)) == NULL) return INVALID_HANDLE_VALUE; - if ((h = CreateThread(NULL, 10240,(LPTHREAD_START_ROUTINE)ShutUpActionThread, (void *)h, 0, &dwId)) == NULL) + if ((h = g_scheduler->createProcess(0, ShutUpActionThread, &h, sizeof(PROCESS *))) == NULL) return INVALID_HANDLE_VALUE; /* @@ -1543,7 +1568,7 @@ static HANDLE DoAction(uint32 nAction, uint32 ordItem, uint32 dwParam) { nExecutingAction = item->nObj; bExecutingAction = true; - return h; + return (HANDLE)h; } return INVALID_HANDLE_VALUE; @@ -1674,7 +1699,7 @@ bool mpalInit(const char *lpszMpcFileName, const char *lpszMprFileName, LPLPCUST //printf("Dialog: %lu\n", sizeof(MPALDIALOG)); /* Si salva l'array delle funzioni custom */ - lplpFunctions=lplpcfArray; + lplpFunctions = lplpcfArray; /* Apre il file MPC in lettura */ if (!hMpc.open(lpszMpcFileName)) diff --git a/engines/tony/mpal/mpal.h b/engines/tony/mpal/mpal.h index e66f1fdb7e..3c2e62d992 100644 --- a/engines/tony/mpal/mpal.h +++ b/engines/tony/mpal/mpal.h @@ -119,6 +119,7 @@ #include "common/scummsys.h" #include "common/rect.h" +#include "tony/coroutine.h" namespace Tony { @@ -220,7 +221,7 @@ typedef ITEM *LPITEM; * to perform various controls as a result of an action \****************************************************************************/ -typedef void (*LPCUSTOMFUNCTION)(uint32, uint32, uint32, uint32); +typedef void (*LPCUSTOMFUNCTION)(CORO_PARAM, uint32, uint32, uint32, uint32); typedef LPCUSTOMFUNCTION *LPLPCUSTOMFUNCTION; diff --git a/engines/tony/sched.cpp b/engines/tony/sched.cpp new file mode 100644 index 0000000000..7f259b7a5b --- /dev/null +++ b/engines/tony/sched.cpp @@ -0,0 +1,498 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Process scheduler. + */ + +#include "common/textconsole.h" +#include "common/util.h" +#include "tony/sched.h" + +namespace Tony { + +Scheduler *g_scheduler = 0; + +//--------------------- FUNCTIONS ------------------------ + +Scheduler::Scheduler() { + processList = NULL; + pFreeProcesses = NULL; + pCurrent = NULL; + +#ifdef DEBUG + // diagnostic process counters + numProcs = 0; + maxProcs = 0; +#endif + + pRCfunction = 0; + + active = new PROCESS; + active->pPrevious = NULL; + active->pNext = NULL; + + g_scheduler = this; // FIXME HACK +} + +Scheduler::~Scheduler() { + // Kill all running processes (i.e. free memory allocated for their state). + PROCESS *pProc = active->pNext; + while (pProc != NULL) { + delete pProc->state; + pProc->state = 0; + pProc = pProc->pNext; + } + + free(processList); + processList = NULL; + + delete active; + active = 0; +} + +/** + * Kills all processes and places them on the free list. + */ +void Scheduler::reset() { + +#ifdef DEBUG + // clear number of process in use + numProcs = 0; +#endif + + if (processList == NULL) { + // first time - allocate memory for process list + processList = (PROCESS *)calloc(MAX_PROCESSES, sizeof(PROCESS)); + + // make sure memory allocated + if (processList == NULL) { + error("Cannot allocate memory for process data"); + } + + // fill with garbage + memset(processList, 'S', MAX_PROCESSES * sizeof(PROCESS)); + } + + // Kill all running processes (i.e. free memory allocated for their state). + PROCESS *pProc = active->pNext; + while (pProc != NULL) { + delete pProc->state; + pProc->state = 0; + pProc = pProc->pNext; + } + + // no active processes + pCurrent = active->pNext = NULL; + + // place first process on free list + pFreeProcesses = processList; + + // link all other processes after first + for (int i = 1; i <= NUM_PROCESS; i++) { + processList[i - 1].pNext = (i == NUM_PROCESS) ? NULL : processList + i; + processList[i - 1].pPrevious = (i == 1) ? active : processList + (i - 2); + } +} + + +#ifdef DEBUG +/** + * Shows the maximum number of process used at once. + */ +void Scheduler::printStats() { + debug("%i process of %i used", maxProcs, NUM_PROCESS); +} +#endif + +#ifdef DEBUG +/** + * Checks both the active and free process list to insure all the links are valid, + * and that no processes have been lost + */ +void Scheduler::CheckStack() { + Common::List pList; + + // Check both the active and free process lists + for (int i = 0; i < 2; ++i) { + PROCESS *p = (i == 0) ? active : pFreeProcesses; + + if (p != NULL) { + // Make sure the linkages are correct + while (p->pNext != NULL) { + assert(p->pNext->pPrevious == p); + pList.push_back(p); + p = p->pNext; + } + pList.push_back(p); + } + } + + // Make sure all processes are accounted for + for (int idx = 0; idx < NUM_PROCESS; idx++) { + bool found = false; + for (Common::List::iterator i = pList.begin(); i != pList.end(); ++i) { + PROCESS *pTemp = *i; + if (*i == &processList[idx]) { + found = true; + break; + } + } + + assert(found); + } +} +#endif + +/** + * Give all active processes a chance to run + */ +void Scheduler::schedule() { + // start dispatching active process list + PROCESS *pNext; + PROCESS *pProc = active->pNext; + while (pProc != NULL) { + pNext = pProc->pNext; + + if (--pProc->sleepTime <= 0) { + // process is ready for dispatch, activate it + pCurrent = pProc; + pProc->coroAddr(pProc->state, pProc->param); + + if (!pProc->state || pProc->state->_sleep <= 0) { + // Coroutine finished + pCurrent = pCurrent->pPrevious; + killProcess(pProc); + } else { + pProc->sleepTime = pProc->state->_sleep; + } + + // pCurrent may have been changed + pNext = pCurrent->pNext; + pCurrent = NULL; + } + + pProc = pNext; + } +} + +/** + * Reschedules all the processes to run again this query + */ +void Scheduler::rescheduleAll() { + assert(pCurrent); + + // Unlink current process + pCurrent->pPrevious->pNext = pCurrent->pNext; + if (pCurrent->pNext) + pCurrent->pNext->pPrevious = pCurrent->pPrevious; + + // Add process to the start of the active list + pCurrent->pNext = active->pNext; + active->pNext->pPrevious = pCurrent; + active->pNext = pCurrent; + pCurrent->pPrevious = active; +} + +/** + * If the specified process has already run on this tick, make it run + * again on the current tick. + */ +void Scheduler::reschedule(PPROCESS pReSchedProc) { + // If not currently processing the schedule list, then no action is needed + if (!pCurrent) + return; + + if (!pReSchedProc) + pReSchedProc = pCurrent; + + PPROCESS pEnd; + + // Find the last process in the list. + // But if the target process is down the list from here, do nothing + for (pEnd = pCurrent; pEnd->pNext != NULL; pEnd = pEnd->pNext) { + if (pEnd->pNext == pReSchedProc) + return; + } + + assert(pEnd->pNext == NULL); + + // Could be in the middle of a KillProc()! + // Dying process was last and this process was penultimate + if (pReSchedProc->pNext == NULL) + return; + + // If we're moving the current process, move it back by one, so that the next + // schedule() iteration moves to the now next one + if (pCurrent == pReSchedProc) + pCurrent = pCurrent->pPrevious; + + // Unlink the process, and add it at the end + pReSchedProc->pPrevious->pNext = pReSchedProc->pNext; + pReSchedProc->pNext->pPrevious = pReSchedProc->pPrevious; + pEnd->pNext = pReSchedProc; + pReSchedProc->pPrevious = pEnd; + pReSchedProc->pNext = NULL; +} + +/** + * Moves the specified process to the end of the dispatch queue + * allowing it to run again within the current game cycle. + * @param pGiveProc Which process + */ +void Scheduler::giveWay(PPROCESS pReSchedProc) { + // If not currently processing the schedule list, then no action is needed + if (!pCurrent) + return; + + if (!pReSchedProc) + pReSchedProc = pCurrent; + + // If the process is already at the end of the queue, nothing has to be done + if (!pReSchedProc->pNext) + return; + + PPROCESS pEnd; + + // Find the last process in the list. + for (pEnd = pCurrent; pEnd->pNext != NULL; pEnd = pEnd->pNext) + ; + assert(pEnd->pNext == NULL); + + + // If we're moving the current process, move it back by one, so that the next + // schedule() iteration moves to the now next one + if (pCurrent == pReSchedProc) + pCurrent = pCurrent->pPrevious; + + // Unlink the process, and add it at the end + pReSchedProc->pPrevious->pNext = pReSchedProc->pNext; + pReSchedProc->pNext->pPrevious = pReSchedProc->pPrevious; + pEnd->pNext = pReSchedProc; + pReSchedProc->pPrevious = pEnd; + pReSchedProc->pNext = NULL; +} + +/** + * Creates a new process. + * + * @param pid process identifier + * @param CORO_ADDR coroutine start address + * @param pParam process specific info + * @param sizeParam size of process specific info + */ +PROCESS *Scheduler::createProcess(int pid, CORO_ADDR coroAddr, const void *pParam, int sizeParam) { + PROCESS *pProc; + + // get a free process + pProc = pFreeProcesses; + + // trap no free process + assert(pProc != NULL); // Out of processes + +#ifdef DEBUG + // one more process in use + if (++numProcs > maxProcs) + maxProcs = numProcs; +#endif + + // get link to next free process + pFreeProcesses = pProc->pNext; + if (pFreeProcesses) + pFreeProcesses->pPrevious = NULL; + + if (pCurrent != NULL) { + // place new process before the next active process + pProc->pNext = pCurrent->pNext; + if (pProc->pNext) + pProc->pNext->pPrevious = pProc; + + // make this new process the next active process + pCurrent->pNext = pProc; + pProc->pPrevious = pCurrent; + + } else { // no active processes, place process at head of list + pProc->pNext = active->pNext; + pProc->pPrevious = active; + + if (pProc->pNext) + pProc->pNext->pPrevious = pProc; + active->pNext = pProc; + + } + + // set coroutine entry point + pProc->coroAddr = coroAddr; + + // clear coroutine state + pProc->state = 0; + + // wake process up as soon as possible + pProc->sleepTime = 1; + + // set new process id + pProc->pid = pid; + + // set new process specific info + if (sizeParam) { + assert(sizeParam > 0 && sizeParam <= PARAM_SIZE); + + // set new process specific info + memcpy(pProc->param, pParam, sizeParam); + } + + // return created process + return pProc; +} + +/** + * Kills the specified process. + * + * @param pKillProc which process to kill + */ +void Scheduler::killProcess(PROCESS *pKillProc) { + // make sure a valid process pointer + assert(pKillProc >= processList && pKillProc <= processList + NUM_PROCESS - 1); + + // can not kill the current process using killProcess ! + assert(pCurrent != pKillProc); + +#ifdef DEBUG + // one less process in use + --numProcs; + assert(numProcs >= 0); +#endif + + // Free process' resources + if (pRCfunction != NULL) + (pRCfunction)(pKillProc); + + delete pKillProc->state; + pKillProc->state = 0; + + // Take the process out of the active chain list + pKillProc->pPrevious->pNext = pKillProc->pNext; + if (pKillProc->pNext) + pKillProc->pNext->pPrevious = pKillProc->pPrevious; + + // link first free process after pProc + pKillProc->pNext = pFreeProcesses; + if (pFreeProcesses) + pKillProc->pNext->pPrevious = pKillProc; + pKillProc->pPrevious = NULL; + + // make pKillProc the first free process + pFreeProcesses = pKillProc; +} + + + +/** + * Returns a pointer to the currently running process. + */ +PROCESS *Scheduler::getCurrentProcess() { + return pCurrent; +} + +/** + * Returns the process identifier of the specified process. + * + * @param pProc which process + */ +int Scheduler::getCurrentPID() const { + PROCESS *pProc = pCurrent; + + // make sure a valid process pointer + assert(pProc >= processList && pProc <= processList + NUM_PROCESS - 1); + + // return processes PID + return pProc->pid; +} + +/** + * Kills any process matching the specified PID. The current + * process cannot be killed. + * + * @param pidKill process identifier of process to kill + * @param pidMask mask to apply to process identifiers before comparison + * @return The number of processes killed is returned. + */ +int Scheduler::killMatchingProcess(int pidKill, int pidMask) { + int numKilled = 0; + PROCESS *pProc, *pPrev; // process list pointers + + for (pProc = active->pNext, pPrev = active; pProc != NULL; pPrev = pProc, pProc = pProc->pNext) { + if ((pProc->pid & pidMask) == pidKill) { + // found a matching process + + // dont kill the current process + if (pProc != pCurrent) { + // kill this process + numKilled++; + + // Free the process' resources + if (pRCfunction != NULL) + (pRCfunction)(pProc); + + delete pProc->state; + pProc->state = 0; + + // make prev point to next to unlink pProc + pPrev->pNext = pProc->pNext; + if (pProc->pNext) + pPrev->pNext->pPrevious = pPrev; + + // link first free process after pProc + pProc->pNext = pFreeProcesses; + pProc->pPrevious = NULL; + pFreeProcesses->pPrevious = pProc; + + // make pProc the first free process + pFreeProcesses = pProc; + + // set to a process on the active list + pProc = pPrev; + } + } + } + +#ifdef DEBUG + // adjust process in use + numProcs -= numKilled; + assert(numProcs >= 0); +#endif + + // return number of processes killed + return numKilled; +} + +/** + * Set pointer to a function to be called by killProcess(). + * + * May be called by a resource allocator, the function supplied is + * called by killProcess() to allow the resource allocator to free + * resources allocated to the dying process. + * + * @param pFunc Function to be called by killProcess() + */ +void Scheduler::setResourceCallback(VFPTRPP pFunc) { + pRCfunction = pFunc; +} + +} // End of namespace Tony diff --git a/engines/tony/sched.h b/engines/tony/sched.h new file mode 100644 index 0000000000..9bc6d052da --- /dev/null +++ b/engines/tony/sched.h @@ -0,0 +1,128 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Data structures used by the process scheduler + */ + +#ifndef TONY_SCHED_H +#define TONY_SCHED_H + +#include "tony/coroutine.h" + +namespace Tony { + +// the size of process specific info +#define PARAM_SIZE 32 + +// the maximum number of processes +#define NUM_PROCESS 100 +#define MAX_PROCESSES 100 + +typedef void (*CORO_ADDR)(CoroContext &, const void *); + +/** process structure */ +struct PROCESS { + PROCESS *pNext; ///< pointer to next process in active or free list + PROCESS *pPrevious; ///< pointer to previous process in active or free list + + CoroContext state; ///< the state of the coroutine + CORO_ADDR coroAddr; ///< the entry point of the coroutine + + int sleepTime; ///< number of scheduler cycles to sleep + int pid; ///< process ID + char param[PARAM_SIZE]; ///< process specific info +}; +typedef PROCESS *PPROCESS; + +struct INT_CONTEXT; + +/** + * Create and manage "processes" (really coroutines). + */ +class Scheduler { +public: + /** Pointer to a function of the form "void function(PPROCESS)" */ + typedef void (*VFPTRPP)(PROCESS *); + +private: + + /** list of all processes */ + PROCESS *processList; + + /** active process list - also saves scheduler state */ + PROCESS *active; + + /** pointer to free process list */ + PROCESS *pFreeProcesses; + + /** the currently active process */ + PROCESS *pCurrent; + +#ifdef DEBUG + // diagnostic process counters + int numProcs; + int maxProcs; + + void CheckStack(); +#endif + + /** + * Called from killProcess() to enable other resources + * a process may be allocated to be released. + */ + VFPTRPP pRCfunction; + + +public: + + Scheduler(); + ~Scheduler(); + + void reset(); + + #ifdef DEBUG + void printStats(); + #endif + + void schedule(); + void rescheduleAll(); + void reschedule(PPROCESS pReSchedProc = NULL); + void giveWay(PPROCESS pReSchedProc = NULL); + + PROCESS *createProcess(int pid, CORO_ADDR coroAddr, const void *pParam, int sizeParam); + PROCESS *createProcess(CORO_ADDR coroAddr, const void *pParam) { + return createProcess(0, coroAddr, &pParam, sizeof(void *)); + } + void killProcess(PROCESS *pKillProc); + + PROCESS *getCurrentProcess(); + int getCurrentPID() const; + int killMatchingProcess(int pidKill, int pidMask = -1); + + + void setResourceCallback(VFPTRPP pFunc); + +}; + +extern Scheduler *g_scheduler; // FIXME: Temporary global var, to be used until everything has been OOifyied + +} // End of namespace Tony + +#endif // TONY_SCHED_H diff --git a/engines/tony/tony.cpp b/engines/tony/tony.cpp index cf746dc978..ab6592342d 100644 --- a/engines/tony/tony.cpp +++ b/engines/tony/tony.cpp @@ -26,6 +26,7 @@ #include "common/events.h" #include "common/file.h" #include "tony/tony.h" +#include "tony/custom.h" #include "tony/game.h" #include "tony/mpal/mpal.h" @@ -67,11 +68,15 @@ Common::ErrorCode TonyEngine::Init() { m_bDrawLocation = true; m_startTime = g_system->getMillis(); + // Reset the scheduler + _scheduler.reset(); + // Initialise the graphics window _window.Init(); // Initialise the function list Common::fill(FuncList, FuncList + 300, (LPCUSTOMFUNCTION)NULL); + InitCustomFunctionMap(); // Initializes MPAL system, passing the custom functions list Common::File f; @@ -127,6 +132,10 @@ Common::ErrorCode TonyEngine::Init() { return Common::kNoError; } +void TonyEngine::InitCustomFunctionMap() { + INIT_CUSTOM_FUNCTION(FuncList); +} + /** * Display an error message */ @@ -385,6 +394,9 @@ void TonyEngine::Play(void) { while (g_system->getEventManager()->pollEvent(evt)) ; + // Call any scheduled processes + _scheduler.schedule(); + // Call the engine to handle the next frame _theEngine.DoFrame(m_bDrawLocation); @@ -468,8 +480,7 @@ void TonyEngine::FreezeTime(void) { m_nTimeFreezed = GetTime() - m_startTime; } -void TonyEngine::UnfreezeTime(void) -{ +void TonyEngine::UnfreezeTime(void) { m_bTimeFreezed = false; } diff --git a/engines/tony/tony.h b/engines/tony/tony.h index e1526db026..1eafe54afb 100644 --- a/engines/tony/tony.h +++ b/engines/tony/tony.h @@ -35,6 +35,7 @@ #include "tony/mpal/memory.h" #include "tony/gfxengine.h" #include "tony/loc.h" +#include "tony/sched.h" #include "tony/utils.h" #include "tony/window.h" @@ -80,6 +81,7 @@ private: void CloseMusic(); bool OpenVoiceDatabase(); void CloseVoiceDatabase(); + void InitCustomFunctionMap(); protected: // Engine APIs virtual Common::Error run(); @@ -93,6 +95,7 @@ public: Common::File _vdbFP; Common::Array _voices; FPSOUND _theSound; + Scheduler _scheduler; enum DATADIR { DD_BASE = 1, @@ -140,9 +143,6 @@ public: // Loop che gestisce i messaggi quando siamo in pausa void PauseLoop(void); - // Carica un modulo e le sue funzioni custom - void InitCustomDll(LPCUSTOMFUNCTION *FuncList); - void Play(); void Close(); void Abort(); diff --git a/engines/tony/tonychar.cpp b/engines/tony/tonychar.cpp index a2648318fe..e4f334d0e5 100644 --- a/engines/tony/tonychar.cpp +++ b/engines/tony/tonychar.cpp @@ -224,7 +224,7 @@ void RMTony::ExecuteAction(int nAction, int nActionItem, int nParm) { } } } else { - // Esegue l'azione + // Perform the action hThread = mpalQueryDoAction(nAction, nActionItem, 0); } -- cgit v1.2.3