diff options
Diffstat (limited to 'engines/agos/event.cpp')
-rw-r--r-- | engines/agos/event.cpp | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/engines/agos/event.cpp b/engines/agos/event.cpp new file mode 100644 index 0000000000..4755dea987 --- /dev/null +++ b/engines/agos/event.cpp @@ -0,0 +1,376 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001 Ludvig Strigeus + * Copyright (C) 2001-2006 The ScummVM project + * + * 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/stdafx.h" + +#include "agos/agos.h" +#include "agos/intern.h" + +namespace Simon { + +void SimonEngine::addTimeEvent(uint timeout, uint subroutine_id) { + TimeEvent *te = (TimeEvent *)malloc(sizeof(TimeEvent)), *first, *last = NULL; + time_t cur_time; + + time(&cur_time); + + te->time = cur_time + timeout - _gameStoppedClock; + if (_clockStopped) + te->time -= ((uint32)time(NULL) - _clockStopped); + te->subroutine_id = subroutine_id; + + first = _firstTimeStruct; + while (first) { + if (te->time <= first->time) { + if (last) { + last->next = te; + te->next = first; + return; + } + te->next = _firstTimeStruct; + _firstTimeStruct = te; + return; + } + + last = first; + first = first->next; + } + + if (last) { + last->next = te; + te->next = NULL; + } else { + _firstTimeStruct = te; + te->next = NULL; + } +} + +void SimonEngine::delTimeEvent(TimeEvent *te) { + TimeEvent *cur; + + if (te == _pendingDeleteTimeEvent) + _pendingDeleteTimeEvent = NULL; + + if (te == _firstTimeStruct) { + _firstTimeStruct = te->next; + free(te); + return; + } + + cur = _firstTimeStruct; + if (cur == NULL) + error("delTimeEvent: none available"); + + for (;;) { + if (cur->next == NULL) + error("delTimeEvent: no such te"); + if (te == cur->next) { + cur->next = te->next; + free(te); + return; + } + cur = cur->next; + } +} + +void SimonEngine::invokeTimeEvent(TimeEvent *te) { + Subroutine *sub; + + _scriptVerb = 0; + + if (_runScriptReturn1) + return; + + sub = getSubroutineByID(te->subroutine_id); + if (sub != NULL) + startSubroutineEx(sub); + + _runScriptReturn1 = false; +} + +void SimonEngine::killAllTimers() { + TimeEvent *cur, *next; + + for (cur = _firstTimeStruct; cur; cur = next) { + next = cur->next; + delTimeEvent(cur); + } +} + +bool SimonEngine::kickoffTimeEvents() { + time_t cur_time; + TimeEvent *te; + bool result = false; + + if (_clockStopped) + return result; + + time(&cur_time); + cur_time -= _gameStoppedClock; + + while ((te = _firstTimeStruct) != NULL && te->time <= (uint32)cur_time) { + result = true; + _pendingDeleteTimeEvent = te; + invokeTimeEvent(te); + if (_pendingDeleteTimeEvent) { + _pendingDeleteTimeEvent = NULL; + delTimeEvent(te); + } + } + + return result; +} + +void SimonEngine::addVgaEvent(uint16 num, const byte *code_ptr, uint16 cur_sprite, uint16 curZoneNum, int32 param) { + VgaTimerEntry *vte; + + // When Simon talks to the Golum about stew in French version of + // Simon the Sorcerer 1 the code_ptr is at wrong location for + // sprite 200. This was a bug in the original game, which + // caused several glitches in this scene. + // We work around the problem by correcting the code_ptr for sprite + // 200 in this scene, if it is wrong. + if (getGameType() == GType_SIMON1 && _language == Common::FR_FRA && + (code_ptr - _vgaBufferPointers[curZoneNum].vgaFile1 == 4) && (cur_sprite == 200) && (curZoneNum == 2)) + code_ptr += 0x66; + + _lockWord |= 1; + + for (vte = _vgaTimerList; vte->delay; vte++) { + } + + vte->delay = num; + vte->script_pointer = code_ptr; + vte->sprite_id = cur_sprite; + vte->cur_vga_file = curZoneNum; + vte->param = param; + + _lockWord &= ~1; +} + +void SimonEngine::deleteVgaEvent(VgaTimerEntry * vte) { + _lockWord |= 1; + + if (vte + 1 <= _nextVgaTimerToProcess) { + _nextVgaTimerToProcess--; + } + + do { + memcpy(vte, vte + 1, sizeof(VgaTimerEntry)); + vte++; + } while (vte->delay); + + _lockWord &= ~1; +} + +void SimonEngine::processVgaEvents() { + VgaTimerEntry *vte = _vgaTimerList; + uint timer = (getGameType() == GType_FF) ? 5 : 1; + + _vgaTickCounter++; + + while (vte->delay) { + vte->delay -= timer; + if (vte->delay <= 0) { + uint16 curZoneNum = vte->cur_vga_file; + uint16 cur_sprite = vte->sprite_id; + const byte *script_ptr = vte->script_pointer; + int32 param = vte->param; + + _nextVgaTimerToProcess = vte + 1; + deleteVgaEvent(vte); + + if (getGameType() == GType_FF && script_ptr == NULL) { + panEvent(curZoneNum, cur_sprite, param); + } else if (getGameType() == GType_SIMON2 && script_ptr == NULL) { + scrollEvent(); + } else { + animateEvent(script_ptr, curZoneNum, cur_sprite); + } + vte = _nextVgaTimerToProcess; + } else { + vte++; + } + } +} + +void SimonEngine::animateEvent(const byte *code_ptr, uint16 curZoneNum, uint16 cur_sprite) { + VgaPointersEntry *vpe; + + _vgaCurSpriteId = cur_sprite; + + _vgaCurZoneNum = curZoneNum; + _zoneNumber = curZoneNum; + vpe = &_vgaBufferPointers[curZoneNum]; + + _curVgaFile1 = vpe->vgaFile1; + _curVgaFile2 = vpe->vgaFile2; + _curSfxFile = vpe->sfxFile; + + _vcPtr = code_ptr; + + runVgaScript(); +} + +void SimonEngine::panEvent(uint16 curZoneNum, uint16 cur_sprite, int32 param) { + _vgaCurSpriteId = cur_sprite; + _vgaCurZoneNum = curZoneNum; + + VgaSprite *vsp = findCurSprite(); + + param &= 0x10; + + int32 pan = (vsp->x - _scrollX + param) * 8 - 2560; + if (pan < -10000) + pan = -10000; + if (pan > 10000) + pan = 10000; + + //setSfxPan(param, pan); + + if (pan != 0) + addVgaEvent(10, NULL, _vgaCurSpriteId, _vgaCurZoneNum); /* pan event */ + debug(0, "panEvent: param %d pan %d", param, pan); +} + +void SimonEngine::scrollEvent() { + if (_scrollCount == 0) + return; + + if (getGameType() == GType_FF) { + if (_scrollCount < 0) { + if (_scrollFlag != -8) { + _scrollFlag = -8; + _scrollCount += 8; + } + } else { + if (_scrollFlag != 8) { + _scrollFlag = 8; + _scrollCount -= 8; + } + } + } else { + if (_scrollCount < 0) { + if (_scrollFlag != -1) { + _scrollFlag = -1; + if (++_scrollCount == 0) + return; + } + } else { + if (_scrollFlag != 1) { + _scrollFlag = 1; + if (--_scrollCount == 0) + return; + } + } + + addVgaEvent(6, NULL, 0, 0); /* scroll event */ + } +} + +void SimonEngine::timer_callback() { + if (_timer5 != 0) { + _syncFlag2 = true; + _timer5--; + } else { + timer_proc1(); + } +} + +void SimonEngine::timer_proc1() { + _timer4++; + + if (_lockWord & 0x80E9 || _lockWord & 2) + return; + + _syncCount++; + + _lockWord |= 2; + + if (!(_lockWord & 0x10)) { + if (getGameType() == GType_FF) { + _syncFlag2 ^= 1; + if (!_syncFlag2) { + processVgaEvents(); + } else { + // Double speed on Oracle + if (getBitFlag(99)) { + processVgaEvents(); + } else if (_scrollCount == 0) { + _lockWord &= ~2; + return; + } + } + } else { + processVgaEvents(); + processVgaEvents(); + _syncFlag2 ^= 1; + _cepeFlag ^= 1; + if (!_cepeFlag) + processVgaEvents(); + + if (_mouseHideCount != 0 && _syncFlag2) { + _lockWord &= ~2; + return; + } + } + } + + if (getGameType() == GType_FF) + _moviePlay->nextFrame(); + + animateSprites(); + if (_drawImagesDebug) + animateSpritesDebug(); + + if (_copyPartialMode == 1) { + fillBackFromFront(80, 46, 208 - 80, 94 - 46); + } + + if (_copyPartialMode == 2) { + if (getGameType() == GType_FF) { + fillFrontFromBack(0, 0, _screenWidth, _screenHeight); + } else { + fillFrontFromBack(176, 61, _screenWidth - 176, 134 - 61); + } + _copyPartialMode = 0; + } + + if (_updateScreen) { + if (getGameType() == GType_FF) { + if (!getBitFlag(78)) { + oracleLogo(); + } + if (getBitFlag(76)) { + swapCharacterLogo(); + } + } + handleMouseMoved(); + dx_update_screen_and_palette(); + _updateScreen = false; + } + + _lockWord &= ~2; +} + +} // End of namespace Simon |