aboutsummaryrefslogtreecommitdiff
path: root/engines/tony
diff options
context:
space:
mode:
Diffstat (limited to 'engines/tony')
-rw-r--r--engines/tony/custom.cpp49
-rw-r--r--engines/tony/globals.cpp1
-rw-r--r--engines/tony/globals.h10
-rw-r--r--engines/tony/tony.cpp1
4 files changed, 55 insertions, 6 deletions
diff --git a/engines/tony/custom.cpp b/engines/tony/custom.cpp
index fcb304c623..3031fc342b 100644
--- a/engines/tony/custom.cpp
+++ b/engines/tony/custom.cpp
@@ -2052,12 +2052,39 @@ DECLARE_CUSTOM_FUNCTION(StartDialog)(CORO_PARAM, uint32 nDialog, uint32 nStartGr
*/
DECLARE_CUSTOM_FUNCTION(TakeOwnership)(CORO_PARAM, uint32 num, uint32, uint32, uint32) {
- // The event is operating as a mutex, so if the event is already set, wait until it's reset
- CoroScheduler.waitForSingleObject(coroParam, GLOBALS._mut[num], CORO_INFINITE);
+ CORO_BEGIN_CONTEXT;
+ CORO_END_CONTEXT(_ctx);
+
+ CORO_BEGIN_CODE(_ctx);
+
+ if (GLOBALS._mut[num]._ownerPid != (uint32)CoroScheduler.getCurrentPID()) {
+ // The mutex is currently owned by a different process.
+ // Wait for the event to be signalled, which means the mutex is free.
+ CORO_INVOKE_2(CoroScheduler.waitForSingleObject, GLOBALS._mut[num]._eventId, CORO_INFINITE);
+ GLOBALS._mut[num]._ownerPid = (uint32)CoroScheduler.getCurrentPID();
+ }
+
+ GLOBALS._mut[num]._lockCount++;
+
+ CORO_END_CODE;
}
DECLARE_CUSTOM_FUNCTION(ReleaseOwnership)(CORO_PARAM, uint32 num, uint32, uint32, uint32) {
- CoroScheduler.setEvent(GLOBALS._mut[num]);
+ if (!GLOBALS._mut[num]._lockCount) {
+ warning("ReleaseOwnership tried to release mutex %d, which isn't held", num);
+ return;
+ }
+
+ if (GLOBALS._mut[num]._ownerPid != (uint32)CoroScheduler.getCurrentPID())
+ error("ReleaseOwnership tried to release mutex %d, which is held by a different process", num);
+
+ GLOBALS._mut[num]._lockCount--;
+ if (!GLOBALS._mut[num]._lockCount) {
+ GLOBALS._mut[num]._ownerPid = 0;
+
+ // Signal the event, to wake up processes waiting for the lock.
+ CoroScheduler.setEvent(GLOBALS._mut[num]._eventId);
+ }
}
/*
@@ -2524,6 +2551,19 @@ ASSIGN(201, MustSkipIdleEnd);
END_CUSTOM_FUNCTION_MAP()
+void processKilledCallback(Common::PROCESS *p) {
+ for (uint i = 0; i < 10; i++)
+ if (GLOBALS._mut[i]._ownerPid == p->pid) {
+ // Handle scripts which don't call ReleaseOwnership, such as
+ // the one in loc37's vEnter when Tony is chasing the mouse.
+ debug(DEBUG_BASIC, "Force-releasing mutex %d after process died", i);
+
+ GLOBALS._mut[i]._ownerPid = 0;
+ GLOBALS._mut[i]._lockCount = 0;
+ CoroScheduler.setEvent(GLOBALS._mut[i]._eventId);
+ }
+}
+
void setupGlobalVars(RMTony *tony, RMPointer *ptr, RMGameBoxes *box, RMLocation *loc, RMInventory *inv, RMInput *input) {
GLOBALS._tony = tony;
GLOBALS._pointer = ptr;
@@ -2549,8 +2589,9 @@ void setupGlobalVars(RMTony *tony, RMPointer *ptr, RMGameBoxes *box, RMLocation
GLOBALS._bAlwaysDisplay = false;
int i;
+ CoroScheduler.setResourceCallback(processKilledCallback);
for (i = 0; i < 10; i++)
- GLOBALS._mut[i] = CoroScheduler.createEvent(false, true);
+ GLOBALS._mut[i]._eventId = CoroScheduler.createEvent(false, true);
for (i = 0; i < 200; i++)
GLOBALS._ambiance[i] = 0;
diff --git a/engines/tony/globals.cpp b/engines/tony/globals.cpp
index ba2698a50b..dd35d8c5ec 100644
--- a/engines/tony/globals.cpp
+++ b/engines/tony/globals.cpp
@@ -67,7 +67,6 @@ Globals::Globals() {
_curSoundEffect = 0;
_bFadeOutStop = false;
- Common::fill(&_mut[0], &_mut[10], 0);
_bSkipIdle = false;
_hSkipIdle = 0;
_lastMusic = 0;
diff --git a/engines/tony/globals.h b/engines/tony/globals.h
index 02bd79eee7..483ced1817 100644
--- a/engines/tony/globals.h
+++ b/engines/tony/globals.h
@@ -155,6 +155,14 @@ typedef CFCALL *LPCFCALL;
typedef LPCFCALL *LPLPCFCALL;
+struct CoroutineMutex {
+ CoroutineMutex() : _eventId(0), _ownerPid(0), _lockCount(0) { }
+
+ uint32 _eventId;
+ uint32 _ownerPid;
+ uint32 _lockCount;
+};
+
/****************************************************************************\
* Global variables
\****************************************************************************/
@@ -236,7 +244,7 @@ public:
RMTony::CharacterTalkType _nTonyNextTalkType;
RMPoint _startLocPos[256];
- uint32 _mut[10];
+ CoroutineMutex _mut[10];
bool _bSkipIdle;
uint32 _hSkipIdle;
diff --git a/engines/tony/tony.cpp b/engines/tony/tony.cpp
index b0ca074c16..b9d12beb11 100644
--- a/engines/tony/tony.cpp
+++ b/engines/tony/tony.cpp
@@ -89,6 +89,7 @@ TonyEngine::~TonyEngine() {
// Reset the coroutine scheduler
CoroScheduler.reset();
+ CoroScheduler.setResourceCallback(NULL);
delete _debugger;
}