aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorArnaud Boutonné2010-10-26 21:16:16 +0000
committerArnaud Boutonné2010-10-26 21:16:16 +0000
commitc4d4277807f5990102817ade9d558b700013ebc3 (patch)
tree4a9c5fbb3a0156fb7a0a6f76cf1df8324ded6b3b /engines
parentbd7d9965e9f2048a53e7fe9668d0c2a05cf2fc81 (diff)
downloadscummvm-rg350-c4d4277807f5990102817ade9d558b700013ebc3.tar.gz
scummvm-rg350-c4d4277807f5990102817ade9d558b700013ebc3.tar.bz2
scummvm-rg350-c4d4277807f5990102817ade9d558b700013ebc3.zip
HUGO: Add specific schedulers for each DOS version.
This fixes intro (and game) in H3 DOS, general game behavior in H2 Dos. H1 Dos is still broken. svn-id: r53858
Diffstat (limited to 'engines')
-rw-r--r--engines/hugo/object_v1d.cpp3
-rw-r--r--engines/hugo/object_v2d.cpp3
-rw-r--r--engines/hugo/object_v3d.cpp8
-rw-r--r--engines/hugo/schedule.cpp134
-rw-r--r--engines/hugo/schedule.h18
-rw-r--r--engines/hugo/schedule_v1d.cpp87
-rw-r--r--engines/hugo/schedule_v1w.cpp128
-rw-r--r--engines/hugo/schedule_v2d.cpp4
-rw-r--r--engines/hugo/schedule_v3d.cpp2
9 files changed, 288 insertions, 99 deletions
diff --git a/engines/hugo/object_v1d.cpp b/engines/hugo/object_v1d.cpp
index 2ad4134a72..b2801d14c1 100644
--- a/engines/hugo/object_v1d.cpp
+++ b/engines/hugo/object_v1d.cpp
@@ -42,6 +42,7 @@
#include "hugo/route.h"
#include "hugo/util.h"
#include "hugo/parser.h"
+#include "hugo/schedule.h"
namespace Hugo {
@@ -104,6 +105,8 @@ void ObjectHandler_v1d::updateImages() {
}
}
+ _vm->_scheduler->waitForRefresh();
+
// Cycle any animating objects
for (int i = 0; i < num_objs; i++) {
object_t *obj = &_objects[objindex[i]];
diff --git a/engines/hugo/object_v2d.cpp b/engines/hugo/object_v2d.cpp
index 11146de0b1..3a0e367261 100644
--- a/engines/hugo/object_v2d.cpp
+++ b/engines/hugo/object_v2d.cpp
@@ -42,6 +42,7 @@
#include "hugo/route.h"
#include "hugo/util.h"
#include "hugo/parser.h"
+#include "hugo/schedule.h"
namespace Hugo {
@@ -104,6 +105,8 @@ void ObjectHandler_v2d::updateImages() {
}
}
+ _vm->_scheduler->waitForRefresh();
+
// Cycle any animating objects
for (int i = 0; i < num_objs; i++) {
object_t *obj = &_objects[objindex[i]];
diff --git a/engines/hugo/object_v3d.cpp b/engines/hugo/object_v3d.cpp
index aee373b26e..42476ce379 100644
--- a/engines/hugo/object_v3d.cpp
+++ b/engines/hugo/object_v3d.cpp
@@ -91,7 +91,7 @@ void ObjectHandler_v3d::moveObjects() {
switch (obj->seqNumb) {
case 4:
if (!obj->vx) { // Got 4 directions
- if (obj->vx != obj->oldvx) { // vx just stopped
+ if (obj->vx != obj->oldvx) { // vx just stopped
if (dy >= 0)
obj->currImagePtr = obj->seqList[DOWN].seqPtr;
else
@@ -119,7 +119,7 @@ void ObjectHandler_v3d::moveObjects() {
obj->cycling = CYCLE_FORWARD;
} else {
obj->cycling = NOT_CYCLING;
- _vm->boundaryCollision(obj); // Must have got hero!
+ _vm->boundaryCollision(obj); // Must have got hero!
}
obj->oldvx = obj->vx;
obj->oldvy = obj->vy;
@@ -180,7 +180,7 @@ void ObjectHandler_v3d::moveObjects() {
int y2 = obj->y + currImage->y2; // Bottom edge
if ((obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING))
- _vm->clearBoundary(x1, x2, y2); // Clear our own boundary
+ _vm->clearBoundary(x1, x2, y2); // Clear our own boundary
// Allowable motion wrt boundary
int dx = _vm->deltaX(x1, x2, obj->vx, y2);
@@ -198,7 +198,7 @@ void ObjectHandler_v3d::moveObjects() {
}
if ((obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING))
- _vm->storeBoundary(x1, x2, y2); // Re-store our own boundary
+ _vm->storeBoundary(x1, x2, y2); // Re-store our own boundary
obj->x += dx; // Update object position
obj->y += dy;
diff --git a/engines/hugo/schedule.cpp b/engines/hugo/schedule.cpp
index 6dd326a630..a72b337ffe 100644
--- a/engines/hugo/schedule.cpp
+++ b/engines/hugo/schedule.cpp
@@ -78,8 +78,8 @@ event_t *Scheduler::getQueue() {
return resEvent;
}
-void Scheduler::insertActionList(uint16 actIndex) {
// Call Insert_action for each action in the list supplied
+void Scheduler::insertActionList(uint16 actIndex) {
debugC(1, kDebugSchedule, "insertActionList(%d)", actIndex);
if (_vm->_actListArr[actIndex]) {
@@ -88,8 +88,8 @@ void Scheduler::insertActionList(uint16 actIndex) {
}
}
-void Scheduler::decodeString(char *line) {
// Decode a string
+void Scheduler::decodeString(char *line) {
debugC(1, kDebugSchedule, "decodeString(%s)", line);
static const char *cypher = getCypher();
@@ -99,29 +99,42 @@ void Scheduler::decodeString(char *line) {
debugC(1, kDebugSchedule, "result : %s", line);
}
-// This is the scheduler which runs every tick. It examines the event queue
-// for any events whose time has come. It dequeues these events and performs
-// the action associated with the event, returning it to the free queue
-void Scheduler::runScheduler() {
- debugC(6, kDebugSchedule, "runScheduler");
-
- status_t &gameStatus = _vm->getGameStatus();
- event_t *curEvent = _headEvent; // The earliest event
+// Return system time in ticks. A tick is 1/TICKS_PER_SEC mS
+uint32 Scheduler::getWinTicks() {
+ debugC(3, kDebugSchedule, "getTicks");
- while (curEvent && curEvent->time <= gameStatus.tick) // While mature events found
- curEvent = doAction(curEvent); // Perform the action (returns next_p)
- gameStatus.tick++; // Accessed elsewhere via getTicks()
+ return _vm->getGameStatus().tick;
}
-uint32 Scheduler::getTicks() {
// Return system time in ticks. A tick is 1/TICKS_PER_SEC mS
- debugC(3, kDebugSchedule, "getTicks");
+// If update FALSE, simply return last known time
+// Note that this is real time unless a processing cycle takes longer than
+// a real tick, in which case the system tick is simply incremented
+uint32 Scheduler::getDosTicks(bool updateFl) {
+ debugC(5, kDebugSchedule, "getTicks");
- return _vm->getGameStatus().tick;
+ static uint32 tick = 0; // Current system time in ticks
+ static uint32 t_old = 0; // The previous wall time in ticks
+
+ uint32 t_now; // Current wall time in ticks
+
+ if (!updateFl)
+ return(tick);
+
+ if (t_old == 0)
+ t_old = (uint32) floor((double) (g_system->getMillis() * TPS / 1000));
+ /* Calculate current wall time in ticks */
+ t_now = g_system->getMillis() * TPS / 1000 ;
+
+ if ((t_now - t_old) > 0) {
+ t_old = t_now;
+ tick++;
+ }
+ return(tick);
}
-void Scheduler::processBonus(int bonusIndex) {
// Add indecated bonus to score if not added already
+void Scheduler::processBonus(int bonusIndex) {
debugC(1, kDebugSchedule, "processBonus(%d)", bonusIndex);
if (!_vm->_points[bonusIndex].scoredFl) {
@@ -172,78 +185,11 @@ void Scheduler::newScreen(int screenIndex) {
_vm->_screen->initNewScreenDisplay();
}
-// Write the event queue to the file with handle f
-// Note that we convert all the event structure ptrs to indexes
-// using -1 for NULL. We can't convert the action ptrs to indexes
-// so we save address of first dummy action ptr to compare on restore.
-void Scheduler::saveEvents(Common::WriteStream *f) {
- debugC(1, kDebugSchedule, "saveEvents()");
-
- uint32 curTime = getTicks();
- event_t saveEventArr[kMaxEvents]; // Convert event ptrs to indexes
-
- // Convert event ptrs to indexes
- for (int16 i = 0; i < kMaxEvents; i++) {
- event_t *wrkEvent = &_events[i];
- saveEventArr[i] = *wrkEvent;
- saveEventArr[i].prevEvent = (wrkEvent->prevEvent == 0) ? (event_t *) - 1 : (event_t *)(wrkEvent->prevEvent - _events);
- saveEventArr[i].nextEvent = (wrkEvent->nextEvent == 0) ? (event_t *) - 1 : (event_t *)(wrkEvent->nextEvent - _events);
- }
-
- int16 freeIndex = (_freeEvent == 0) ? -1 : _freeEvent - _events;
- int16 headIndex = (_headEvent == 0) ? -1 : _headEvent - _events;
- int16 tailIndex = (_tailEvent == 0) ? -1 : _tailEvent - _events;
-
- f->write(&curTime, sizeof(curTime));
- f->write(&freeIndex, sizeof(freeIndex));
- f->write(&headIndex, sizeof(headIndex));
- f->write(&tailIndex, sizeof(tailIndex));
- f->write(saveEventArr, sizeof(saveEventArr));
-}
-
-// Restore the event list from file with handle f
-void Scheduler::restoreEvents(Common::SeekableReadStream *f) {
- debugC(1, kDebugSchedule, "restoreEvents");
-
- uint32 saveTime;
- int16 freeIndex; // Free list index
- int16 headIndex; // Head of list index
- int16 tailIndex; // Tail of list index
- event_t savedEvents[kMaxEvents]; // Convert event ptrs to indexes
-
- f->read(&saveTime, sizeof(saveTime)); // time of save
- f->read(&freeIndex, sizeof(freeIndex));
- f->read(&headIndex, sizeof(headIndex));
- f->read(&tailIndex, sizeof(tailIndex));
- f->read(savedEvents, sizeof(savedEvents));
-
- event_t *wrkEvent;
- // Restore events indexes to pointers
- for (int i = 0; i < kMaxEvents; i++) {
- wrkEvent = &savedEvents[i];
- _events[i] = *wrkEvent;
- _events[i].prevEvent = (wrkEvent->prevEvent == (event_t *) - 1) ? (event_t *)0 : &_events[(size_t)wrkEvent->prevEvent ];
- _events[i].nextEvent = (wrkEvent->nextEvent == (event_t *) - 1) ? (event_t *)0 : &_events[(size_t)wrkEvent->nextEvent ];
- }
- _freeEvent = (freeIndex == -1) ? 0 : &_events[freeIndex];
- _headEvent = (headIndex == -1) ? 0 : &_events[headIndex];
- _tailEvent = (tailIndex == -1) ? 0 : &_events[tailIndex];
-
- // Adjust times to fit our time
- uint32 curTime = getTicks();
- wrkEvent = _headEvent; // The earliest event
- while (wrkEvent) { // While mature events found
- wrkEvent->time = wrkEvent->time - saveTime + curTime;
- wrkEvent = wrkEvent->nextEvent;
- }
-}
-
-void Scheduler::restoreScreen(int screenIndex) {
// Transition to a new screen as follows:
// 1. Set the new screen (in the hero object and any carried objects)
// 2. Read in the screen files for the new screen
// 3. Initialise prompt line and status line
-
+void Scheduler::restoreScreen(int screenIndex) {
debugC(1, kDebugSchedule, "restoreScreen(%d)", screenIndex);
// 1. Set the new screen in the hero object and any being carried
@@ -256,4 +202,22 @@ void Scheduler::restoreScreen(int screenIndex) {
_vm->_screen->initNewScreenDisplay();
}
+// Wait (if necessary) for next synchronizing tick
+// Slow machines won't make it by the end of tick, so will just plod on
+// at their own speed, not waiting here, but free running.
+// Note: DOS Versions only
+void Scheduler::waitForRefresh(void) {
+ debugC(1, kDebugSchedule, "waitForRefresh()");
+
+ static uint32 timeout = 0;
+ uint32 t;
+
+ if (timeout == 0)
+ timeout = getDosTicks(true);
+
+ while ((t = getDosTicks(true)) < timeout)
+ ;
+ timeout = ++t;
+}
+
} // End of namespace Hugo
diff --git a/engines/hugo/schedule.h b/engines/hugo/schedule.h
index c74c0cb640..e6eb5d7947 100644
--- a/engines/hugo/schedule.h
+++ b/engines/hugo/schedule.h
@@ -52,16 +52,18 @@ public:
virtual ~Scheduler();
virtual void insertAction(act *action) = 0;
+ virtual void restoreEvents(Common::SeekableReadStream *f) = 0;
+ virtual void runScheduler() = 0;
+ virtual void saveEvents(Common::WriteStream *f) = 0;
void initEventQueue();
void insertActionList(uint16 actIndex);
void decodeString(char *line);
- void runScheduler();
- uint32 getTicks();
+ uint32 getWinTicks();
+ uint32 getDosTicks(bool updateFl);
+ void waitForRefresh(void);
void processBonus(int bonusIndex);
void newScreen(int screenIndex);
- void restoreEvents(Common::SeekableReadStream *f);
- void saveEvents(Common::WriteStream *f);
void restoreScreen(int screenIndex);
protected:
@@ -91,6 +93,9 @@ public:
virtual const char *getCypher();
virtual void insertAction(act *action);
+ virtual void restoreEvents(Common::SeekableReadStream *f);
+ virtual void saveEvents(Common::WriteStream *f);
+ virtual void runScheduler();
protected:
virtual void delQueue(event_t *curEvent);
virtual event_t *doAction(event_t *curEvent);
@@ -124,7 +129,10 @@ public:
~Scheduler_v1w();
virtual event_t *doAction(event_t *curEvent);
+ void insertAction(act *action);
+ void restoreEvents(Common::SeekableReadStream *f);
+ void runScheduler();
+ void saveEvents(Common::WriteStream *f);
};
} // End of namespace Hugo
-
#endif //HUGO_SCHEDULE_H
diff --git a/engines/hugo/schedule_v1d.cpp b/engines/hugo/schedule_v1d.cpp
index ac85463939..09bfc2294b 100644
--- a/engines/hugo/schedule_v1d.cpp
+++ b/engines/hugo/schedule_v1d.cpp
@@ -88,7 +88,7 @@ void Scheduler_v1d::insertAction(act *action) {
curEvent->localActionFl = true; // Rest are for current screen only
- curEvent->time = action->a0.timer + getTicks(); // Convert rel to abs time
+ curEvent->time = action->a0.timer + getDosTicks(false); // Convert rel to abs time
// Now find the place to insert the event
if (!_tailEvent) { // Empty queue
@@ -165,7 +165,7 @@ event_t *Scheduler_v1d::doAction(event_t *curEvent) {
insertActionList(action->a3.actFailIndex);
#endif
- // HACK: As the answer is not read, currently it's always considered correct
+ // HACK: As the answer is not read, currently it's always considered correct
insertActionList(action->a3.actPassIndex);
break;
}
@@ -320,4 +320,87 @@ event_t *Scheduler_v1d::doAction(event_t *curEvent) {
return wrkEvent; // Return next event ptr
}
}
+
+// Write the event queue to the file with handle f
+// Note that we convert all the event structure ptrs to indexes
+// using -1 for NULL. We can't convert the action ptrs to indexes
+// so we save address of first dummy action ptr to compare on restore.
+void Scheduler_v1d::saveEvents(Common::WriteStream *f) {
+ debugC(1, kDebugSchedule, "saveEvents()");
+
+ uint32 curTime = getDosTicks(false);
+ event_t saveEventArr[kMaxEvents]; // Convert event ptrs to indexes
+
+ // Convert event ptrs to indexes
+ for (int16 i = 0; i < kMaxEvents; i++) {
+ event_t *wrkEvent = &_events[i];
+ saveEventArr[i] = *wrkEvent;
+ saveEventArr[i].prevEvent = (wrkEvent->prevEvent == 0) ? (event_t *) - 1 : (event_t *)(wrkEvent->prevEvent - _events);
+ saveEventArr[i].nextEvent = (wrkEvent->nextEvent == 0) ? (event_t *) - 1 : (event_t *)(wrkEvent->nextEvent - _events);
+ }
+
+ int16 freeIndex = (_freeEvent == 0) ? -1 : _freeEvent - _events;
+ int16 headIndex = (_headEvent == 0) ? -1 : _headEvent - _events;
+ int16 tailIndex = (_tailEvent == 0) ? -1 : _tailEvent - _events;
+
+ f->write(&curTime, sizeof(curTime));
+ f->write(&freeIndex, sizeof(freeIndex));
+ f->write(&headIndex, sizeof(headIndex));
+ f->write(&tailIndex, sizeof(tailIndex));
+ f->write(saveEventArr, sizeof(saveEventArr));
+}
+
+// Restore the event list from file with handle f
+void Scheduler_v1d::restoreEvents(Common::SeekableReadStream *f) {
+ debugC(1, kDebugSchedule, "restoreEvents");
+
+ uint32 saveTime;
+ int16 freeIndex; // Free list index
+ int16 headIndex; // Head of list index
+ int16 tailIndex; // Tail of list index
+ event_t savedEvents[kMaxEvents]; // Convert event ptrs to indexes
+
+ f->read(&saveTime, sizeof(saveTime)); // time of save
+ f->read(&freeIndex, sizeof(freeIndex));
+ f->read(&headIndex, sizeof(headIndex));
+ f->read(&tailIndex, sizeof(tailIndex));
+ f->read(savedEvents, sizeof(savedEvents));
+
+ event_t *wrkEvent;
+ // Restore events indexes to pointers
+ for (int i = 0; i < kMaxEvents; i++) {
+ wrkEvent = &savedEvents[i];
+ _events[i] = *wrkEvent;
+ _events[i].prevEvent = (wrkEvent->prevEvent == (event_t *) - 1) ? (event_t *)0 : &_events[(size_t)wrkEvent->prevEvent ];
+ _events[i].nextEvent = (wrkEvent->nextEvent == (event_t *) - 1) ? (event_t *)0 : &_events[(size_t)wrkEvent->nextEvent ];
+ }
+ _freeEvent = (freeIndex == -1) ? 0 : &_events[freeIndex];
+ _headEvent = (headIndex == -1) ? 0 : &_events[headIndex];
+ _tailEvent = (tailIndex == -1) ? 0 : &_events[tailIndex];
+
+ // Adjust times to fit our time
+ uint32 curTime = getDosTicks(false);
+ wrkEvent = _headEvent; // The earliest event
+ while (wrkEvent) { // While mature events found
+ wrkEvent->time = wrkEvent->time - saveTime + curTime;
+ wrkEvent = wrkEvent->nextEvent;
+ }
+}
+
+// This is the scheduler which runs every tick. It examines the event queue
+// for any events whose time has come. It dequeues these events and performs
+// the action associated with the event, returning it to the free queue
+void Scheduler_v1d::runScheduler() {
+ debugC(6, kDebugSchedule, "runScheduler");
+
+ uint32 ticker; // The time now, in ticks
+ event_t *curEvent; // Event ptr
+
+ ticker = getDosTicks(false);
+
+ curEvent = _headEvent; // The earliest event
+ while (curEvent && curEvent->time <= ticker) // While mature events found
+ curEvent = doAction(curEvent); // Perform the action (returns next_p)
+}
+
} // End of namespace Hugo
diff --git a/engines/hugo/schedule_v1w.cpp b/engines/hugo/schedule_v1w.cpp
index 93deaa6b6b..34eff0447f 100644
--- a/engines/hugo/schedule_v1w.cpp
+++ b/engines/hugo/schedule_v1w.cpp
@@ -350,4 +350,132 @@ event_t *Scheduler_v1w::doAction(event_t *curEvent) {
return wrkEvent; // Return next event ptr
}
}
+
+// Write the event queue to the file with handle f
+// Note that we convert all the event structure ptrs to indexes
+// using -1 for NULL. We can't convert the action ptrs to indexes
+// so we save address of first dummy action ptr to compare on restore.
+void Scheduler_v1w::saveEvents(Common::WriteStream *f) {
+ debugC(1, kDebugSchedule, "saveEvents()");
+
+ uint32 curTime = getWinTicks();
+ event_t saveEventArr[kMaxEvents]; // Convert event ptrs to indexes
+
+ // Convert event ptrs to indexes
+ for (int16 i = 0; i < kMaxEvents; i++) {
+ event_t *wrkEvent = &_events[i];
+ saveEventArr[i] = *wrkEvent;
+ saveEventArr[i].prevEvent = (wrkEvent->prevEvent == 0) ? (event_t *) - 1 : (event_t *)(wrkEvent->prevEvent - _events);
+ saveEventArr[i].nextEvent = (wrkEvent->nextEvent == 0) ? (event_t *) - 1 : (event_t *)(wrkEvent->nextEvent - _events);
+ }
+
+ int16 freeIndex = (_freeEvent == 0) ? -1 : _freeEvent - _events;
+ int16 headIndex = (_headEvent == 0) ? -1 : _headEvent - _events;
+ int16 tailIndex = (_tailEvent == 0) ? -1 : _tailEvent - _events;
+
+ f->write(&curTime, sizeof(curTime));
+ f->write(&freeIndex, sizeof(freeIndex));
+ f->write(&headIndex, sizeof(headIndex));
+ f->write(&tailIndex, sizeof(tailIndex));
+ f->write(saveEventArr, sizeof(saveEventArr));
+}
+
+// Restore the event list from file with handle f
+void Scheduler_v1w::restoreEvents(Common::SeekableReadStream *f) {
+ debugC(1, kDebugSchedule, "restoreEvents");
+
+ uint32 saveTime;
+ int16 freeIndex; // Free list index
+ int16 headIndex; // Head of list index
+ int16 tailIndex; // Tail of list index
+ event_t savedEvents[kMaxEvents]; // Convert event ptrs to indexes
+
+ f->read(&saveTime, sizeof(saveTime)); // time of save
+ f->read(&freeIndex, sizeof(freeIndex));
+ f->read(&headIndex, sizeof(headIndex));
+ f->read(&tailIndex, sizeof(tailIndex));
+ f->read(savedEvents, sizeof(savedEvents));
+
+ event_t *wrkEvent;
+ // Restore events indexes to pointers
+ for (int i = 0; i < kMaxEvents; i++) {
+ wrkEvent = &savedEvents[i];
+ _events[i] = *wrkEvent;
+ _events[i].prevEvent = (wrkEvent->prevEvent == (event_t *) - 1) ? (event_t *)0 : &_events[(size_t)wrkEvent->prevEvent ];
+ _events[i].nextEvent = (wrkEvent->nextEvent == (event_t *) - 1) ? (event_t *)0 : &_events[(size_t)wrkEvent->nextEvent ];
+ }
+ _freeEvent = (freeIndex == -1) ? 0 : &_events[freeIndex];
+ _headEvent = (headIndex == -1) ? 0 : &_events[headIndex];
+ _tailEvent = (tailIndex == -1) ? 0 : &_events[tailIndex];
+
+ // Adjust times to fit our time
+ uint32 curTime = getWinTicks();
+ wrkEvent = _headEvent; // The earliest event
+ while (wrkEvent) { // While mature events found
+ wrkEvent->time = wrkEvent->time - saveTime + curTime;
+ wrkEvent = wrkEvent->nextEvent;
+ }
+}
+
+void Scheduler_v1w::insertAction(act *action) {
+ debugC(1, kDebugSchedule, "insertAction() - Action type A%d", action->a0.actType);
+
+ // First, get and initialise the event structure
+ event_t *curEvent = getQueue();
+ curEvent->action = action;
+ switch (action->a0.actType) { // Assign whether local or global
+ case AGSCHEDULE:
+ curEvent->localActionFl = false; // Lasts over a new screen
+ break;
+ default:
+ curEvent->localActionFl = true; // Rest are for current screen only
+ break;
+ }
+
+ curEvent->time = action->a0.timer + getWinTicks(); // Convert rel to abs time
+
+ // Now find the place to insert the event
+ if (!_tailEvent) { // Empty queue
+ _tailEvent = _headEvent = curEvent;
+ curEvent->nextEvent = curEvent->prevEvent = 0;
+ } else {
+ event_t *wrkEvent = _tailEvent; // Search from latest time back
+ bool found = false;
+
+ while (wrkEvent && !found) {
+ if (wrkEvent->time <= curEvent->time) { // Found if new event later
+ found = true;
+ if (wrkEvent == _tailEvent) // New latest in list
+ _tailEvent = curEvent;
+ else
+ wrkEvent->nextEvent->prevEvent = curEvent;
+ curEvent->nextEvent = wrkEvent->nextEvent;
+ wrkEvent->nextEvent = curEvent;
+ curEvent->prevEvent = wrkEvent;
+ }
+ wrkEvent = wrkEvent->prevEvent;
+ }
+
+ if (!found) { // Must be earliest in list
+ _headEvent->prevEvent = curEvent; // So insert as new head
+ curEvent->nextEvent = _headEvent;
+ curEvent->prevEvent = 0;
+ _headEvent = curEvent;
+ }
+ }
+}
+
+// This is the scheduler which runs every tick. It examines the event queue
+// for any events whose time has come. It dequeues these events and performs
+// the action associated with the event, returning it to the free queue
+void Scheduler_v1w::runScheduler() {
+ debugC(6, kDebugSchedule, "runScheduler");
+
+ status_t &gameStatus = _vm->getGameStatus();
+ event_t *curEvent = _headEvent; // The earliest event
+
+ while (curEvent && curEvent->time <= gameStatus.tick) // While mature events found
+ curEvent = doAction(curEvent); // Perform the action (returns next_p)
+ gameStatus.tick++; // Accessed elsewhere via getTicks()
+}
} // End of namespace Hugo
diff --git a/engines/hugo/schedule_v2d.cpp b/engines/hugo/schedule_v2d.cpp
index 3c4c71ddc2..2735bc4cf4 100644
--- a/engines/hugo/schedule_v2d.cpp
+++ b/engines/hugo/schedule_v2d.cpp
@@ -101,7 +101,7 @@ void Scheduler_v2d::insertAction(act *action) {
break;
}
- curEvent->time = action->a0.timer + getTicks(); // Convert rel to abs time
+ curEvent->time = action->a0.timer + getDosTicks(false); // Convert rel to abs time
// Now find the place to insert the event
if (!_tailEvent) { // Empty queue
@@ -134,10 +134,10 @@ void Scheduler_v2d::insertAction(act *action) {
}
}
-event_t *Scheduler_v2d::doAction(event_t *curEvent) {
// This function performs the action in the event structure pointed to by p
// It dequeues the event and returns it to the free list. It returns a ptr
// to the next action in the list, except special case of NEW_SCREEN
+event_t *Scheduler_v2d::doAction(event_t *curEvent) {
debugC(1, kDebugSchedule, "doAction - Event action type : %d", curEvent->action->a0.actType);
status_t &gameStatus = _vm->getGameStatus();
diff --git a/engines/hugo/schedule_v3d.cpp b/engines/hugo/schedule_v3d.cpp
index 5623ad3fc5..cc449ba8c4 100644
--- a/engines/hugo/schedule_v3d.cpp
+++ b/engines/hugo/schedule_v3d.cpp
@@ -57,10 +57,10 @@ const char *Scheduler_v3d::getCypher() {
return "Copyright 1992, Gray Design Associates";
}
-event_t *Scheduler_v3d::doAction(event_t *curEvent) {
// This function performs the action in the event structure pointed to by p
// It dequeues the event and returns it to the free list. It returns a ptr
// to the next action in the list, except special case of NEW_SCREEN
+event_t *Scheduler_v3d::doAction(event_t *curEvent) {
debugC(1, kDebugSchedule, "doAction - Event action type : %d", curEvent->action->a0.actType);
status_t &gameStatus = _vm->getGameStatus();