mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-04 01:46:42 +00:00
879f6a43f5
("Waxworks crashing at Egypt Level 3, corrupting save file") The design for the timers is a bit sloppy, even the original interpreter often writes negative timeouts into the save files. We replicated this correctly, but treated these values as very large positives which effectively disabled the timers. The bug report is only about Waxworks, but I checked Elvira and i have the same absurd timer values in my old savegames there. It seems that the timers have little impact in most cases, but in Waxworks there is a timer that runs every 10 seconds which cleans up the items chain. And if that doesn't happen it will lead to invalid item handles, like in that bug ticket.
773 lines
17 KiB
C++
773 lines
17 KiB
C++
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "agos/agos.h"
|
|
#include "agos/animation.h"
|
|
#include "agos/debugger.h"
|
|
#include "agos/sound.h"
|
|
#include "agos/intern.h"
|
|
|
|
#include "common/events.h"
|
|
#include "common/system.h"
|
|
#include "common/textconsole.h"
|
|
|
|
#include "backends/audiocd/audiocd.h"
|
|
|
|
#include "gui/about.h"
|
|
|
|
#include "graphics/surface.h"
|
|
|
|
|
|
namespace AGOS {
|
|
|
|
void AGOSEngine::addTimeEvent(int32 timeout, uint16 subroutine_id) {
|
|
TimeEvent *te = (TimeEvent *)malloc(sizeof(TimeEvent)), *first, *last = nullptr;
|
|
uint32 cur_time = getTime();
|
|
|
|
if (getGameId() == GID_DIMP) {
|
|
timeout /= 2;
|
|
}
|
|
|
|
if ((int32)(cur_time + timeout - _gameStoppedClock) < 0) {
|
|
// This basically fixes a signed/unsigned bug. See comment in AGOSEngine_Elvira2::loadGame().
|
|
warning("AGOSEngine::addTimeEvent(): Invalid timer encountered (probably from an older savegame) - applying workaround");
|
|
timeout = 0;
|
|
}
|
|
|
|
te->time = cur_time + timeout - _gameStoppedClock;
|
|
if (getGameType() == GType_FF && _clockStopped)
|
|
te->time -= (getTime() - _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 = nullptr;
|
|
} else {
|
|
_firstTimeStruct = te;
|
|
te->next = nullptr;
|
|
}
|
|
}
|
|
|
|
void AGOSEngine::delTimeEvent(TimeEvent *te) {
|
|
TimeEvent *cur;
|
|
|
|
if (te == _pendingDeleteTimeEvent)
|
|
_pendingDeleteTimeEvent = nullptr;
|
|
|
|
if (te == _firstTimeStruct) {
|
|
_firstTimeStruct = te->next;
|
|
free(te);
|
|
return;
|
|
}
|
|
|
|
cur = _firstTimeStruct;
|
|
if (cur == nullptr)
|
|
error("delTimeEvent: none available");
|
|
|
|
for (;;) {
|
|
if (cur->next == nullptr)
|
|
error("delTimeEvent: no such te");
|
|
if (te == cur->next) {
|
|
cur->next = te->next;
|
|
free(te);
|
|
return;
|
|
}
|
|
cur = cur->next;
|
|
}
|
|
}
|
|
|
|
void AGOSEngine::invokeTimeEvent(TimeEvent *te) {
|
|
Subroutine *sub;
|
|
|
|
_scriptVerb = 0;
|
|
|
|
if (_runScriptReturn1)
|
|
return;
|
|
|
|
sub = getSubroutineByID(te->subroutine_id);
|
|
if (sub != nullptr)
|
|
startSubroutineEx(sub);
|
|
|
|
_runScriptReturn1 = false;
|
|
}
|
|
|
|
void AGOSEngine::killAllTimers() {
|
|
TimeEvent *cur, *next;
|
|
|
|
for (cur = _firstTimeStruct; cur; cur = next) {
|
|
next = cur->next;
|
|
delTimeEvent(cur);
|
|
}
|
|
_clickOnly = false;
|
|
}
|
|
|
|
bool AGOSEngine::kickoffTimeEvents() {
|
|
uint32 cur_time;
|
|
TimeEvent *te;
|
|
bool result = false;
|
|
|
|
if (getGameType() == GType_FF && _clockStopped)
|
|
return result;
|
|
|
|
cur_time = getTime() - _gameStoppedClock;
|
|
|
|
while ((te = _firstTimeStruct) != nullptr && te->time <= cur_time && !shouldQuit()) {
|
|
result = true;
|
|
_pendingDeleteTimeEvent = te;
|
|
invokeTimeEvent(te);
|
|
if (_pendingDeleteTimeEvent) {
|
|
_pendingDeleteTimeEvent = nullptr;
|
|
delTimeEvent(te);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool AGOSEngine::isVgaQueueEmpty() {
|
|
VgaTimerEntry *vte = _vgaTimerList;
|
|
bool result = false;
|
|
|
|
while (vte->delay) {
|
|
if (vte->zoneNum == _variableArray[999] && vte->id >= 100) {
|
|
result = true;
|
|
break;
|
|
}
|
|
vte++;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void AGOSEngine::haltAnimation() {
|
|
if (_videoLockOut & 0x10)
|
|
return;
|
|
|
|
_videoLockOut |= 0x10;
|
|
|
|
if (_displayFlag) {
|
|
displayScreen();
|
|
_displayFlag = 0;
|
|
}
|
|
}
|
|
|
|
void AGOSEngine::restartAnimation() {
|
|
if (!(_videoLockOut & 0x10))
|
|
return;
|
|
|
|
if (getGameType() != GType_PN) {
|
|
_window4Flag = 2;
|
|
setMoveRect(0, 0, 224, 127);
|
|
displayScreen();
|
|
}
|
|
|
|
_videoLockOut &= ~0x10;
|
|
}
|
|
|
|
void AGOSEngine::addVgaEvent(uint16 num, uint8 type, const byte *codePtr, uint16 curSprite, uint16 curZoneNum) {
|
|
VgaTimerEntry *vte;
|
|
|
|
_videoLockOut |= 1;
|
|
|
|
for (vte = _vgaTimerList; vte->delay; vte++) {
|
|
}
|
|
|
|
vte->delay = num;
|
|
vte->codePtr = codePtr;
|
|
vte->id = curSprite;
|
|
vte->zoneNum = curZoneNum;
|
|
vte->type = type;
|
|
|
|
_videoLockOut &= ~1;
|
|
}
|
|
|
|
void AGOSEngine::deleteVgaEvent(VgaTimerEntry * vte) {
|
|
_videoLockOut |= 1;
|
|
|
|
if (vte + 1 <= _nextVgaTimerToProcess) {
|
|
_nextVgaTimerToProcess--;
|
|
}
|
|
|
|
do {
|
|
memcpy(vte, vte + 1, sizeof(VgaTimerEntry));
|
|
vte++;
|
|
} while (vte->delay);
|
|
|
|
_videoLockOut &= ~1;
|
|
}
|
|
|
|
void AGOSEngine::processVgaEvents() {
|
|
VgaTimerEntry *vte = _vgaTimerList;
|
|
|
|
_vgaTickCounter++;
|
|
|
|
while (vte->delay) {
|
|
vte->delay -= _vgaBaseDelay;
|
|
if (vte->delay <= 0) {
|
|
uint16 curZoneNum = vte->zoneNum;
|
|
uint16 curSprite = vte->id;
|
|
const byte *script_ptr = vte->codePtr;
|
|
|
|
switch (vte->type) {
|
|
case ANIMATE_INT:
|
|
vte->delay = (getGameType() == GType_SIMON2) ? 5 : _frameCount;
|
|
animateSprites();
|
|
vte++;
|
|
break;
|
|
case ANIMATE_EVENT:
|
|
_nextVgaTimerToProcess = vte + 1;
|
|
deleteVgaEvent(vte);
|
|
animateEvent(script_ptr, curZoneNum, curSprite);
|
|
vte = _nextVgaTimerToProcess;
|
|
break;
|
|
case SCROLL_EVENT:
|
|
_nextVgaTimerToProcess = vte + 1;
|
|
deleteVgaEvent(vte);
|
|
scrollEvent();
|
|
vte = _nextVgaTimerToProcess;
|
|
break;
|
|
case PLAYER_DAMAGE_EVENT:
|
|
playerDamageEvent(vte, curZoneNum);
|
|
vte = _nextVgaTimerToProcess;
|
|
break;
|
|
case MONSTER_DAMAGE_EVENT:
|
|
monsterDamageEvent(vte, curZoneNum);
|
|
vte = _nextVgaTimerToProcess;
|
|
break;
|
|
default:
|
|
error("processVgaEvents: Unknown event type %d", vte->type);
|
|
}
|
|
} else {
|
|
vte++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void AGOSEngine::animateEvent(const byte *codePtr, uint16 curZoneNum, uint16 curSprite) {
|
|
VgaPointersEntry *vpe;
|
|
|
|
_vgaCurSpriteId = curSprite;
|
|
|
|
_vgaCurZoneNum = curZoneNum;
|
|
_zoneNumber = curZoneNum;
|
|
vpe = &_vgaBufferPointers[curZoneNum];
|
|
|
|
_curVgaFile1 = vpe->vgaFile1;
|
|
_curVgaFile2 = vpe->vgaFile2;
|
|
_curSfxFile = vpe->sfxFile;
|
|
_curSfxFileSize = vpe->sfxFileEnd - vpe->sfxFile;
|
|
|
|
_vcPtr = codePtr;
|
|
|
|
runVgaScript();
|
|
}
|
|
|
|
void AGOSEngine::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, SCROLL_EVENT, nullptr, 0, 0);
|
|
}
|
|
}
|
|
|
|
static const byte _image1[32] = {
|
|
0x3A, 0x37, 0x3B, 0x37,
|
|
0x3A, 0x3E, 0x3F, 0x3E,
|
|
0x37, 0x3F, 0x31, 0x3F,
|
|
0x37, 0x3F, 0x31, 0x3F,
|
|
0x3A, 0x3E, 0x3F, 0x3E,
|
|
0x3A, 0x37, 0x3B, 0x37,
|
|
};
|
|
|
|
static const byte _image2[32] = {
|
|
0x3A, 0x3A, 0x3B, 0x3A,
|
|
0x3A, 0x37, 0x3E, 0x37,
|
|
0x3A, 0x37, 0x3E, 0x37,
|
|
0x3A, 0x37, 0x3E, 0x37,
|
|
0x3A, 0x37, 0x3E, 0x37,
|
|
0x3A, 0x3A, 0x3B, 0x3A,
|
|
};
|
|
|
|
static const byte _image3[32] = {
|
|
0x3A, 0x32, 0x3B, 0x32,
|
|
0x3A, 0x39, 0x3F, 0x39,
|
|
0x32, 0x3F, 0x31, 0x3F,
|
|
0x32, 0x3F, 0x31, 0x3F,
|
|
0x3A, 0x39, 0x3F, 0x39,
|
|
0x3A, 0x32, 0x3B, 0x32,
|
|
};
|
|
|
|
static const byte _image4[32] = {
|
|
0x3A, 0x3A, 0x3B, 0x3A,
|
|
0x3A, 0x32, 0x39, 0x32,
|
|
0x3A, 0x32, 0x38, 0x32,
|
|
0x3A, 0x32, 0x38, 0x32,
|
|
0x3A, 0x32, 0x39, 0x32,
|
|
0x3A, 0x3A, 0x3B, 0x3A,
|
|
};
|
|
|
|
void AGOSEngine::drawStuff(const byte *src, uint xoffs) {
|
|
const uint8 y = (getPlatform() == Common::kPlatformAtariST) ? 132 : 135;
|
|
|
|
Graphics::Surface *screen = getBackendSurface();
|
|
byte *dst = (byte *)screen->getBasePtr(xoffs, y);
|
|
|
|
for (uint h = 0; h < 6; h++) {
|
|
memcpy(dst, src, 4);
|
|
src += 4;
|
|
dst += screen->pitch;
|
|
}
|
|
|
|
Common::Rect dirtyRect(xoffs, y, xoffs + 4, y + 6);
|
|
updateBackendSurface(&dirtyRect);
|
|
}
|
|
|
|
void AGOSEngine::playerDamageEvent(VgaTimerEntry * vte, uint dx) {
|
|
// Draws damage indicator gauge when player hit
|
|
_nextVgaTimerToProcess = vte + 1;
|
|
|
|
if (!_opcode177Var1) {
|
|
drawStuff(_image1, 4 + _opcode177Var2 * 4);
|
|
_opcode177Var2++;
|
|
if (_opcode177Var2 == dx) {
|
|
_opcode177Var1 = 1;
|
|
vte->delay = 16 - dx;
|
|
} else {
|
|
vte->delay = 1;
|
|
}
|
|
} else if (_opcode177Var2) {
|
|
_opcode177Var2--;
|
|
drawStuff(_image2, 4 + _opcode177Var2 * 4);
|
|
vte->delay = 3;
|
|
} else {
|
|
deleteVgaEvent(vte);
|
|
}
|
|
}
|
|
|
|
void AGOSEngine::monsterDamageEvent(VgaTimerEntry * vte, uint dx) {
|
|
// Draws damage indicator gauge when monster hit
|
|
_nextVgaTimerToProcess = vte + 1;
|
|
|
|
if (!_opcode178Var1) {
|
|
drawStuff(_image3, 275 + _opcode178Var2 * 4);
|
|
_opcode178Var2++;
|
|
if (_opcode178Var2 >= 10 || _opcode178Var2 == dx) {
|
|
_opcode178Var1 = 1;
|
|
vte->delay = 16 - dx;
|
|
} else {
|
|
vte->delay = 1;
|
|
}
|
|
} else if (_opcode178Var2) {
|
|
_opcode178Var2--;
|
|
drawStuff(_image4, 275 + _opcode178Var2 * 4);
|
|
vte->delay = 3;
|
|
} else {
|
|
deleteVgaEvent(vte);
|
|
}
|
|
}
|
|
|
|
void AGOSEngine::delay(uint amount) {
|
|
Common::Event event;
|
|
|
|
uint32 start = _system->getMillis();
|
|
uint32 cur = start;
|
|
uint this_delay, vgaPeriod;
|
|
|
|
_system->getAudioCDManager()->update();
|
|
|
|
vgaPeriod = (_fastMode) ? 10 : _vgaPeriod;
|
|
if (getGameType() == GType_PP && getGameId() != GID_DIMP) {
|
|
if (vgaPeriod == 15 && _variableArray[999] == 0)
|
|
vgaPeriod = 30;
|
|
}
|
|
|
|
_rnd.getRandomNumber(2);
|
|
|
|
do {
|
|
while (!_inCallBack && cur >= _lastVgaTick + vgaPeriod && !_pause) {
|
|
_lastVgaTick += vgaPeriod;
|
|
|
|
// don't get too many frames behind
|
|
if (cur >= _lastVgaTick + vgaPeriod * 2)
|
|
_lastVgaTick = cur;
|
|
|
|
_inCallBack = true;
|
|
timerProc();
|
|
_inCallBack = false;
|
|
}
|
|
|
|
while (_eventMan->pollEvent(event)) {
|
|
switch (event.type) {
|
|
case Common::EVENT_KEYDOWN:
|
|
if (event.kbd.keycode >= Common::KEYCODE_0 && event.kbd.keycode <= Common::KEYCODE_9
|
|
&& (event.kbd.hasFlags(Common::KBD_ALT) ||
|
|
event.kbd.hasFlags(Common::KBD_CTRL))) {
|
|
_saveLoadSlot = event.kbd.keycode - Common::KEYCODE_0;
|
|
|
|
// There is no save slot 0
|
|
if (_saveLoadSlot == 0)
|
|
_saveLoadSlot = 10;
|
|
|
|
memset(_saveLoadName, 0, sizeof(_saveLoadName));
|
|
Common::sprintf_s(_saveLoadName, "Quick %d", _saveLoadSlot);
|
|
_saveLoadType = (event.kbd.hasFlags(Common::KBD_ALT)) ? 1 : 2;
|
|
quickLoadOrSave();
|
|
} else if (event.kbd.hasFlags(Common::KBD_ALT)) {
|
|
if (event.kbd.keycode == Common::KEYCODE_u) {
|
|
dumpAllSubroutines();
|
|
} else if (event.kbd.keycode == Common::KEYCODE_i) {
|
|
dumpAllVgaImageFiles();
|
|
} else if (event.kbd.keycode == Common::KEYCODE_v) {
|
|
dumpAllVgaScriptFiles();
|
|
}
|
|
} else if (event.kbd.hasFlags(Common::KBD_CTRL)) {
|
|
if (event.kbd.keycode == Common::KEYCODE_a) {
|
|
GUI::AboutDialog aboutDialog;
|
|
aboutDialog.runModal();
|
|
} else if (event.kbd.keycode == Common::KEYCODE_f) {
|
|
_fastMode = !_fastMode;
|
|
}
|
|
}
|
|
|
|
if (getGameType() == GType_PP) {
|
|
if (event.kbd.hasFlags(Common::KBD_SHIFT))
|
|
_variableArray[41] = 0;
|
|
else
|
|
_variableArray[41] = 1;
|
|
}
|
|
|
|
_keyPressed = event.kbd;
|
|
break;
|
|
case Common::EVENT_MOUSEMOVE:
|
|
break;
|
|
case Common::EVENT_LBUTTONDOWN:
|
|
if (getGameType() == GType_FF)
|
|
setBitFlag(89, true);
|
|
_leftButtonDown = true;
|
|
_leftButton = 1;
|
|
break;
|
|
case Common::EVENT_LBUTTONUP:
|
|
if (getGameType() == GType_FF)
|
|
setBitFlag(89, false);
|
|
|
|
_leftButton = 0;
|
|
_leftButtonCount = 0;
|
|
_leftClick = true;
|
|
break;
|
|
case Common::EVENT_RBUTTONDOWN:
|
|
if (getGameType() == GType_FF)
|
|
setBitFlag(92, false);
|
|
_rightButtonDown = true;
|
|
break;
|
|
case Common::EVENT_RBUTTONUP:
|
|
_rightClick = true;
|
|
break;
|
|
case Common::EVENT_RETURN_TO_LAUNCHER:
|
|
case Common::EVENT_QUIT:
|
|
return;
|
|
case Common::EVENT_WHEELUP:
|
|
handleMouseWheelUp();
|
|
break;
|
|
case Common::EVENT_WHEELDOWN:
|
|
handleMouseWheelDown();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (_leftButton == 1)
|
|
_leftButtonCount++;
|
|
|
|
_system->getAudioCDManager()->update();
|
|
|
|
_system->updateScreen();
|
|
|
|
if (amount == 0)
|
|
break;
|
|
|
|
this_delay = _fastMode ? 1 : 20;
|
|
if (this_delay > amount)
|
|
this_delay = amount;
|
|
_system->delayMillis(this_delay);
|
|
|
|
cur = _system->getMillis();
|
|
} while (cur < start + amount && !shouldQuit());
|
|
}
|
|
|
|
#ifdef ENABLE_AGOS2
|
|
void AGOSEngine_DIMP::timerProc() {
|
|
_lastTickCount = _system->getMillis();
|
|
|
|
AGOSEngine_Feeble::timerProc();
|
|
dimpIdle();
|
|
}
|
|
|
|
void AGOSEngine_Feeble::timerProc() {
|
|
if (_videoLockOut & 0x80E9 || _videoLockOut & 2)
|
|
return;
|
|
|
|
_syncCount++;
|
|
|
|
_videoLockOut |= 2;
|
|
|
|
if (!(_videoLockOut & 0x10)) {
|
|
_syncFlag2 = !_syncFlag2;
|
|
if (!_syncFlag2) {
|
|
processVgaEvents();
|
|
} else {
|
|
// Double speed on Oracle
|
|
if (getGameType() == GType_FF && getBitFlag(99)) {
|
|
processVgaEvents();
|
|
} else if (_scrollCount == 0) {
|
|
_videoLockOut &= ~2;
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (getGameType() == GType_FF && _interactiveVideo) {
|
|
// Controls Omni TV videos
|
|
if (getBitFlag(42)) {
|
|
stopInteractiveVideo();
|
|
} else {
|
|
_moviePlayer->nextFrame();
|
|
}
|
|
}
|
|
|
|
animateSprites();
|
|
}
|
|
|
|
if (_displayFlag) {
|
|
if (getGameType() == GType_FF && !(getFeatures() & GF_DEMO)) {
|
|
if (!getBitFlag(78)) {
|
|
oracleLogo();
|
|
}
|
|
if (getBitFlag(76)) {
|
|
swapCharacterLogo();
|
|
}
|
|
}
|
|
handleMouseMoved();
|
|
displayScreen();
|
|
_displayFlag = 0;
|
|
}
|
|
|
|
_videoLockOut &= ~2;
|
|
}
|
|
#endif
|
|
|
|
void AGOSEngine_PN::timerProc() {
|
|
if (_videoLockOut & 0x80E9 || _videoLockOut & 2)
|
|
return;
|
|
|
|
_syncCount++;
|
|
|
|
_videoLockOut |= 2;
|
|
|
|
_sound->handleSoundQueue();
|
|
handleMouseMoved();
|
|
handleKeyboard();
|
|
|
|
if (!(_videoLockOut & 0x10)) {
|
|
if (_sampleWait) {
|
|
_vgaCurSpriteId = 0xFFFF;
|
|
vc15_sync();
|
|
_sampleWait = false;
|
|
}
|
|
if (_sampleEnd) {
|
|
_vgaCurSpriteId = 0xFFFE;
|
|
vc15_sync();
|
|
_sampleEnd = false;
|
|
}
|
|
|
|
processVgaEvents();
|
|
processVgaEvents();
|
|
_cepeFlag = !_cepeFlag;
|
|
if (!_cepeFlag)
|
|
processVgaEvents();
|
|
}
|
|
|
|
if (_displayFlag) {
|
|
displayScreen();
|
|
_displayFlag = 0;
|
|
}
|
|
|
|
_videoLockOut &= ~2;
|
|
}
|
|
|
|
void AGOSEngine::timerProc() {
|
|
if (_videoLockOut & 0x80E9 || _videoLockOut & 2)
|
|
return;
|
|
|
|
_syncCount++;
|
|
|
|
_videoLockOut |= 2;
|
|
|
|
handleMouseMoved();
|
|
|
|
if (!(_videoLockOut & 0x10)) {
|
|
processVgaEvents();
|
|
processVgaEvents();
|
|
_cepeFlag = !_cepeFlag;
|
|
if (!_cepeFlag)
|
|
processVgaEvents();
|
|
}
|
|
|
|
if (_displayFlag) {
|
|
displayScreen();
|
|
_displayFlag = 0;
|
|
}
|
|
|
|
_videoLockOut &= ~2;
|
|
}
|
|
|
|
#ifdef ENABLE_AGOS2
|
|
void AGOSEngine_DIMP::dimpIdle() {
|
|
int z, n;
|
|
|
|
_iconToggleCount++;
|
|
if (_iconToggleCount == 30) {
|
|
if ((_variableArray[110] < 3) || (_variableArray[111] < 3) || (_variableArray[112] < 3)) {
|
|
_voiceCount++;
|
|
if (_voiceCount == 50) {
|
|
if (!getBitFlag(14) && !getBitFlag(11) && !getBitFlag(13)) {
|
|
loadSoundFile("Whistle.WAV");
|
|
z = 0;
|
|
while (z == 0) {
|
|
n = _rnd.getRandomNumber(2);
|
|
switch (n) {
|
|
default:
|
|
case(0):
|
|
if (_variableArray[110] > 2)
|
|
break;
|
|
n = _rnd.getRandomNumber(6);
|
|
switch (n) {
|
|
default:
|
|
case(0): loadSoundFile("And01.wav");break;
|
|
case(1): loadSoundFile("And02.wav");break;
|
|
case(2): loadSoundFile("And03.wav");break;
|
|
case(3): loadSoundFile("And04.wav");break;
|
|
case(4): loadSoundFile("And05.wav");break;
|
|
case(5): loadSoundFile("And06.wav");break;
|
|
case(6): loadSoundFile("And07.wav");break;
|
|
}
|
|
z = 1;
|
|
break;
|
|
case(1):
|
|
if (_variableArray[111] > 2)
|
|
break;
|
|
n = _rnd.getRandomNumber(6);
|
|
switch (n) {
|
|
default:
|
|
case(0): loadSoundFile("And08.wav");break;
|
|
case(1): loadSoundFile("And09.wav");break;
|
|
case(2): loadSoundFile("And0a.wav");break;
|
|
case(3): loadSoundFile("And0b.wav");break;
|
|
case(4): loadSoundFile("And0c.wav");break;
|
|
case(5): loadSoundFile("And0d.wav");break;
|
|
case(6): loadSoundFile("And0e.wav");break;
|
|
}
|
|
z = 1;
|
|
break;
|
|
case(2):
|
|
if (_variableArray[112] > 2)
|
|
break;
|
|
n = _rnd.getRandomNumber(4);
|
|
switch (n) {
|
|
default:
|
|
case(0): loadSoundFile("And0f.wav");break;
|
|
case(1): loadSoundFile("And0g.wav");break;
|
|
case(2): loadSoundFile("And0h.wav");break;
|
|
case(3): loadSoundFile("And0i.wav");break;
|
|
case(4): loadSoundFile("And0j.wav");break;
|
|
}
|
|
z = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
_voiceCount = 0;
|
|
}
|
|
} else {
|
|
_voiceCount = 48;
|
|
}
|
|
_iconToggleCount = 0;
|
|
}
|
|
|
|
if (_variableArray[121] == 0) {
|
|
_variableArray[121]++;
|
|
_startSecondCount = _lastTickCount;
|
|
}
|
|
if (((_lastTickCount - _startSecondCount) / 1000) != _tSecondCount) {
|
|
if (_startSecondCount != 0) {
|
|
uint32 x = (_variableArray[123] * 65536) + _variableArray[122] + ((_lastTickCount - _startSecondCount) / 1000) - _tSecondCount;
|
|
_variableArray[122] = (uint16)(x % 65536);
|
|
_variableArray[123] = (uint16)(x / 65536);
|
|
_tSecondCount = (_lastTickCount - _startSecondCount) / 1000;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
} // End of namespace AGOS
|