|
|
@@ -32,18 +32,26 @@ namespace BladeRunner { |
|
|
|
|
|
bool VQAPlayer::open(const Common::String &name) { |
|
|
_s = _vm->getResourceStream(name); |
|
|
if (!_s) |
|
|
if (!_s) { |
|
|
return false; |
|
|
} |
|
|
|
|
|
if(!_decoder.loadStream(_s)) { |
|
|
if (!_decoder.loadStream(_s)) { |
|
|
delete _s; |
|
|
_s = nullptr; |
|
|
return false; |
|
|
} |
|
|
|
|
|
_hasAudio = _decoder.hasAudio(); |
|
|
if (_hasAudio) |
|
|
if (_hasAudio) { |
|
|
_audioStream = Audio::makeQueuingAudioStream(_decoder.frequency(), false); |
|
|
} |
|
|
|
|
|
if (_loopInitial >= 0) { |
|
|
setLoop(_loopInitial, _repeatsCountInitial, 2, nullptr, nullptr); |
|
|
} else { |
|
|
setBeginAndEndFrame(0, _decoder.numFrames() - 1, 0, 0, nullptr, nullptr); |
|
|
} |
|
|
|
|
|
return true; |
|
|
} |
|
|
@@ -57,19 +65,19 @@ void VQAPlayer::close() { |
|
|
int VQAPlayer::update() { |
|
|
uint32 now = 60 * _vm->_system->getMillis(); |
|
|
|
|
|
if (_curFrame == -1) { |
|
|
_curFrame = 0; |
|
|
if (_curFrame >= 0) { |
|
|
_decoder.readPacket(_curFrame); |
|
|
if (_frameCurrent == -1) { |
|
|
_frameCurrent = 0; |
|
|
if (_frameCurrent >= 0) { |
|
|
_decoder.readPacket(_frameCurrent); |
|
|
if (_hasAudio) |
|
|
queueAudioFrame(_decoder.decodeAudioFrame()); |
|
|
_surface = _decoder.decodeVideoFrame(); |
|
|
_zBuffer = _decoder.decodeZBuffer(); |
|
|
} |
|
|
|
|
|
_decodedFrame = calcNextFrame(_curFrame); |
|
|
if (_decodedFrame >= 0) { |
|
|
_decoder.readPacket(_decodedFrame); |
|
|
_frameDecoded = calcNextFrame(_frameCurrent); |
|
|
if (_frameDecoded >= 0) { |
|
|
_decoder.readPacket(_frameDecoded); |
|
|
if (_hasAudio) |
|
|
queueAudioFrame(_decoder.decodeAudioFrame()); |
|
|
} |
|
|
@@ -80,25 +88,25 @@ int VQAPlayer::update() { |
|
|
} |
|
|
|
|
|
_nextFrameTime = now + 60000 / 15; |
|
|
return _curFrame; |
|
|
return _frameCurrent; |
|
|
} |
|
|
|
|
|
if (now >= _nextFrameTime) { |
|
|
_curFrame = _decodedFrame; |
|
|
if (_curFrame >= 0) { |
|
|
_frameCurrent = _frameDecoded; |
|
|
if (_frameCurrent >= 0) { |
|
|
_surface = _decoder.decodeVideoFrame(); |
|
|
_zBuffer = _decoder.decodeZBuffer(); |
|
|
} |
|
|
|
|
|
_decodedFrame = calcNextFrame(_curFrame); |
|
|
if (_decodedFrame >= 0) { |
|
|
_decoder.readPacket(_decodedFrame); |
|
|
_frameDecoded = calcNextFrame(_frameCurrent); |
|
|
if (_frameDecoded >= 0) { |
|
|
_decoder.readPacket(_frameDecoded); |
|
|
if (_hasAudio) |
|
|
queueAudioFrame(_decoder.decodeAudioFrame()); |
|
|
} |
|
|
|
|
|
_nextFrameTime += 60000 / 15; |
|
|
return _curFrame; |
|
|
return _frameCurrent; |
|
|
} |
|
|
|
|
|
_surface = nullptr; |
|
|
@@ -121,21 +129,58 @@ void VQAPlayer::updateLights(Lights *lights) { |
|
|
_decoder.decodeLights(lights); |
|
|
} |
|
|
|
|
|
bool VQAPlayer::setLoop(int loop, int unknown, int loopMode, void(*callback)(void*, int, int), void *callbackData) { |
|
|
bool VQAPlayer::setLoop(int loop, int repeatsCount, int loopMode, void (*callback)(void *, int, int), void *callbackData) { |
|
|
debug("VQAPlayer::setBeginAndEndFrameFromLoop(%i, %i, %i, %p, %p), streamLoaded = %i", loop, repeatsCount, loopMode, (void*)callback, callbackData, _s != nullptr); |
|
|
if (_s == nullptr) { |
|
|
_loopInitial = loop; |
|
|
_repeatsCountInitial = repeatsCount; |
|
|
return true; |
|
|
} |
|
|
|
|
|
int begin, end; |
|
|
if (!_decoder.getLoopBeginAndEndFrame(loop, &begin, &end)) { |
|
|
return false; |
|
|
} |
|
|
if (setBeginAndEndFrame(begin, end, repeatsCount, loopMode, callback, callbackData)) { |
|
|
_loop = loop; |
|
|
return true; |
|
|
} |
|
|
return false; |
|
|
} |
|
|
|
|
|
bool VQAPlayer::setBeginAndEndFrame(int begin, int end, int repeatsCount, int loopMode, void (*callback)(void *, int, int), void *callbackData) { |
|
|
debug("VQAPlayer::setBeginAndEndFrame(%i, %i, %i, %i, %p, %p), streamLoaded = %i", begin, end, repeatsCount, loopMode, (void*)callback, callbackData, _s != nullptr); |
|
|
|
|
|
if (repeatsCount < 0) { |
|
|
repeatsCount = -1; |
|
|
} |
|
|
|
|
|
_curLoop = loop; |
|
|
_loopBegin = begin; |
|
|
_loopEnd = end; |
|
|
if (_repeatsCount == 0 && loopMode == 1) { |
|
|
loopMode = 2; |
|
|
} |
|
|
|
|
|
//TODO: there is code in original game which deals with changing loop at start of loop, is it nescesarry? loc_46EA04 |
|
|
|
|
|
_frameBegin = begin; |
|
|
|
|
|
if (loopMode == 1) { |
|
|
_repeatsCountQueued = repeatsCount; |
|
|
_frameEndQueued = end; |
|
|
} else if (loopMode == 2) { |
|
|
_repeatsCount = repeatsCount; |
|
|
_frameEnd = end; |
|
|
_frameCurrent = begin; |
|
|
//TODO: extract this to seek function |
|
|
_decoder.readPacket(_frameCurrent); |
|
|
_frameDecoded = _frameCurrent; |
|
|
_nextFrameTime = 60 * _vm->_system->getMillis(); |
|
|
} else if (loopMode == 0) { |
|
|
_repeatsCount = repeatsCount; |
|
|
} |
|
|
|
|
|
_callbackLoopEnded = callback; |
|
|
_callbackData = callbackData; |
|
|
|
|
|
// warning("\t\t\tActive Loop: %d - %d\n", begin, end); |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
@@ -155,23 +200,45 @@ int VQAPlayer::getLoopEndFrame(int loop) { |
|
|
return end; |
|
|
} |
|
|
|
|
|
int VQAPlayer::calcNextFrame(int frame) const { |
|
|
if (frame < 0) |
|
|
int VQAPlayer::calcNextFrame(int frame) { |
|
|
//TODO: needs a slight refactoring, because it is not only calculating the next frame |
|
|
if (frame < 0) { |
|
|
return -3; |
|
|
} |
|
|
|
|
|
int frameNext = frame + 1; |
|
|
|
|
|
if (_curLoop != -1 && frame >= _loopEnd) { |
|
|
frame = _loopBegin; |
|
|
if (_callbackLoopEnded != nullptr) { |
|
|
_callbackLoopEnded(_callbackData, 0, _curLoop); |
|
|
if ((_repeatsCount > 0 || _repeatsCount == -1) && (frameNext > _frameEnd)) { |
|
|
int loopEndQueued = _frameEndQueued; |
|
|
if (_frameEndQueued != -1) { |
|
|
_frameEnd = _frameEndQueued; |
|
|
_frameEndQueued = -1; |
|
|
} |
|
|
if (frameNext != _frameBegin) { |
|
|
frameNext = _frameBegin; |
|
|
} |
|
|
|
|
|
if (loopEndQueued == -1) { |
|
|
if (_repeatsCount != -1) { |
|
|
_repeatsCount--; |
|
|
} |
|
|
//callback for repeat, it is not used in the blade runner |
|
|
} else { |
|
|
_repeatsCount = _repeatsCountQueued; |
|
|
_repeatsCountQueued = -1; |
|
|
|
|
|
if (_callbackLoopEnded != nullptr) { |
|
|
_callbackLoopEnded(_callbackData, 0, _loop); |
|
|
} |
|
|
} |
|
|
} else { |
|
|
frame++; |
|
|
} |
|
|
|
|
|
if (frame == _decoder.numFrames()) |
|
|
frame = -3; |
|
|
//TODO: original game is using end of loop instead of count of frames |
|
|
if (frameNext == _decoder.numFrames()) { |
|
|
return -3; |
|
|
} |
|
|
|
|
|
return frame; |
|
|
return frameNext; |
|
|
} |
|
|
|
|
|
void VQAPlayer::queueAudioFrame(Audio::AudioStream *audioStream) { |
|
|
|