From 98a8e88f61e871096fe979c2d9a27c2053aa38ca Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Thu, 8 Feb 2007 21:55:37 +0000 Subject: Instead of pre-rendering all subtitles and pre-loading all sounds for a movie cutscene, render the text and play the speech when needed. It probably won't play as nicely from CD now, but using less memory seems more important to me. svn-id: r25428 --- engines/sword2/animation.cpp | 200 +++++++++++++++++++++++++------------------ engines/sword2/animation.h | 68 ++++++++------- engines/sword2/anims.cpp | 127 --------------------------- engines/sword2/function.cpp | 32 +++---- engines/sword2/logic.h | 19 +--- engines/sword2/music.cpp | 40 --------- engines/sword2/sound.h | 1 - 7 files changed, 170 insertions(+), 317 deletions(-) (limited to 'engines') diff --git a/engines/sword2/animation.cpp b/engines/sword2/animation.cpp index 2ebbdf4386..1127d825f2 100644 --- a/engines/sword2/animation.cpp +++ b/engines/sword2/animation.cpp @@ -30,6 +30,7 @@ #include "sword2/sword2.h" #include "sword2/defs.h" #include "sword2/header.h" +#include "sword2/logic.h" #include "sword2/maketext.h" #include "sword2/mouse.h" #include "sword2/resman.h" @@ -65,11 +66,11 @@ const MovieInfo MoviePlayer::_movies[19] = { { "enddemo", 110, false } }; -MoviePlayer::MoviePlayer(Sword2Engine *vm) { +MoviePlayer::MoviePlayer(Sword2Engine *vm, const char *name) { _vm = vm; + _name = strdup(name); _mixer = _vm->_mixer; _system = _vm->_system; - _name = NULL; _textSurface = NULL; _bgSoundStream = NULL; _ticks = 0; @@ -86,7 +87,6 @@ MoviePlayer::MoviePlayer(Sword2Engine *vm) { _seamless = false; _framesSkipped = 0; _forceFrame = false; - _textList = NULL; _currentText = 0; } @@ -202,84 +202,121 @@ void MoviePlayer::drawFrame() { _system->copyRectToScreen(_frameBuffer + _frameY * screenWidth + _frameX, screenWidth, _frameX, _frameY, _frameWidth, _frameHeight); } -void MoviePlayer::openTextObject(MovieTextObject *t) { - if (t->textSprite) { - _vm->_screen->createSurface(t->textSprite, &_textSurface); +void MoviePlayer::openTextObject(SequenceTextInfo *t) { + // Pull out the text line to get the official text number (for WAV id) + + uint32 res = t->textNumber / SIZE; + uint32 localText = t->textNumber & 0xffff; + + // Open text resource and get the line + + byte *text = _vm->fetchTextLine(_vm->_resman->openResource(res), localText); + + _textObject.speechId = READ_LE_UINT16(text); + + // Is it speech or subtitles, or both? + + // If we want subtitles, or there was no sound + + if (_vm->getSubtitles() || !_textObject.speechId) { + _textObject.textMem = _vm->_fontRenderer->makeTextSprite(text + 2, 600, 255, _vm->_speechFontId, 1); + } + + _vm->_resman->closeResource(res); + + if (_textObject.textMem) { + FrameHeader frame; + + frame.read(_textObject.textMem); + + _textObject.textSprite.x = 320 - frame.width / 2; + _textObject.textSprite.y = 440 - frame.height; + _textObject.textSprite.w = frame.width; + _textObject.textSprite.h = frame.height; + _textObject.textSprite.type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION; + _textObject.textSprite.data = _textObject.textMem + FrameHeader::size(); + _vm->_screen->createSurface(&_textObject.textSprite, &_textSurface); } } -void MoviePlayer::closeTextObject(MovieTextObject *t) { +void MoviePlayer::closeTextObject() { + free(_textObject.textMem); + _textObject.textMem = NULL; + + _textObject.speechId = 0; + if (_textSurface) { _vm->_screen->deleteSurface(_textSurface); _textSurface = NULL; } } -void MoviePlayer::calcTextPosition(MovieTextObject *t, int &xPos, int &yPos) { - xPos = 320 - t->textSprite->w / 2; - yPos = 420 - t->textSprite->h; +void MoviePlayer::calcTextPosition(int &xPos, int &yPos) { + xPos = 320 - _textObject.textSprite.w / 2; + yPos = 420 - _textObject.textSprite.h; } -void MoviePlayer::drawTextObject(MovieTextObject *t) { - if (t->textSprite && _textSurface) { +void MoviePlayer::drawTextObject() { + if (_textObject.textMem && _textSurface) { int screenWidth = _vm->_screen->getScreenWide(); - byte *src = t->textSprite->data; + byte *src = _textObject.textSprite.data; + uint16 width = _textObject.textSprite.w; + uint16 height = _textObject.textSprite.h; int xPos, yPos; - calcTextPosition(t, xPos, yPos); + calcTextPosition(xPos, yPos); byte *dst = _frameBuffer + yPos * screenWidth + xPos; - for (int y = 0; y < t->textSprite->h; y++) { - for (int x = 0; x < t->textSprite->w; x++) { + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { if (src[x] == 1) dst[x] = _black; else if (src[x] == 255) dst[x] = _white; } - src += t->textSprite->w; + src += width; dst += screenWidth; } - if (yPos + t->textSprite->h > _frameY + _frameHeight || t->textSprite->w > _frameWidth) { - _system->copyRectToScreen(_frameBuffer + yPos * screenWidth + xPos, screenWidth, xPos, yPos, t->textSprite->w, t->textSprite->h); + if (yPos + height > _frameY + _frameHeight || width > _frameWidth) { + _system->copyRectToScreen(_frameBuffer + yPos * screenWidth + xPos, screenWidth, xPos, yPos, width, height); } } } -void MoviePlayer::undrawTextObject(MovieTextObject *t) { - if (t->textSprite) { +void MoviePlayer::undrawTextObject() { + if (_textObject.textMem) { int xPos, yPos; - calcTextPosition(t, xPos, yPos); + calcTextPosition(xPos, yPos); + uint16 width = _textObject.textSprite.w; + uint16 height = _textObject.textSprite.h; // We only need to undraw the text if it's outside the frame. // Otherwise the next frame will cover the old text anyway. - if (yPos + t->textSprite->h > _frameY + _frameHeight || t->textSprite->w > _frameWidth) { + if (yPos + height > _frameY + _frameHeight || width > _frameWidth) { int screenWidth = _vm->_screen->getScreenWide(); byte *dst = _frameBuffer + yPos * screenWidth + xPos; - for (int y = 0; y < t->textSprite->h; y++) { - memset(dst, 0, t->textSprite->w); + for (int y = 0; y < height; y++) { + memset(dst, 0, width); dst += screenWidth; } - _system->copyRectToScreen(_frameBuffer + yPos * screenWidth + xPos, screenWidth, xPos, yPos, t->textSprite->w, t->textSprite->h); + _system->copyRectToScreen(_frameBuffer + yPos * screenWidth + xPos, screenWidth, xPos, yPos, width, height); } } } -bool MoviePlayer::load(const char *name, MovieTextObject *text[]) { +bool MoviePlayer::load() { _bgSoundStream = NULL; - _textList = text; _currentText = 0; _currentFrame = 0; - _name = strdup(name); - for (int i = 0; i < ARRAYSIZE(_movies); i++) { - if (scumm_stricmp(name, _movies[i].name) == 0) { + if (scumm_stricmp(_name, _movies[i].name) == 0) { _seamless = _movies[i].seamless; _numFrames = _movies[i].frames; if (_numFrames > 60) @@ -304,26 +341,24 @@ bool MoviePlayer::load(const char *name, MovieTextObject *text[]) { return false; } -void MoviePlayer::play(int32 leadIn, int32 leadOut) { +void MoviePlayer::play(SequenceTextInfo *textList, uint32 numLines, int32 leadIn, int32 leadOut) { bool terminate = false; bool textVisible = false; bool startNextText = false; - uint32 flags = Audio::Mixer::FLAG_16BITS; // This happens if the user quits during the "eye" cutscene. if (_vm->_quit) return; + _numSpeechLines = numLines; + _firstSpeechFrame = (numLines > 0) ? textList[0].startFrame : 0; + if (leadIn) { _vm->_sound->playMovieSound(leadIn, kLeadInSound); } savePalette(); -#ifndef SCUMM_BIG_ENDIAN - flags |= Audio::Mixer::FLAG_LITTLE_ENDIAN; -#endif - _framesSkipped = 0; _ticks = _system->getMillis(); _bgSoundStream = Audio::AudioStream::openStreamFile(_name); @@ -338,32 +373,32 @@ void MoviePlayer::play(int32 leadIn, int32 leadOut) { // The frame has been decoded. Now draw the subtitles, if any, // before drawing it to the screen. - if (_textList && _textList[_currentText]) { - MovieTextObject *t = _textList[_currentText]; + if (_currentText < numLines) { + SequenceTextInfo *t = &textList[_currentText]; if (_currentFrame == t->startFrame) { openTextObject(t); textVisible = true; - if (t->speech) { + if (_textObject.speechId) { startNextText = true; } } - if (startNextText && !_mixer->isSoundHandleActive(_speechHandle)) { - _mixer->playRaw(Audio::Mixer::kSpeechSoundType, &_speechHandle, t->speech, t->speechBufferSize, 22050, flags); + if (startNextText && _vm->_sound->amISpeaking() == RDSE_QUIET) { + _vm->_sound->playCompSpeech(_textObject.speechId, 16, 0); startNextText = false; } if (_currentFrame == t->endFrame) { - undrawTextObject(t); - closeTextObject(t); + undrawTextObject(); + closeTextObject(); _currentText++; textVisible = false; } if (textVisible) - drawTextObject(t); + drawTextObject(); } if (leadOut && _currentFrame == _leadOutFrame) { @@ -404,8 +439,8 @@ void MoviePlayer::play(int32 leadIn, int32 leadOut) { // If the sound is still playing, draw the subtitles one final // time. This happens in the "carib" cutscene. - if (textVisible && _mixer->isSoundHandleActive(_speechHandle)) { - drawTextObject(_textList[_currentText]); + if (textVisible && _vm->_sound->amISpeaking() == RDSE_SPEAKING) { + drawTextObject(); } drawFrame(); @@ -418,19 +453,17 @@ void MoviePlayer::play(int32 leadIn, int32 leadOut) { // mid-sentence, and - even more importantly - that we don't // free the sound buffer while it's still in use. - while (_mixer->isSoundHandleActive(_speechHandle) || _mixer->isSoundHandleActive(_bgSoundHandle)) { + while (_vm->_sound->amISpeaking() == RDSE_SPEAKING || _mixer->isSoundHandleActive(_bgSoundHandle)) { _system->delayMillis(100); } } else { - _mixer->stopHandle(_speechHandle); + _vm->_sound->stopSpeech(); _mixer->stopHandle(_bgSoundHandle); } // The current text object may still be open - if (_textList && _textList[_currentText]) { - undrawTextObject(_textList[_currentText]); - closeTextObject(_textList[_currentText]); - } + undrawTextObject(); + closeTextObject(); if (!_seamless) { clearFrame(); @@ -448,7 +481,8 @@ void MoviePlayer::play(int32 leadIn, int32 leadOut) { // Movie player for the new DXA movies /////////////////////////////////////////////////////////////////////////////// -MoviePlayerDXA::MoviePlayerDXA(Sword2Engine *vm) : MoviePlayer(vm) { +MoviePlayerDXA::MoviePlayerDXA(Sword2Engine *vm, const char *name) + : MoviePlayer(vm, name) { debug(0, "Creating DXA cutscene player"); } @@ -466,13 +500,13 @@ bool MoviePlayerDXA::decodeFrame() { return true; } -bool MoviePlayerDXA::load(const char *name, MovieTextObject *text[]) { - if (!MoviePlayer::load(name, text)) +bool MoviePlayerDXA::load() { + if (!MoviePlayer::load()) return false; char filename[20]; - snprintf(filename, sizeof(filename), "%s.dxa", name); + snprintf(filename, sizeof(filename), "%s.dxa", _name); if (loadFile(filename)) { // The Broken Sword games always use external audio tracks. @@ -501,7 +535,8 @@ bool MoviePlayerDXA::load(const char *name, MovieTextObject *text[]) { // Movie player for the old MPEG movies /////////////////////////////////////////////////////////////////////////////// -MoviePlayerMPEG::MoviePlayerMPEG(Sword2Engine *vm) : MoviePlayer(vm) { +MoviePlayerMPEG::MoviePlayerMPEG(Sword2Engine *vm, const char *name) + : MoviePlayer(vm, name) { #ifdef BACKEND_8BIT debug(0, "Creating MPEG cutscene player (8-bit)"); #else @@ -514,13 +549,13 @@ MoviePlayerMPEG::~MoviePlayerMPEG() { _anim = NULL; } -bool MoviePlayerMPEG::load(const char *name, MovieTextObject *text[]) { - if (!MoviePlayer::load(name, text)) +bool MoviePlayerMPEG::load() { + if (!MoviePlayer::load()) return false; _anim = new AnimationState(_vm, this); - if (!_anim->init(name)) { + if (!_anim->init(_name)) { delete _anim; _anim = NULL; return false; @@ -579,13 +614,13 @@ void MoviePlayerMPEG::updateScreen() { _anim->updateScreen(); } -void MoviePlayerMPEG::drawTextObject(MovieTextObject *t) { - if (t->textSprite && _textSurface) { - _anim->drawTextObject(t->textSprite, _textSurface); +void MoviePlayerMPEG::drawTextObject() { + if (_textObject.textMem && _textSurface) { + _anim->drawTextObject(&_textObject.textSprite, _textSurface); } } -void MoviePlayerMPEG::undrawTextObject(MovieTextObject *t) { +void MoviePlayerMPEG::undrawTextObject() { // As long as we only have subtitles for full-sized cutscenes, we don't // really need to implement this function. } @@ -689,15 +724,16 @@ void AnimationState::drawYUV(int width, int height, byte *const *dat) { // Dummy player for subtitled speech only /////////////////////////////////////////////////////////////////////////////// -MoviePlayerDummy::MoviePlayerDummy(Sword2Engine *vm) : MoviePlayer(vm) { +MoviePlayerDummy::MoviePlayerDummy(Sword2Engine *vm, const char *name) + : MoviePlayer(vm, name) { debug(0, "Creating Dummy cutscene player"); } MoviePlayerDummy::~MoviePlayerDummy() { } -bool MoviePlayerDummy::load(const char *name, MovieTextObject *text[]) { - if (!MoviePlayer::load(name, text)) +bool MoviePlayerDummy::load() { + if (!MoviePlayer::load()) return false; _frameBuffer = _vm->_screen->getScreen(); @@ -711,7 +747,7 @@ bool MoviePlayerDummy::load(const char *name, MovieTextObject *text[]) { } bool MoviePlayerDummy::decodeFrame() { - if (_currentFrame == 0 && _textList) { + if (_currentFrame == 0 && _numSpeechLines > 0) { byte dummyPalette[] = { 0, 0, 0, 0, 255, 255, 255, 0, @@ -767,7 +803,7 @@ bool MoviePlayerDummy::decodeFrame() { // If we have played the final voice-over, skip ahead to the lead out - if (_textList && !_textList[_currentText] && !_mixer->isSoundHandleActive(_speechHandle) && _leadOutFrame != (uint)-1 && _currentFrame < _leadOutFrame) { + if (_currentText >= _numSpeechLines && _vm->_sound->amISpeaking() == RDSE_QUIET && _leadOutFrame != (uint)-1 && _currentFrame < _leadOutFrame) { _currentFrame = _leadOutFrame - 1; } @@ -775,7 +811,7 @@ bool MoviePlayerDummy::decodeFrame() { } void MoviePlayerDummy::syncFrame() { - if (!_textList || _currentFrame < _textList[0]->startFrame) { + if (_numSpeechLines == 0 || _currentFrame < _firstSpeechFrame) { _ticks = _system->getMillis(); return; } @@ -786,16 +822,16 @@ void MoviePlayerDummy::syncFrame() { void MoviePlayerDummy::drawFrame() { } -void MoviePlayerDummy::drawTextObject(MovieTextObject *t) { - if (t->textSprite && _textSurface) { - _vm->_screen->drawSurface(t->textSprite, _textSurface); +void MoviePlayerDummy::drawTextObject() { + if (_textObject.textMem && _textSurface) { + _vm->_screen->drawSurface(&_textObject.textSprite, _textSurface); } } -void MoviePlayerDummy::undrawTextObject(MovieTextObject *t) { - if (t->textSprite && _textSurface) { - memset(_textSurface, 1, t->textSprite->w * t->textSprite->h); - drawTextObject(t); +void MoviePlayerDummy::undrawTextObject() { + if (_textObject.textMem && _textSurface) { + memset(_textSurface, 1, _textObject.textSprite.w * _textObject.textSprite.h); + drawTextObject(); } } @@ -804,13 +840,13 @@ void MoviePlayerDummy::undrawTextObject(MovieTextObject *t) { /////////////////////////////////////////////////////////////////////////////// MoviePlayer *makeMoviePlayer(Sword2Engine *vm, const char *name) { - char filename[20]; + static char filename[20]; #ifdef USE_ZLIB snprintf(filename, sizeof(filename), "%s.dxa", name); if (Common::File::exists(filename)) { - return new MoviePlayerDXA(vm); + return new MoviePlayerDXA(vm, name); } #endif @@ -818,11 +854,11 @@ MoviePlayer *makeMoviePlayer(Sword2Engine *vm, const char *name) { snprintf(filename, sizeof(filename), "%s.mp2", name); if (Common::File::exists(filename)) { - return new MoviePlayerMPEG(vm); + return new MoviePlayerMPEG(vm, name); } #endif - return new MoviePlayerDummy(vm); + return new MoviePlayerDummy(vm, name); } } // End of namespace Sword2 diff --git a/engines/sword2/animation.h b/engines/sword2/animation.h index d667b248fa..5c1715a08f 100644 --- a/engines/sword2/animation.h +++ b/engines/sword2/animation.h @@ -26,20 +26,25 @@ #include "graphics/mpeg_player.h" #include "sound/mixer.h" -namespace Sword2 { - -struct SpriteInfo; +#include "sword2/screen.h" -// This is the structure which is passed to the sequence player. It includes -// the smack to play, and any text lines which are to be displayed over the top -// of the sequence. +namespace Sword2 { -struct MovieTextObject { +struct SequenceTextInfo { + uint32 textNumber; uint16 startFrame; uint16 endFrame; - SpriteInfo *textSprite; - uint32 speechBufferSize; - uint16 *speech; +}; + +struct MovieTextObject { + byte *textMem; + SpriteInfo textSprite; + uint16 speechId; + + MovieTextObject() { + textMem = NULL; + speechId = 0; + } }; struct MovieInfo { @@ -61,9 +66,11 @@ protected: byte _originalPalette[4 * 256]; + uint32 _numSpeechLines; + uint32 _firstSpeechFrame; + MovieTextObject _textObject; byte *_textSurface; - Audio::SoundHandle _speechHandle; Audio::SoundHandle _bgSoundHandle; Audio::AudioStream *_bgSoundStream; @@ -85,15 +92,14 @@ protected: static const MovieInfo _movies[]; - MovieTextObject **_textList; - int _currentText; + uint32 _currentText; void savePalette(); void restorePalette(); - void openTextObject(MovieTextObject *t); - void closeTextObject(MovieTextObject *t); - void calcTextPosition(MovieTextObject *t, int &xPos, int &yPos); + void openTextObject(SequenceTextInfo *t); + void closeTextObject(); + void calcTextPosition(int &xPos, int &yPos); virtual void handleScreenChanged() {} @@ -102,16 +108,16 @@ protected: virtual bool decodeFrame() = 0; virtual void syncFrame(); virtual void drawFrame(); - virtual void drawTextObject(MovieTextObject *t); - virtual void undrawTextObject(MovieTextObject *t); + virtual void drawTextObject(); + virtual void undrawTextObject(); public: - MoviePlayer(Sword2Engine *vm); + MoviePlayer(Sword2Engine *vm, const char *name); virtual ~MoviePlayer(); void updatePalette(byte *pal, bool packed = true); - virtual bool load(const char *name, MovieTextObject *text[]); - void play(int32 leadIn, int32 leadOut); + virtual bool load(); + void play(SequenceTextInfo *textList, uint32 numLines, int32 leadIn, int32 leadOut); }; class MoviePlayerDummy : public MoviePlayer { @@ -119,14 +125,14 @@ protected: bool decodeFrame(); void syncFrame(); void drawFrame(); - void drawTextObject(MovieTextObject *t); - void undrawTextObject(MovieTextObject *t); + void drawTextObject(); + void undrawTextObject(); public: - MoviePlayerDummy(Sword2Engine *vm); + MoviePlayerDummy(Sword2Engine *vm, const char *name); virtual ~MoviePlayerDummy(); - bool load(const char *name, MovieTextObject *text[]); + bool load(); }; #ifdef USE_MPEG2 @@ -164,15 +170,15 @@ protected: void clearFrame(); void drawFrame(); void updateScreen(); - void drawTextObject(MovieTextObject *t); - void undrawTextObject(MovieTextObject *t); + void drawTextObject(); + void undrawTextObject(); #endif public: - MoviePlayerMPEG(Sword2Engine *vm); + MoviePlayerMPEG(Sword2Engine *vm, const char *name); ~MoviePlayerMPEG(); - bool load(const char *name, MovieTextObject *text[]); + bool load(); }; #endif @@ -183,10 +189,10 @@ protected: bool decodeFrame(); public: - MoviePlayerDXA(Sword2Engine *vm); + MoviePlayerDXA(Sword2Engine *vm, const char *name); ~MoviePlayerDXA(); - bool load(const char *name, MovieTextObject *text[]); + bool load(); }; #endif diff --git a/engines/sword2/anims.cpp b/engines/sword2/anims.cpp index 82322282b7..b00e40a8f4 100644 --- a/engines/sword2/anims.cpp +++ b/engines/sword2/anims.cpp @@ -179,131 +179,4 @@ void Router::setSpriteShading(byte *ob_graph, uint32 type) { obGraph.setType((obGraph.getType() & 0x0000ffff) | type); } -void Logic::createSequenceSpeech(MovieTextObject *sequenceText[]) { - uint32 line; - uint32 local_text; - uint32 text_res; - byte *text; - uint32 wavId; // ie. offical text number (actor text number) - bool speechRunning; - - // for each sequence text line that's been logged - for (line = 0; line < _sequenceTextLines; line++) { - // allocate this structure - sequenceText[line] = new MovieTextObject; - - sequenceText[line]->startFrame = _sequenceTextList[line].startFrame; - sequenceText[line]->endFrame = _sequenceTextList[line].endFrame; - - // pull out the text line to get the official text number - // (for wav id) - - text_res = _sequenceTextList[line].textNumber / SIZE; - local_text = _sequenceTextList[line].textNumber & 0xffff; - - // open text resource & get the line - text = _vm->fetchTextLine(_vm->_resman->openResource(text_res), local_text); - wavId = (int32)READ_LE_UINT16(text); - - // now ok to close the text file - _vm->_resman->closeResource(text_res); - - // 1st word of text line is the official line number - debug(5,"(%d) SEQUENCE TEXT: %s", READ_LE_UINT16(text), text + 2); - - // is it to be speech or subtitles or both? - // assume speech is not running until know otherwise - - speechRunning = false; - _sequenceTextList[line].speech_mem = NULL; - sequenceText[line]->speech = NULL; - - if (!_vm->_sound->isSpeechMute()) { - _sequenceTextList[line].speechBufferSize = _vm->_sound->preFetchCompSpeech(wavId, &_sequenceTextList[line].speech_mem); - if (_sequenceTextList[line].speechBufferSize) { - // ok, we've got speech! - speechRunning = true; - } - } - - // if we want subtitles, or speech failed to load - - if (_vm->getSubtitles() || !speechRunning) { - // open text resource & get the line - text = _vm->fetchTextLine(_vm->_resman->openResource(text_res), local_text); - // make the sprite - // 'text+2' to skip the first 2 bytes which form the - // line reference number - - // NB. The mem block containing the text sprite is - // currently FLOATING! - - // When rendering text over a sequence we need a - // different colour for the border. - - _sequenceTextList[line].text_mem = _vm->_fontRenderer->makeTextSprite(text + 2, 600, 255, _vm->_speechFontId, 1); - - // ok to close the text resource now - _vm->_resman->closeResource(text_res); - } else { - _sequenceTextList[line].text_mem = NULL; - sequenceText[line]->textSprite = NULL; - } - } - - // for drivers: NULL-terminate the array of pointers to - // MovieTextObject's - sequenceText[_sequenceTextLines] = NULL; - - for (line = 0; line < _sequenceTextLines; line++) { - // if we've made a text sprite for this line... - - if (_sequenceTextList[line].text_mem) { - // now fill out the SpriteInfo structure in the - // MovieTextObjectStructure - FrameHeader frame; - - frame.read(_sequenceTextList[line].text_mem); - - sequenceText[line]->textSprite = new SpriteInfo; - - // center text at bottom of screen - sequenceText[line]->textSprite->x = 320 - frame.width / 2; - sequenceText[line]->textSprite->y = 440 - frame.height; - sequenceText[line]->textSprite->w = frame.width; - sequenceText[line]->textSprite->h = frame.height; - sequenceText[line]->textSprite->type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION; - sequenceText[line]->textSprite->data = _sequenceTextList[line].text_mem + FrameHeader::size(); - } - - // if we've loaded a speech sample for this line... - - if (_sequenceTextList[line].speech_mem) { - // for drivers: set up pointer to decompressed wav in - // memory - - sequenceText[line]->speechBufferSize = _sequenceTextList[line].speechBufferSize; - sequenceText[line]->speech = _sequenceTextList[line].speech_mem; - } - } -} - -void Logic::clearSequenceSpeech(MovieTextObject *sequenceText[]) { - for (uint i = 0; i < _sequenceTextLines; i++) { - // free up the memory used by this MovieTextObject - delete sequenceText[i]; - - // free up the mem block containing this text sprite - if (_sequenceTextList[i].text_mem) - free(_sequenceTextList[i].text_mem); - - // free up the mem block containing this speech sample - if (_sequenceTextList[i].speech_mem) - free(_sequenceTextList[i].speech_mem); - } - - // IMPORTANT! Reset the line count ready for the next sequence! - _sequenceTextLines = 0; -} - } // End of namespace Sword2 diff --git a/engines/sword2/function.cpp b/engines/sword2/function.cpp index 3812a4f5a3..ea7629ce4c 100644 --- a/engines/sword2/function.cpp +++ b/engines/sword2/function.cpp @@ -2102,7 +2102,6 @@ int32 Logic::fnPlaySequence(int32 *params) { // 1 number of frames in the sequence, used for PSX. char filename[30]; - MovieTextObject *sequenceSpeechArray[MAX_SEQUENCE_TEXT_LINES + 1]; // The original code had some #ifdef blocks for skipping or muting the // cutscenes - fondly described as "the biggest fudge in the history @@ -2118,12 +2117,7 @@ int32 Logic::fnPlaySequence(int32 *params) { // Write to walkthrough file (zebug0.txt) debug(5, "PLAYING SEQUENCE \"%s\"", filename); - // now create the text sprites, if any - - if (_sequenceTextLines) - createSequenceSpeech(sequenceSpeechArray); - - // don't want to carry on streaming game music when smacker starts! + // don't want to carry on streaming game music when cutscene starts! fnStopMusic(NULL); // pause sfx during sequence @@ -2131,10 +2125,12 @@ int32 Logic::fnPlaySequence(int32 *params) { MoviePlayer *player = makeMoviePlayer(_vm, filename); - if (player->load(filename, (_sequenceTextLines && !readVar(DEMO)) ? sequenceSpeechArray : NULL)) { - player->play(_smackerLeadIn, _smackerLeadOut); + if (player->load()) { + player->play(_sequenceTextList, _sequenceTextLines, _smackerLeadIn, _smackerLeadOut); } + _sequenceTextLines = 0; + delete player; // unpause sound fx again, in case we're staying in same location @@ -2143,11 +2139,6 @@ int32 Logic::fnPlaySequence(int32 *params) { _smackerLeadIn = 0; _smackerLeadOut = 0; - // now clear the text sprites, if any - - if (_sequenceTextLines) - clearSequenceSpeech(sequenceSpeechArray); - // now clear the screen in case the Sequence was quitted (using ESC) // rather than fading down to black @@ -2219,12 +2210,15 @@ int32 Logic::fnAddSequenceText(int32 *params) { // 1 frame number to start the text displaying // 2 frame number to stop the text dispalying - assert(_sequenceTextLines < MAX_SEQUENCE_TEXT_LINES); + if (!readVar(DEMO)) { + assert(_sequenceTextLines < MAX_SEQUENCE_TEXT_LINES); + + _sequenceTextList[_sequenceTextLines].textNumber = params[0]; + _sequenceTextList[_sequenceTextLines].startFrame = params[1]; + _sequenceTextList[_sequenceTextLines].endFrame = params[2]; + _sequenceTextLines++; + } - _sequenceTextList[_sequenceTextLines].textNumber = params[0]; - _sequenceTextList[_sequenceTextLines].startFrame = params[1]; - _sequenceTextList[_sequenceTextLines].endFrame = params[2]; - _sequenceTextLines++; return IR_CONT; } diff --git a/engines/sword2/logic.h b/engines/sword2/logic.h index e68d9c9317..6048fe7310 100644 --- a/engines/sword2/logic.h +++ b/engines/sword2/logic.h @@ -24,13 +24,12 @@ #ifndef SWORD2_LOGIC_H #define SWORD2_LOGIC_H -#include "sword2/memory.h" #include "common/endian.h" +#include "sword2/animation.h" +#include "sword2/memory.h" namespace Sword2 { -struct MovieTextObject; - #define MAX_events 10 #define TREE_SIZE 3 @@ -79,22 +78,8 @@ private: // keeps count of number of text lines to disaply during the sequence uint32 _sequenceTextLines; - // FOR TEXT LINES IN SEQUENCE PLAYER - - struct SequenceTextInfo { - uint32 textNumber; - uint16 startFrame; - uint16 endFrame; - byte *text_mem; - uint32 speechBufferSize; - uint16 *speech_mem; - }; - SequenceTextInfo _sequenceTextList[MAX_SEQUENCE_TEXT_LINES]; - void createSequenceSpeech(MovieTextObject *sequenceText[]); - void clearSequenceSpeech(MovieTextObject *sequenceText[]); - // when not playing a wav we calculate the speech time based upon // length of ascii diff --git a/engines/sword2/music.cpp b/engines/sword2/music.cpp index 4b5f1e935d..c13c5532d4 100644 --- a/engines/sword2/music.cpp +++ b/engines/sword2/music.cpp @@ -704,46 +704,6 @@ int32 Sound::amISpeaking() { return RDSE_QUIET; } -/** - * This function loads and decompresses a list of speech from a cluster, but - * does not play it. This is used for cutscene voice-overs, presumably to - * avoid having to read from more than one file on the CD during playback. - * @param speechId the text line id used to reference the speech - * @param buf a pointer to the buffer that will be allocated for the sound - */ - -uint32 Sound::preFetchCompSpeech(uint32 speechId, uint16 **buf) { - int cd = _vm->_resman->getCD(); - uint32 numSamples; - - SoundFileHandle *fh = (cd == 1) ? &_speechFile[0] : &_speechFile[1]; - - Audio::AudioStream *input = getAudioStream(fh, "speech", cd, speechId, &numSamples); - - if (!input) - return 0; - - *buf = NULL; - - // Decompress data into speech buffer. - - uint32 bufferSize = 2 * numSamples; - - *buf = (uint16 *)malloc(bufferSize); - if (!*buf) { - delete input; - fh->file.close(); - return 0; - } - - uint32 readSamples = input->readBuffer((int16 *)*buf, numSamples); - - fh->file.close(); - delete input; - - return 2 * readSamples; -} - /** * This function loads, decompresses and plays a line of speech. An error * occurs if speech is already playing. diff --git a/engines/sword2/sound.h b/engines/sword2/sound.h index b941f98b4c..8c24494148 100644 --- a/engines/sword2/sound.h +++ b/engines/sword2/sound.h @@ -269,7 +269,6 @@ public: int32 getSpeechStatus(); int32 amISpeaking(); int32 playCompSpeech(uint32 speechId, uint8 vol, int8 pan); - uint32 preFetchCompSpeech(uint32 speechId, uint16 **buf); int32 stopSpeech(); int32 streamCompMusic(uint32 musicId, bool loop); -- cgit v1.2.3