mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-13 21:31:53 +00:00
Proper handling of BS2 cutscene lead-outs, plus some other minor fixes.
svn-id: r12907
This commit is contained in:
parent
2e7badd6dc
commit
55556c813c
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,21 +440,12 @@ void Sound::restoreMusicState(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void Sound::playLeadOut(uint8 *leadOut) {
|
||||
int i;
|
||||
void Sound::waitForLeadOut(void) {
|
||||
int i = getFxIndex(-1);
|
||||
|
||||
if (!leadOut)
|
||||
if (i == MAXFX)
|
||||
return;
|
||||
|
||||
playFx(0, leadOut, 0, 0, RDSE_FXLEADOUT);
|
||||
|
||||
i = getFxIndex(-1);
|
||||
|
||||
if (i == MAXFX) {
|
||||
warning("playLeadOut: Can't find lead-out sound handle");
|
||||
return;
|
||||
}
|
||||
|
||||
while (_fx[i]._handle.isActive()) {
|
||||
_vm->_graphics->updateDisplay();
|
||||
_vm->_system->delay_msecs(30);
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user