aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorTorbjörn Andersson2007-02-08 21:55:37 +0000
committerTorbjörn Andersson2007-02-08 21:55:37 +0000
commit98a8e88f61e871096fe979c2d9a27c2053aa38ca (patch)
treec480e85462867cc355066e9d6b2e696ef8b23e9d /engines
parent65dfc335ef134c4ff7a6d50ddab38c0565611f3b (diff)
downloadscummvm-rg350-98a8e88f61e871096fe979c2d9a27c2053aa38ca.tar.gz
scummvm-rg350-98a8e88f61e871096fe979c2d9a27c2053aa38ca.tar.bz2
scummvm-rg350-98a8e88f61e871096fe979c2d9a27c2053aa38ca.zip
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
Diffstat (limited to 'engines')
-rw-r--r--engines/sword2/animation.cpp200
-rw-r--r--engines/sword2/animation.h68
-rw-r--r--engines/sword2/anims.cpp127
-rw-r--r--engines/sword2/function.cpp32
-rw-r--r--engines/sword2/logic.h19
-rw-r--r--engines/sword2/music.cpp40
-rw-r--r--engines/sword2/sound.h1
7 files changed, 170 insertions, 317 deletions
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
@@ -705,46 +705,6 @@ int32 Sound::amISpeaking() {
}
/**
- * 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.
* @param speechId the text line id used to reference the speech
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);