diff options
author | Paul Gilbert | 2012-05-11 23:23:05 +1000 |
---|---|---|
committer | Paul Gilbert | 2012-05-11 23:23:05 +1000 |
commit | beef5fdb264850079208b5513cf72626ff7edd86 (patch) | |
tree | 2bc16c9433836f68d0d008fd29dbe18aa261ce92 /engines | |
parent | 68c1b0b0e46b0575a4670d1ffda2fa3c8ae94ed8 (diff) | |
download | scummvm-rg350-beef5fdb264850079208b5513cf72626ff7edd86.tar.gz scummvm-rg350-beef5fdb264850079208b5513cf72626ff7edd86.tar.bz2 scummvm-rg350-beef5fdb264850079208b5513cf72626ff7edd86.zip |
TONY: Removal of now redundant includes, and deprecated scheduler/coroutine files
Diffstat (limited to 'engines')
-rw-r--r-- | engines/tony/coroutine.cpp | 82 | ||||
-rw-r--r-- | engines/tony/coroutine.h | 271 | ||||
-rw-r--r-- | engines/tony/custom.cpp | 1 | ||||
-rw-r--r-- | engines/tony/font.h | 1 | ||||
-rw-r--r-- | engines/tony/loc.h | 1 | ||||
-rw-r--r-- | engines/tony/mpal/mpal.cpp | 1 | ||||
-rw-r--r-- | engines/tony/sched.cpp | 801 | ||||
-rw-r--r-- | engines/tony/sched.h | 27 | ||||
-rw-r--r-- | engines/tony/tony.cpp | 109 | ||||
-rw-r--r-- | engines/tony/tony.h | 1 |
10 files changed, 104 insertions, 1191 deletions
diff --git a/engines/tony/coroutine.cpp b/engines/tony/coroutine.cpp deleted file mode 100644 index 504dc2a3fd..0000000000 --- a/engines/tony/coroutine.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* 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<Common::String, int> 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 deleted file mode 100644 index b4eb105f58..0000000000 --- a/engines/tony/coroutine.h +++ /dev/null @@ -1,271 +0,0 @@ -/* 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: - * <http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html>. - * 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 : Common::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 { CoroScheduler.giveWay(); CORO_SLEEP(1); } while (0) -#define CORO_RESCHEDULE do { CoroScheduler.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 234dd0a4f9..89d3123b60 100644 --- a/engines/tony/custom.cpp +++ b/engines/tony/custom.cpp @@ -56,7 +56,6 @@ #include "tony/font.h" #include "tony/game.h" #include "tony/gfxcore.h" -#include "tony/sched.h" #include "tony/tony.h" #include "tony/tonychar.h" #include "tony/utils.h" diff --git a/engines/tony/font.h b/engines/tony/font.h index 7447f31515..d883733db6 100644 --- a/engines/tony/font.h +++ b/engines/tony/font.h @@ -52,7 +52,6 @@ #include "common/coroutines.h" #include "tony/gfxcore.h" #include "tony/resid.h" -#include "tony/sched.h" namespace Tony { diff --git a/engines/tony/loc.h b/engines/tony/loc.h index 4b8946da54..218aca02e7 100644 --- a/engines/tony/loc.h +++ b/engines/tony/loc.h @@ -52,7 +52,6 @@ #include "common/system.h" #include "common/file.h" #include "tony/mpal/stubs.h" -#include "tony/sched.h" #include "tony/sound.h" #include "tony/utils.h" diff --git a/engines/tony/mpal/mpal.cpp b/engines/tony/mpal/mpal.cpp index 42c790a1c7..a665fbacc5 100644 --- a/engines/tony/mpal/mpal.cpp +++ b/engines/tony/mpal/mpal.cpp @@ -51,7 +51,6 @@ #include "common/file.h" #include "common/savefile.h" #include "common/system.h" -#include "tony/sched.h" #include "tony/tony.h" #include "tony/mpal/lzo.h" #include "tony/mpal/mpal.h" diff --git a/engines/tony/sched.cpp b/engines/tony/sched.cpp deleted file mode 100644 index c447afa094..0000000000 --- a/engines/tony/sched.cpp +++ /dev/null @@ -1,801 +0,0 @@ -/* 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/system.h" -#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 = NULL; - pidCounter = 0; - - active = new PROCESS; - active->pPrevious = NULL; - active->pNext = NULL; - - g_scheduler = this; // FIXME HACK - - reset(); -} - -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; - - // Clear the event list - Common::List<EVENT *>::iterator i; - for (i = _events.begin(); i != _events.end(); ++i) - delete (*i); -} - -/** - * 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->waiting = false; - 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<PROCESS *> 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<PROCESS *>::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; -} - -/** - * Continously makes a given process wait for another process to finish or event to signal. - * - * @param pid Process/Event identifier - * @param duration Duration in milliseconds - * @param expired If specified, set to true if delay period expired - */ -void Scheduler::waitForSingleObject(CORO_PARAM, int pid, uint32 duration, bool *expired) { - if (!pCurrent) - error("Called Scheduler::waitForSingleObject from the main process"); - - CORO_BEGIN_CONTEXT; - uint32 endTime; - PROCESS *pProcess; - EVENT *pEvent; - CORO_END_CONTEXT(_ctx); - - 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 - *expired = true; - - // Outer loop for doing checks until expiry - while (g_system->getMillis() < _ctx->endTime) { - // Check to see if a process or event with the given Id exists - _ctx->pProcess = getProcess(pid); - _ctx->pEvent = !_ctx->pProcess ? getEvent(pid) : NULL; - - // If there's no active process or event, presume it's a process that's finished, - // so the waiting can immediately exit - if ((_ctx->pProcess == NULL) && (_ctx->pEvent == NULL)) { - if (expired) - *expired = false; - break; - } - - // If a process was found, don't go into the if statement, and keep waiting. - // Likewise if it's an event that's not yet signalled - if ((_ctx->pEvent != NULL) && _ctx->pEvent->signalled) { - // Unless the event is flagged for manual reset, reset it now - if (!_ctx->pEvent->manualReset) - _ctx->pEvent->signalled = false; - - if (expired) - *expired = false; - break; - } - - // Sleep until the next cycle - CORO_SLEEP(1); - } - - // Signal waiting is done - pCurrent->waiting = false; - - CORO_END_CODE; -} - -/** - * Continously makes a given process wait for given prcesses to finished or events to be set - * - * @param nCount Number of Id's being passed - * @param evtList List of pids to wait for - * @param bWaitAll Specifies whether all or any of the processes/events - * @param duration Duration in milliseconds - * @param expired Set to true if delay period expired - */ -void Scheduler::waitForMultipleObjects(CORO_PARAM, int nCount, uint32 *pidList, bool bWaitAll, - uint32 duration, bool *expired) { - if (!pCurrent) - error("Called Scheduler::waitForMultipleEvents from the main process"); - - CORO_BEGIN_CONTEXT; - uint32 endTime; - bool signalled; - bool pidSignalled; - int i; - PROCESS *pProcess; - EVENT *pEvent; - CORO_END_CONTEXT(_ctx); - - CORO_BEGIN_CODE(_ctx); - - // Signal as waiting - pCurrent->waiting = true; - - _ctx->endTime = (duration == INFINITE) ? INFINITE : g_system->getMillis() + duration; - if (expired) - // Presume that delay will expire - *expired = true; - - // Outer loop for doing checks until expiry - while (g_system->getMillis() < _ctx->endTime) { - _ctx->signalled = bWaitAll; - - for (_ctx->i = 0; _ctx->i < nCount; ++_ctx->i) { - _ctx->pProcess = getProcess(pidList[_ctx->i]); - _ctx->pEvent = !_ctx->pProcess ? getEvent(pidList[_ctx->i]) : NULL; - - // Determine the signalled state - _ctx->pidSignalled = (_ctx->pProcess) || !_ctx->pEvent ? false : _ctx->pEvent->signalled; - - if (bWaitAll && _ctx->pidSignalled) - _ctx->signalled = false; - else if (!bWaitAll & _ctx->pidSignalled) - _ctx->signalled = true; - } - - // At this point, if the signalled variable is set, waiting is finished - if (_ctx->signalled) { - // Automatically reset any events not flagged for manual reset - for (_ctx->i = 0; _ctx->i < nCount; ++_ctx->i) { - _ctx->pEvent = getEvent(pidList[_ctx->i]); - - if (_ctx->pEvent->manualReset) - _ctx->pEvent->signalled = false; - } - - if (expired) - *expired = false; - break; - } - - // Sleep until the next cycle - CORO_SLEEP(1); - } - - // Signal waiting is done - pCurrent->waiting = false; - - CORO_END_CODE; -} - -/** - * Make the active process sleep for the given duration in milliseconds - * @param duration Duration in milliseconds - * @remarks This duration won't be precise, since it relies on the frequency the - * scheduler is called. - */ -void Scheduler::sleep(CORO_PARAM, uint32 duration) { - if (!pCurrent) - error("Called Scheduler::waitForSingleObject from the main process"); - - CORO_BEGIN_CONTEXT; - uint32 endTime; - PROCESS *pProcess; - EVENT *pEvent; - CORO_END_CONTEXT(_ctx); - - CORO_BEGIN_CODE(_ctx); - - // Signal as waiting - pCurrent->waiting = true; - - _ctx->endTime = g_system->getMillis() + duration; - - // Outer loop for doing checks until expiry - while (g_system->getMillis() < _ctx->endTime) { - // Sleep until the next cycle - CORO_SLEEP(1); - } - - // Signal waiting is done - pCurrent->waiting = false; - - CORO_END_CODE; -} - -/** - * 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 - */ -uint32 Scheduler::createProcess(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 = ++pidCounter; - - // 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->pid; -} - -/** - * 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(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 & (uint32)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; -} - -PROCESS *Scheduler::getProcess(uint32 pid) { - PROCESS *pProc = active->pNext; - while ((pProc != NULL) && (pProc->pid != pid)) - pProc = pProc->pNext; - - return pProc; -} - -EVENT *Scheduler::getEvent(uint32 pid) { - Common::List<EVENT *>::iterator i; - for (i = _events.begin(); i != _events.end(); ++i) { - EVENT *evt = *i; - if (evt->pid == pid) - return evt; - } - - return NULL; -} - - -/** - * Creates a new event object - * @param bManualReset Events needs to be manually reset. Otherwise, events - * will be automatically reset after a process waits on the event finishes - * @param bInitialState Specifies whether the event is signalled or not initially - */ -uint32 Scheduler::createEvent(bool bManualReset, bool bInitialState) { - EVENT *evt = new EVENT(); - evt->pid = ++pidCounter; - evt->manualReset = bManualReset; - evt->signalled = bInitialState; - - _events.push_back(evt); - return evt->pid; -} - -/** - * Destroys the given event - * @param pidEvent Event PID - */ -void Scheduler::closeEvent(uint32 pidEvent) { - EVENT *evt = getEvent(pidEvent); - if (evt) { - _events.remove(evt); - delete evt; - } -} - -/** - * Sets the event - * @param pidEvent Event PID - */ -void Scheduler::setEvent(uint32 pidEvent) { - EVENT *evt = getEvent(pidEvent); - if (evt) - evt->signalled = true; -} - -/** - * Resets the event - * @param pidEvent Event PID - */ -void Scheduler::resetEvent(uint32 pidEvent) { - EVENT *evt = getEvent(pidEvent); - if (evt) - evt->signalled = false; -} - -/** - * 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 deleted file mode 100644 index f7dabd47ae..0000000000 --- a/engines/tony/sched.h +++ /dev/null @@ -1,27 +0,0 @@ -/* 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 - -#endif // TONY_SCHED_H diff --git a/engines/tony/tony.cpp b/engines/tony/tony.cpp index ece1904810..76f6cfcecb 100644 --- a/engines/tony/tony.cpp +++ b/engines/tony/tony.cpp @@ -162,7 +162,85 @@ OSystem::MutexRef csMusic; void TonyEngine::PlayMusic(int nChannel, const char *fn, int nFX, bool bLoop, int nSync) { - warning("TonyEngine::PlayMusic"); + warning("TODO: TonyEngine::PlayMusic"); + g_system->lockMutex(csMusic); + + if (nChannel < 4) + if (flipflop) + nChannel = nChannel + 1; + + switch (nFX) { + case 0: + case 1: + case 2: + m_stream[nChannel]->Stop(); + m_stream[nChannel]->UnloadFile(); + break; + + case 22: + break; + } + +#ifdef REFACTOR_ME + // Mette il path giusto + if (nChannel < 4) + GetDataDirectory(DD_MUSIC, path_buffer); + else + GetDataDirectory(DD_LAYER, path_buffer); + _splitpath(path_buffer,drive,dir,NULL,NULL); + _splitpath(fn,NULL,NULL,fname,ext); + _makepath(path_buffer,drive,dir,fname,ext); + + _makepath(path_buffer,drive,dir,fname,ext); + + if (nFX==22) // Sync a tempo + { + curChannel=nChannel; + strcpy(nextMusic, path_buffer); + nextLoop=bLoop; + nextSync=nSync; + if (flipflop) + nextChannel=nChannel-1; + else + nextChannel=nChannel+1; + DWORD id; + HANDLE hThread=CreateThread(NULL,10240,(LPTHREAD_START_ROUTINE)DoNextMusic,m_stream,0,&id); + SetThreadPriority(hThread,THREAD_PRIORITY_HIGHEST); + } + else if (nFX==44) // Cambia canale e lascia finire il primo + { + if (flipflop) + nextChannel=nChannel-1; + else + nextChannel=nChannel+1; + + m_stream[nextChannel]->Stop(); + m_stream[nextChannel]->UnloadFile(); +#ifndef DEMO + if (!m_stream[nextChannel]->LoadFile(path_buffer,FPCODEC_ADPCM,nSync)) + theGame.Abort(); +#else + m_stream[nextChannel]->LoadFile(path_buffer,FPCODEC_ADPCM,nSync); +#endif + m_stream[nextChannel]->SetLoop(bLoop); + m_stream[nextChannel]->Play(); + + flipflop = 1-flipflop; + } + else + { +#ifndef DEMO + if (!m_stream[nChannel]->LoadFile(path_buffer,FPCODEC_ADPCM,nSync)) + theGame.Abort(); +#else + m_stream[nChannel]->LoadFile(path_buffer,FPCODEC_ADPCM,nSync); +#endif + m_stream[nChannel]->SetLoop(bLoop); + m_stream[nChannel]->Play(); + } +#endif + + g_system->unlockMutex(csMusic); } void TonyEngine::PlaySFX(int nChannel, int nFX) { @@ -183,19 +261,40 @@ void TonyEngine::PlaySFX(int nChannel, int nFX) { } void TonyEngine::StopMusic(int nChannel) { - warning("TODO TonyEngine::StopMusic"); + g_system->lockMutex(csMusic); + + if (nChannel < 4) + m_stream[nChannel+flipflop]->Stop(); + else + m_stream[nChannel]->Stop(); + + g_system->unlockMutex(csMusic); } void TonyEngine::StopSFX(int nChannel) { - warning("TODO TonyEngine::StopSFX"); + m_sfx[nChannel]->Stop(); } void TonyEngine::PlayUtilSFX(int nChannel, int nFX) { - warning("TODO TonyEngine::PlayUtilSFX"); + if (m_utilSfx[nChannel]==NULL) + return; + + switch (nFX) { + case 0: + m_utilSfx[nChannel]->SetLoop(false); + break; + + case 1: + m_utilSfx[nChannel]->SetLoop(true); + break; + } + + m_utilSfx[nChannel]->SetVolume(52); + m_utilSfx[nChannel]->Play(); } void TonyEngine::StopUtilSFX(int nChannel) { - warning("TODO TonyEngine::StopUtilSFX"); + m_utilSfx[nChannel]->Stop(); } void TonyEngine::PreloadSFX(int nChannel, const char *fn) { diff --git a/engines/tony/tony.h b/engines/tony/tony.h index d8104e641b..69b54e8edb 100644 --- a/engines/tony/tony.h +++ b/engines/tony/tony.h @@ -36,7 +36,6 @@ #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" |