mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-20 19:21:46 +00:00
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.
This commit is contained in:
parent
1e989c44ed
commit
f621f6a505
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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++;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -121,8 +121,6 @@ protected:
|
||||
void initItemList();
|
||||
|
||||
void initVirgin();
|
||||
static void timerHandler(void *ptr);
|
||||
void gotTimerTick();
|
||||
void loadFixedItems();
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user