From f621f6a5059ec619ae9ea1045548e62a27e99ab4 Mon Sep 17 00:00:00 2001 From: dhewg Date: Mon, 14 Feb 2011 01:12:40 +0100 Subject: [PATCH] SKY: get rid of timer based gfx updates on most platforms timers are implemented using threads. never ever make gfx updates from another thread other than the main one. seriously. replace the whole timer crap in sky with timestamp based updates. this fixes crashes when OpenGL is enabled (android included). needs more testing. --- engines/sky/intro.cpp | 14 ++++++-- engines/sky/screen.cpp | 78 +++++++++++++++++++++++++++--------------- engines/sky/screen.h | 6 ++-- engines/sky/sky.cpp | 14 +------- engines/sky/sky.h | 2 -- 5 files changed, 65 insertions(+), 49 deletions(-) diff --git a/engines/sky/intro.cpp b/engines/sky/intro.cpp index 129de9c1291..6455f3b15bc 100644 --- a/engines/sky/intro.cpp +++ b/engines/sky/intro.cpp @@ -644,6 +644,7 @@ Intro::Intro(Disk *disk, Screen *screen, MusicBase *music, Sound *sound, Text *t Intro::~Intro() { if (_skyScreen->sequenceRunning()) _skyScreen->stopSequence(); + free(_textBuf); free(_saveBuf); free(_bgBuf); @@ -658,6 +659,7 @@ bool Intro::doIntro(bool floppyIntro) { if (!escDelay(3000)) return false; + if (floppyIntro) _skyMusic->startMusic(1); @@ -817,6 +819,7 @@ bool Intro::floppyScrollFlirt() { bool Intro::commandFlirt(uint16 *&data) { _skyScreen->startSequence(*data++); + while ((*data != COMMANDEND) || _skyScreen->sequenceRunning()) { while ((_skyScreen->seqFramesLeft() < *data)) { data++; @@ -844,11 +847,13 @@ bool Intro::commandFlirt(uint16 *&data) { error("Unknown FLIRT command %X", command); } } + if (!escDelay(50)) { _skyScreen->stopSequence(); return false; } } + data++; // move pointer over "COMMANDEND" return true; } @@ -893,6 +898,7 @@ void Intro::restoreScreen() { bool Intro::escDelay(uint32 msecs) { Common::EventManager *eventMan = _system->getEventManager(); Common::Event event; + if (_relDelay == 0) // first call, init with system time _relDelay = (int32)_system->getMillis(); @@ -911,11 +917,13 @@ bool Intro::escDelay(uint32 msecs) { nDelay = _relDelay - _system->getMillis(); if (nDelay < 0) nDelay = 0; - else if (nDelay > 40) - nDelay = 40; + else if (nDelay > 10) + nDelay = 10; _system->delayMillis(nDelay); + _skyScreen->processSequence(); _system->updateScreen(); - } while (nDelay == 40); + } while (nDelay == 10); + return true; } diff --git a/engines/sky/screen.cpp b/engines/sky/screen.cpp index 76b4b24f511..ab4ba1eb2a6 100644 --- a/engines/sky/screen.cpp +++ b/engines/sky/screen.cpp @@ -86,7 +86,7 @@ Screen::Screen(OSystem *pSystem, Disk *pDisk, SkyCompact *skyCompact) { _system->getPaletteManager()->setPalette(tmpPal, 0, VGA_COLOURS); _currentPalette = 0; - _seqInfo.framesLeft = 0; + _seqInfo.nextFrame = _seqInfo.framesLeft = 0; _seqInfo.seqData = _seqInfo.seqDataPos = NULL; _seqInfo.running = false; } @@ -348,7 +348,7 @@ void Screen::fnFadeUp(uint32 palNum, uint32 scroll) { scrOldPtr += GAME_SCREEN_WIDTH; } showScreen(_scrollScreen); - waitForTimer(); + waitForTick(); } showScreen(_currentScreen); } else if (scroll == 321) { // scroll right (going left) @@ -364,7 +364,7 @@ void Screen::fnFadeUp(uint32 palNum, uint32 scroll) { scrOldPtr += GAME_SCREEN_WIDTH; } showScreen(_scrollScreen); - waitForTimer(); + waitForTick(); } showScreen(_currentScreen); } @@ -374,11 +374,39 @@ void Screen::fnFadeUp(uint32 palNum, uint32 scroll) { } } -void Screen::waitForTimer() { +void Screen::waitForTick() { + uint32 start = _system->getMillis(); + uint32 end = start + 20 - (start % 20); + uint32 remain; + Common::EventManager *eventMan = _system->getEventManager(); - _gotTick = false; - while (!_gotTick) { - Common::Event event; + Common::Event event; + + while (true) { + start = _system->getMillis(); + + if (start >= end) + return; + + while (eventMan->pollEvent(event)) + ; + + remain = end - start; + if (remain < 10) { + _system->delayMillis(remain); + return; + } + + _system->delayMillis(10); + } +} + +void Screen::waitForSequence() { + Common::EventManager *eventMan = _system->getEventManager(); + Common::Event event; + + while (_seqInfo.running) { + processSequence(); _system->delayMillis(10); while (eventMan->pollEvent(event)) @@ -386,25 +414,9 @@ void Screen::waitForTimer() { } } -void Screen::waitForSequence() { - Common::EventManager *eventMan = _system->getEventManager(); - while (_seqInfo.running) { - Common::Event event; - - _system->delayMillis(20); - while (eventMan->pollEvent(event)) - ; - } -} - -void Screen::handleTimer() { - _gotTick = true; - if (_seqInfo.running) - processSequence(); -} - void Screen::startSequence(uint16 fileNum) { _seqInfo.seqData = _skyDisk->loadFile(fileNum); + _seqInfo.nextFrame = _system->getMillis(); _seqInfo.framesLeft = _seqInfo.seqData[0]; _seqInfo.seqDataPos = _seqInfo.seqData + 1; _seqInfo.delay = SEQ_DELAY; @@ -414,6 +426,7 @@ void Screen::startSequence(uint16 fileNum) { void Screen::startSequenceItem(uint16 itemNum) { _seqInfo.seqData = (uint8 *)SkyEngine::fetchItem(itemNum); + _seqInfo.nextFrame = _system->getMillis(); _seqInfo.framesLeft = _seqInfo.seqData[0] - 1; _seqInfo.seqDataPos = _seqInfo.seqData + 1; _seqInfo.delay = SEQ_DELAY; @@ -423,21 +436,29 @@ void Screen::startSequenceItem(uint16 itemNum) { void Screen::stopSequence() { _seqInfo.running = false; - waitForTimer(); - waitForTimer(); - _seqInfo.framesLeft = 0; + waitForTick(); + waitForTick(); + _seqInfo.nextFrame = _seqInfo.framesLeft = 0; free(_seqInfo.seqData); _seqInfo.seqData = _seqInfo.seqDataPos = NULL; } void Screen::processSequence() { - uint32 screenPos = 0; + if (!_seqInfo.running) + return; + + if (_system->getMillis() < _seqInfo.nextFrame) + return; _seqInfo.delay--; if (_seqInfo.delay == 0) { _seqInfo.delay = SEQ_DELAY; + _seqInfo.nextFrame += 20 * SEQ_DELAY; + memset(_seqGrid, 0, 12 * 20); + uint32 screenPos = 0; + uint8 nrToSkip, nrToDo, cnt; do { do { @@ -445,6 +466,7 @@ void Screen::processSequence() { _seqInfo.seqDataPos++; screenPos += nrToSkip; } while (nrToSkip == 0xFF); + do { nrToDo = _seqInfo.seqDataPos[0]; _seqInfo.seqDataPos++; diff --git a/engines/sky/screen.h b/engines/sky/screen.h index e587958c7b4..048f5c1e3e3 100644 --- a/engines/sky/screen.h +++ b/engines/sky/screen.h @@ -75,6 +75,7 @@ public: void startSequenceItem(uint16 itemNum); void stopSequence(); bool sequenceRunning() { return _seqInfo.running; } + void processSequence(); void waitForSequence(); uint32 seqFramesLeft() { return _seqInfo.framesLeft; } uint8 *giveCurrent() { return _currentScreen; } @@ -105,14 +106,13 @@ private: uint32 _currentPalette; uint8 _seqGrid[20 * 12]; - bool volatile _gotTick; - void waitForTimer(); - void processSequence(); + void waitForTick(); uint8 *_gameGrid; uint8 *_currentScreen; uint8 *_scrollScreen; struct { + uint32 nextFrame; uint32 framesLeft; uint32 delay; uint8 *seqData; diff --git a/engines/sky/sky.cpp b/engines/sky/sky.cpp index 14d57465af0..c42bb6301ea 100644 --- a/engines/sky/sky.cpp +++ b/engines/sky/sky.cpp @@ -84,8 +84,6 @@ SkyEngine::SkyEngine(OSystem *syst) } SkyEngine::~SkyEngine() { - _timer->removeTimerProc(&timerHandler); - delete _skyLogic; delete _skySound; delete _skyMusic; @@ -207,6 +205,7 @@ Common::Error SkyEngine::go() { } _skyLogic->engine(); + _skyScreen->processSequence(); _skyScreen->recreate(); _skyScreen->spriteEngine(); if (_debugger->showGrid()) { @@ -300,9 +299,6 @@ Common::Error SkyEngine::init() { _skyLogic = new Logic(_skyCompact, _skyScreen, _skyDisk, _skyText, _skyMusic, _skyMouse, _skySound); _skyMouse->useLogicInstance(_skyLogic); - // initialize timer *after* _skyScreen has been initialized. - _timer->installTimerProc(&timerHandler, 1000000 / 50, this); //call 50 times per second - _skyControl = new Control(_saveFileMan, _skyScreen, _skyDisk, _skyMouse, _skyText, _skyMusic, _skyLogic, _skySound, _skyCompact, _system); _skyLogic->useControlInstance(_skyControl); @@ -386,14 +382,6 @@ void *SkyEngine::fetchItem(uint32 num) { return _itemList[num]; } -void SkyEngine::timerHandler(void *refCon) { - ((SkyEngine *)refCon)->gotTimerTick(); -} - -void SkyEngine::gotTimerTick() { - _skyScreen->handleTimer(); -} - void SkyEngine::delay(int32 amount) { Common::Event event; diff --git a/engines/sky/sky.h b/engines/sky/sky.h index 58c9d1de11f..29e7c9ab42a 100644 --- a/engines/sky/sky.h +++ b/engines/sky/sky.h @@ -121,8 +121,6 @@ protected: void initItemList(); void initVirgin(); - static void timerHandler(void *ptr); - void gotTimerTick(); void loadFixedItems(); };