aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sword1/animation.cpp8
-rw-r--r--sword2/driver/animation.cpp101
-rw-r--r--sword2/driver/animation.h8
-rw-r--r--sword2/driver/d_sound.cpp38
-rw-r--r--sword2/driver/d_sound.h2
5 files changed, 122 insertions, 35 deletions
diff --git a/sword1/animation.cpp b/sword1/animation.cpp
index 46d8c59006..73b88221a7 100644
--- a/sword1/animation.cpp
+++ b/sword1/animation.cpp
@@ -74,8 +74,14 @@ bool AnimationState::init(const char *basename) {
p = 0;
while (!feof(f)) {
- if (fscanf(f, "%i %i", &palettes[p].end, &palettes[p].cnt) != 2)
+ int end, cnt;
+
+ if (fscanf(f, "%i %i", &end, &cnt) != 2)
break;
+
+ palettes[p].end = (uint) end;
+ palettes[p].cnt = (uint) cnt;
+
for (i = 0; i < palettes[p].cnt; i++) {
int r, g, b;
fscanf(f, "%i", &r);
diff --git a/sword2/driver/animation.cpp b/sword2/driver/animation.cpp
index c20fb8498d..e54b76f0de 100644
--- a/sword2/driver/animation.cpp
+++ b/sword2/driver/animation.cpp
@@ -80,8 +80,14 @@ bool AnimationState::init(const char *name) {
p = 0;
while (!feof(f)) {
- if (fscanf(f, "%i %i", &palettes[p].end, &palettes[p].cnt) != 2)
+ int end, cnt;
+
+ if (fscanf(f, "%i %i", &end, &cnt) != 2)
break;
+
+ palettes[p].end = (uint) end;
+ palettes[p].cnt = (uint) cnt;
+
for (i = 0; i < palettes[p].cnt; i++) {
int r, g, b;
fscanf(f, "%i", &r);
@@ -410,6 +416,26 @@ bool AnimationState::decodeFrame() {
return false;
}
+MovieInfo MoviePlayer::_movies[] = {
+ { "carib", 222 },
+ { "escape", 187 },
+ { "eye", 248 },
+ { "finale", 1485 },
+ { "guard", 75 },
+ { "intro", 1800 },
+ { "jungle", 186 },
+ { "museum", 167 },
+ { "pablo", 75 },
+ { "pyramid", 60 },
+ { "quaram", 184 },
+ { "river", 656 },
+ { "sailing", 138 },
+ { "shaman", 788 },
+ { "stone1", 34 },
+ { "stone2", 282 },
+ { "stone3", 65 }
+};
+
void MoviePlayer::openTextObject(MovieTextObject *obj) {
if (obj->textSprite)
_vm->_graphics->createSurface(obj->textSprite, &_textSurface);
@@ -444,7 +470,7 @@ void MoviePlayer::drawTextObject(AnimationState *anim, MovieTextObject *obj) {
int32 MoviePlayer::play(const char *filename, MovieTextObject *text[], uint8 *musicOut) {
#ifdef USE_MPEG2
- int frameCounter = 0, textCounter = 0;
+ uint frameCounter = 0, textCounter = 0;
PlayingSoundHandle handle;
bool skipCutscene = false, textVisible = false;
uint32 flags = SoundMixer::FLAG_16BITS;
@@ -454,7 +480,7 @@ int32 MoviePlayer::play(const char *filename, MovieTextObject *text[], uint8 *mu
memcpy(oldPal, _vm->_graphics->_palCopy, 1024);
AnimationState *anim = new AnimationState(_vm);
-
+
if (!anim->init(filename)) {
delete anim;
// Missing Files? Use the old 'Narration Only' hack
@@ -468,6 +494,22 @@ int32 MoviePlayer::play(const char *filename, MovieTextObject *text[], uint8 *mu
flags |= SoundMixer::FLAG_LITTLE_ENDIAN;
#endif
+ int i;
+ uint leadOutFrame = (uint) -1;
+
+ for (i = 0; i < ARRAYSIZE(_movies); i++) {
+ if (scumm_stricmp(filename, _movies[i].name) == 0) {
+ if (_movies[i].frames >= 60)
+ leadOutFrame = _movies[i].frames - 60;
+ else
+ leadOutFrame = 0;
+ break;
+ }
+ }
+
+ if (i == ARRAYSIZE(_movies))
+ warning("Unknown movie, '%s'", filename);
+
while (anim->decodeFrame()) {
if (text && text[textCounter]) {
if (frameCounter == text[textCounter]->startFrame) {
@@ -495,6 +537,9 @@ int32 MoviePlayer::play(const char *filename, MovieTextObject *text[], uint8 *mu
frameCounter++;
+ if (frameCounter == leadOutFrame && musicOut)
+ _vm->_sound->playFx(0, musicOut, 0, 0, RDSE_FXLEADOUT);
+
#ifdef BACKEND_8BIT
_vm->_graphics->updateDisplay(true);
#else
@@ -512,6 +557,37 @@ int32 MoviePlayer::play(const char *filename, MovieTextObject *text[], uint8 *mu
}
+ if (!skipCutscene) {
+ // Sleep for one frame so that the last frame is displayed.
+ _vm->_system->delay_msecs(1000 / 12);
+ }
+
+#ifndef BACKEND_8BIT
+ // Most movies fade to black on their own, but not all of them. Since
+ // we may be hanging around in the cutscene player for a while longer,
+ // waiting for the lead-out sound to finish, paint the overlay black.
+
+ anim->clearDisplay();
+#else
+ _vm->_graphics->clearScene();
+ _vm->_graphics->setNeedFullRedraw();
+#endif
+
+ // If the speech is still playing, redraw the subtitles. At least in
+ // the English version this is most noticeable in the "carib" cutscene.
+
+ if (textVisible && handle.isActive())
+ drawTextObject(anim, text[textCounter]);
+
+ if (text)
+ closeTextObject(text[textCounter]);
+
+#ifndef BACKEND_8BIT
+ anim->updateDisplay();
+#else
+ _vm->_graphics->updateDisplay(true);
+#endif
+
// Wait for the voice to stop playing. This is to make sure
// that we don't cut off the speech in mid-sentence, and - even
// more importantly - that we don't free the sound buffer while
@@ -522,14 +598,9 @@ int32 MoviePlayer::play(const char *filename, MovieTextObject *text[], uint8 *mu
_vm->_system->delay_msecs(100);
}
- if (text)
- closeTextObject(text[textCounter]);
+ // Clear the screen again
#ifndef BACKEND_8BIT
- // Most movies fade to black on their own, but not all of them. Since
- // we may be hanging around in the cutscene player for a while longer,
- // waiting for the lead-out sound to finish, paint the overlay black.
-
anim->clearDisplay();
anim->updateDisplay();
#endif
@@ -537,13 +608,13 @@ int32 MoviePlayer::play(const char *filename, MovieTextObject *text[], uint8 *mu
_vm->_graphics->clearScene();
_vm->_graphics->setNeedFullRedraw();
- if (!skipCutscene)
- _vm->_sound->playLeadOut(musicOut);
-
_vm->_graphics->setPalette(0, 256, oldPal, RDPAL_INSTANT);
delete anim;
+ // Wait for the lead-out to stop, if there is any.
+ _vm->_sound->waitForLeadOut();
+
// Lead-in and lead-out music are, as far as I can tell, only used for
// the animated cut-scenes, so this seems like a good place to close
// both of them.
@@ -688,8 +759,10 @@ int32 MoviePlayer::playDummy(const char *filename, MovieTextObject *text[], uint
// FIXME: For now, only play the lead-out music for cutscenes
// that have subtitles.
- if (!skipCutscene)
- _vm->_sound->playLeadOut(musicOut);
+ if (!skipCutscene && musicOut) {
+ _vm->_sound->playFx(0, musicOut, 0, 0, RDSE_FXLEADOUT);
+ _vm->_sound->waitForLeadOut();
+ }
_vm->_graphics->setPalette(0, 256, oldPal, RDPAL_INSTANT);
}
diff --git a/sword2/driver/animation.h b/sword2/driver/animation.h
index f87e074c7e..25c4284f4c 100644
--- a/sword2/driver/animation.h
+++ b/sword2/driver/animation.h
@@ -54,7 +54,6 @@ typedef sequence_t mpeg2_sequence_t;
namespace Sword2 {
-
#ifdef BACKEND_8BIT
#define SQR(x) ((x) * (x))
#define SHIFT 3
@@ -135,11 +134,18 @@ private:
#endif
};
+struct MovieInfo {
+ char name[9];
+ uint frames;
+};
+
class MoviePlayer {
private:
Sword2Engine *_vm;
uint8 *_textSurface;
+ static struct MovieInfo _movies[];
+
void openTextObject(MovieTextObject *obj);
void closeTextObject(MovieTextObject *obj);
void drawTextObject(AnimationState *anim, MovieTextObject *obj);
diff --git a/sword2/driver/d_sound.cpp b/sword2/driver/d_sound.cpp
index 4277e525da..0d16c72969 100644
--- a/sword2/driver/d_sound.cpp
+++ b/sword2/driver/d_sound.cpp
@@ -252,11 +252,16 @@ bool MusicHandle::endOfData(void) const {
*/
bool Sound::getWavInfo(uint8 *data, WavInfo *wavInfo) {
+ uint32 wavLength;
+ uint32 offset;
+
if (READ_UINT32(data) != MKID('RIFF')) {
warning("getWavInfo: No 'RIFF' header");
return false;
}
+ wavLength = READ_LE_UINT32(data + 4) + 8;
+
if (READ_UINT32(data + 8) != MKID('WAVE')) {
warning("getWavInfo: No 'WAVE' header");
return false;
@@ -270,15 +275,21 @@ bool Sound::getWavInfo(uint8 *data, WavInfo *wavInfo) {
wavInfo->channels = READ_LE_UINT16(data + 22);
wavInfo->rate = READ_LE_UINT16(data + 24);
- data += READ_LE_UINT32(data + 16) + 20;
+ offset = READ_LE_UINT32(data + 16) + 20;
- if (READ_UINT32(data) != MKID('data')) {
- warning("getWavInfo: No 'data' header");
- return false;
+ // It's almost certainly a WAV file, but we still need to find its
+ // 'data' chunk.
+
+ while (READ_UINT32(data + offset) != MKID('data')) {
+ if (offset >= wavLength) {
+ warning("getWavInfo: Can't find 'data' chunk");
+ return false;
+ }
+ offset += (READ_LE_UINT32(data + offset + 4) + 8);
}
- wavInfo->samples = READ_LE_UINT32(data + 4);
- wavInfo->data = data + 8;
+ wavInfo->samples = READ_LE_UINT32(data + offset + 4);
+ wavInfo->data = data + offset + 8;
return true;
}
@@ -429,20 +440,11 @@ void Sound::restoreMusicState(void) {
}
}
-void Sound::playLeadOut(uint8 *leadOut) {
- int i;
+void Sound::waitForLeadOut(void) {
+ int i = getFxIndex(-1);
- if (!leadOut)
- return;
-
- playFx(0, leadOut, 0, 0, RDSE_FXLEADOUT);
-
- i = getFxIndex(-1);
-
- if (i == MAXFX) {
- warning("playLeadOut: Can't find lead-out sound handle");
+ if (i == MAXFX)
return;
- }
while (_fx[i]._handle.isActive()) {
_vm->_graphics->updateDisplay();
diff --git a/sword2/driver/d_sound.h b/sword2/driver/d_sound.h
index 8612bbefb0..19a3458510 100644
--- a/sword2/driver/d_sound.h
+++ b/sword2/driver/d_sound.h
@@ -131,7 +131,7 @@ public:
void stopMusic(void);
void saveMusicState(void);
void restoreMusicState(void);
- void playLeadOut(uint8 *leadOut);
+ void waitForLeadOut(void);
int32 streamCompMusic(const char *filename, uint32 musicId, bool looping);
int32 musicTimeRemaining(void);