scummvm/engines/toltecs/movie.cpp
Benjamin Haisch 2eb6482b06 TOLTECS: - Fixed compilation after Fingolfin's latest series of commits
- Added a warning for the yet unimplemented palette transparency code
- Removed "debug" calls from script, they weren't that useful
- Removed unneccessary delete in the MoviePlayer
- Fixed the renderer (hopefully?)
2011-11-20 22:43:07 +01:00

271 lines
6.8 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 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.
*
*
*/
#include "common/events.h"
#include "common/keyboard.h"
#include "common/file.h"
#include "common/savefile.h"
#include "common/config-manager.h"
#include "base/plugins.h"
#include "base/version.h"
#include "sound/mixer.h"
#include "toltecs/toltecs.h"
#include "toltecs/movie.h"
#include "toltecs/palette.h"
#include "toltecs/resource.h"
#include "toltecs/screen.h"
#include "toltecs/script.h"
namespace Toltecs {
MoviePlayer::MoviePlayer(ToltecsEngine *vm) : _vm(vm) {
}
MoviePlayer::~MoviePlayer() {
}
void MoviePlayer::playMovie(uint resIndex) {
uint32 subtitleSlot;
byte moviePalette[768];
_vm->_isSaveAllowed = false;
memset(moviePalette, 0, sizeof(moviePalette));
_vm->_screen->finishTalkTextItems();
_vm->_screen->clearSprites();
_vm->_arc->openResource(resIndex);
subtitleSlot = kMaxScriptSlots - 1;
_frameCount = _vm->_arc->readUint32LE();
_chunkCount = _vm->_arc->readUint32LE();
// TODO: Figure out rest of the header
_vm->_arc->readUint32LE();
_vm->_arc->readUint32LE();
_framesPerSoundChunk = _vm->_arc->readUint32LE();
_vm->_arc->readUint32LE();
_vm->_sceneWidth = 640;
_vm->_sceneHeight = 400;
_vm->_cameraHeight = 400;
_vm->_cameraX = 0;
_vm->_cameraY = 0;
_audioStream = Audio::makeAppendableAudioStream(22050, Audio::Mixer::FLAG_UNSIGNED);
_vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, _audioStream);
_soundChunkFramesLeft = 0;
_lastPrefetchOfs = 0;
fetchAudioChunks();
uint32 lastTime = _vm->_mixer->getSoundElapsedTime(_audioStreamHandle);
while (_chunkCount--) {
byte chunkType;
uint32 chunkSize;
byte *chunkBuffer;
uint32 movieOffset;
chunkType = _vm->_arc->readByte();
chunkSize = _vm->_arc->readUint32LE();
debug(0, "chunkType = %d; chunkSize = %d", chunkType, chunkSize);
chunkBuffer = new byte[chunkSize];
_vm->_arc->read(chunkBuffer, chunkSize);
movieOffset = _vm->_arc->pos();
switch (chunkType) {
case 0: // image data
case 1:
unpackRle(chunkBuffer, _vm->_screen->_backScreen);
// TODO: Rework this
_vm->_screen->updateShakeScreen();
_vm->_screen->_fullRefresh = true;
_vm->updateInput();
_vm->updateScreen();
_soundChunkFramesLeft--;
if (_soundChunkFramesLeft <= _framesPerSoundChunk) {
fetchAudioChunks();
}
while (_vm->_mixer->getSoundElapsedTime(_audioStreamHandle) < lastTime + 111) {
g_system->delayMillis(0);
}
lastTime = _vm->_mixer->getSoundElapsedTime(_audioStreamHandle);
break;
case 2: // palette data
unpackPalette(chunkBuffer, moviePalette, 256, 3);
_vm->_palette->setFullPalette(moviePalette);
break;
//case 3: -- what is this type
case 4: // audio data
break;
case 5:
// TODO: Check if the text is a subtitle (last character == 0xFE).
// If so, don't show it if text display is disabled.
memcpy(_vm->_script->getSlotData(subtitleSlot), chunkBuffer, chunkSize);
_vm->_screen->updateTalkText(subtitleSlot, 0);
break;
case 6: // start/stop shakescreen effect
if (chunkBuffer[0] == 0xFF)
_vm->_screen->stopShakeScreen();
else
_vm->_screen->startShakeScreen(chunkBuffer[0]);
break;
case 7: // setup subtitle parameters
_vm->_screen->_talkTextY = READ_LE_UINT16(chunkBuffer + 0);
_vm->_screen->_talkTextX = READ_LE_UINT16(chunkBuffer + 2);
_vm->_screen->_talkTextFontColor = ((chunkBuffer[4] << 4) & 0xF0) | ((chunkBuffer[4] >> 4) & 0x0F);
debug(0, "_talkTextX = %d; _talkTextY = %d; _talkTextFontColor = %d",
_vm->_screen->_talkTextX, _vm->_screen->_talkTextY, _vm->_screen->_talkTextFontColor);
break;
case 8: // stop subtitles
_vm->_script->getSlotData(subtitleSlot)[0] = 0xFF;
_vm->_screen->finishTalkTextItems();
break;
default:
error("MoviePlayer::playMovie(%04X) Unknown chunk type %d at %08X", resIndex, chunkType, _vm->_arc->pos() - 5 - chunkSize);
}
delete[] chunkBuffer;
_vm->_arc->seek(movieOffset, SEEK_SET);
if (!handleInput())
break;
}
_audioStream->finish();
_vm->_mixer->stopHandle(_audioStreamHandle);
_vm->_arc->closeResource();
debug(0, "playMovie() done");
_vm->_isSaveAllowed = true;
}
void MoviePlayer::fetchAudioChunks() {
uint32 startOfs = _vm->_arc->pos();
uint32 chunkCount = _chunkCount;
uint prefetchChunkCount = 0;
if (_lastPrefetchOfs != 0)
_vm->_arc->seek(_lastPrefetchOfs, SEEK_SET);
while (chunkCount-- && prefetchChunkCount < _framesPerSoundChunk / 2) {
byte chunkType = _vm->_arc->readByte();
uint32 chunkSize = _vm->_arc->readUint32LE();
if (chunkType == 4) {
byte *chunkBuffer = new byte[chunkSize];
_vm->_arc->read(chunkBuffer, chunkSize);
_audioStream->queueBuffer(chunkBuffer, chunkSize);
chunkBuffer = NULL;
prefetchChunkCount++;
_soundChunkFramesLeft += _framesPerSoundChunk;
} else {
_vm->_arc->seek(chunkSize, SEEK_CUR);
}
}
_lastPrefetchOfs = _vm->_arc->pos();
_vm->_arc->seek(startOfs, SEEK_SET);
}
void MoviePlayer::unpackPalette(byte *source, byte *dest, int elemCount, int elemSize) {
int ofs = 0, size = elemCount * elemSize;
while (ofs < size) {
byte len;
len = *source++;
if (len == 0) {
len = *source++;
} else {
byte value = *source++;
memset(dest, value, len);
}
ofs += len;
dest += len;
}
}
void MoviePlayer::unpackRle(byte *source, byte *dest) {
int size = 256000;
while (size > 0) {
byte a = *source++;
byte b = *source++;
if (a == 0) {
dest += b;
size -= b;
} else {
memset(dest, b, a);
dest += a;
size -= a;
}
}
}
bool MoviePlayer::handleInput() {
Common::Event event;
Common::EventManager *eventMan = g_system->getEventManager();
while (eventMan->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_KEYDOWN:
if (event.kbd.keycode == Common::KEYCODE_ESCAPE)
return false;
break;
case Common::EVENT_LBUTTONDOWN:
case Common::EVENT_RBUTTONDOWN:
return false;
case Common::EVENT_QUIT:
_vm->quitGame();
return false;
break;
default:
break;
}
}
return !_vm->shouldQuit();
}
} // End of namespace Toltecs