diff options
Diffstat (limited to 'engines/hugo/schedule_v1w.cpp')
-rw-r--r-- | engines/hugo/schedule_v1w.cpp | 128 |
1 files changed, 128 insertions, 0 deletions
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 |