aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/agi/detection.cpp15
-rw-r--r--engines/agos/animation.cpp105
-rw-r--r--engines/agos/animation.h7
-rw-r--r--engines/cine/anim.cpp19
-rw-r--r--engines/cine/anim.h2
-rw-r--r--engines/cine/bg_list.cpp12
-rw-r--r--engines/cine/cine.cpp2
-rw-r--r--engines/cine/gfx.cpp70
-rw-r--r--engines/cine/gfx.h9
-rw-r--r--engines/cine/main_loop.cpp17
-rw-r--r--engines/cine/saveload.cpp16
-rw-r--r--engines/cine/script_fw.cpp19
-rw-r--r--engines/cine/various.cpp21
-rw-r--r--engines/cine/various.h2
-rw-r--r--engines/lastexpress/data/background.cpp1
-rw-r--r--engines/lastexpress/data/subtitle.cpp6
-rw-r--r--engines/lastexpress/debug.cpp93
-rw-r--r--engines/lastexpress/debug.h3
-rw-r--r--engines/lastexpress/entities/abbot.cpp26
-rw-r--r--engines/lastexpress/entities/abbot.h8
-rw-r--r--engines/lastexpress/entities/august.cpp2
-rw-r--r--engines/lastexpress/entities/chapters.cpp2
-rw-r--r--engines/lastexpress/entities/chapters.h2
-rw-r--r--engines/lastexpress/entities/entity.cpp27
-rw-r--r--engines/lastexpress/entities/entity.h23
-rw-r--r--engines/lastexpress/entities/verges.cpp164
-rw-r--r--engines/lastexpress/entities/verges.h26
-rw-r--r--engines/lastexpress/fight/fight.cpp2
-rw-r--r--engines/lastexpress/game/action.cpp4
-rw-r--r--engines/lastexpress/game/beetle.cpp5
-rw-r--r--engines/lastexpress/game/entities.cpp4
-rw-r--r--engines/lastexpress/game/entities.h2
-rw-r--r--engines/lastexpress/game/inventory.cpp6
-rw-r--r--engines/lastexpress/game/logic.cpp1
-rw-r--r--engines/lastexpress/game/savegame.cpp47
-rw-r--r--engines/lastexpress/game/savegame.h4
-rw-r--r--engines/lastexpress/game/savepoint.cpp4
-rw-r--r--engines/lastexpress/game/scenes.cpp2
-rw-r--r--engines/lastexpress/game/scenes.h2
-rw-r--r--engines/lastexpress/menu/menu.cpp4
-rw-r--r--engines/lastexpress/sound/entry.cpp4
-rw-r--r--engines/lastexpress/sound/queue.cpp6
-rw-r--r--engines/mohawk/myst_stacks/dni.cpp2
-rw-r--r--engines/mohawk/video.cpp22
-rw-r--r--engines/mohawk/video.h6
-rw-r--r--engines/saga/introproc_saga2.cpp7
-rw-r--r--engines/saga/shorten.cpp3
-rw-r--r--engines/sci/console.cpp12
-rw-r--r--engines/sci/engine/kgraphics32.cpp21
-rw-r--r--engines/sci/engine/kmath.cpp25
-rw-r--r--engines/sci/engine/kvideo.cpp22
-rw-r--r--engines/sci/engine/workarounds.cpp2
-rw-r--r--engines/sci/graphics/frameout.cpp9
-rw-r--r--engines/sci/graphics/palette.cpp21
-rw-r--r--engines/sci/graphics/palette.h1
-rw-r--r--engines/sci/sci.cpp2
-rw-r--r--engines/sci/sound/audio.cpp3
-rw-r--r--engines/sci/sound/soundcmd.cpp41
-rw-r--r--engines/sci/video/robot_decoder.cpp377
-rw-r--r--engines/sci/video/robot_decoder.h129
-rw-r--r--engines/sci/video/seq_decoder.cpp61
-rw-r--r--engines/sci/video/seq_decoder.h67
-rw-r--r--engines/scumm/detection.cpp17
-rw-r--r--engines/scumm/he/animation_he.cpp7
-rw-r--r--engines/sword1/animation.cpp72
-rw-r--r--engines/sword1/animation.h32
-rw-r--r--engines/sword1/logic.cpp2
-rw-r--r--engines/sword2/animation.cpp62
-rw-r--r--engines/sword2/animation.h30
-rw-r--r--engines/sword2/function.cpp2
-rw-r--r--engines/sword25/fmv/movieplayer.cpp1
-rw-r--r--engines/sword25/fmv/movieplayer.h4
-rw-r--r--engines/sword25/fmv/theora_decoder.cpp565
-rw-r--r--engines/sword25/fmv/theora_decoder.h144
-rw-r--r--engines/sword25/module.mk5
-rw-r--r--engines/sword25/sfx/soundengine.cpp18
-rw-r--r--engines/sword25/util/pluto/pluto.cpp4
-rw-r--r--engines/toon/movie.cpp38
-rw-r--r--engines/toon/movie.h14
-rw-r--r--engines/toon/toon.cpp2
-rw-r--r--engines/tucker/sequences.cpp4
81 files changed, 1009 insertions, 1643 deletions
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index 805fe7d366..5f7780bfe3 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -20,9 +20,6 @@
*
*/
-// FIXME: Avoid using printf
-#define FORBIDDEN_SYMBOL_EXCEPTION_printf
-
#include "base/plugins.h"
#include "engines/advancedDetector.h"
@@ -491,10 +488,14 @@ const ADGameDescription *AgiMetaEngine::fallbackDetect(const FileMap &allFilesXX
g_fallbackDesc.desc.gameid = _gameid.c_str();
g_fallbackDesc.desc.extra = _extra.c_str();
- printf("Your game version has been detected using fallback matching as a\n");
- printf("variant of %s (%s).\n", g_fallbackDesc.desc.gameid, g_fallbackDesc.desc.extra);
- printf("If this is an original and unmodified version or new made Fanmade game,\n");
- printf("please report any, information previously printed by ScummVM to the team.\n");
+ Common::String fallbackWarning;
+
+ fallbackWarning = "Your game version has been detected using fallback matching as a\n";
+ fallbackWarning += Common::String::format("variant of %s (%s).\n", g_fallbackDesc.desc.gameid, g_fallbackDesc.desc.extra);
+ fallbackWarning += "If this is an original and unmodified version or new made Fanmade game,\n";
+ fallbackWarning += "please report any, information previously printed by ScummVM to the team.\n";
+
+ g_system->logMessage(LogMessageType::kWarning, fallbackWarning.c_str());
return (const ADGameDescription *)&g_fallbackDesc;
}
diff --git a/engines/agos/animation.cpp b/engines/agos/animation.cpp
index 10c01741ae..9176412e0e 100644
--- a/engines/agos/animation.cpp
+++ b/engines/agos/animation.cpp
@@ -260,9 +260,6 @@ bool MoviePlayerDXA::load() {
debug(0, "Playing video %s", videoName.c_str());
CursorMan.showMouse(false);
-
- _firstFrameOffset = _fileStream->pos();
-
return true;
}
@@ -271,6 +268,10 @@ void MoviePlayerDXA::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) {
uint w = getWidth();
const Graphics::Surface *surface = decodeNextFrame();
+
+ if (!surface)
+ return;
+
byte *src = (byte *)surface->pixels;
dst += y * pitch + x;
@@ -281,7 +282,7 @@ void MoviePlayerDXA::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) {
} while (--h);
if (hasDirtyPalette())
- setSystemPalette();
+ g_system->getPaletteManager()->setPalette(getPalette(), 0, 256);
}
void MoviePlayerDXA::playVideo() {
@@ -302,34 +303,7 @@ void MoviePlayerDXA::stopVideo() {
}
void MoviePlayerDXA::startSound() {
- uint32 offset, size;
-
- if (getSoundTag() == MKTAG('W','A','V','E')) {
- size = _fileStream->readUint32BE();
-
- if (_sequenceNum) {
- Common::File in;
-
- _fileStream->seek(size, SEEK_CUR);
-
- in.open("audio.wav");
- if (!in.isOpen()) {
- error("Can't read offset file 'audio.wav'");
- }
-
- in.seek(_sequenceNum * 8, SEEK_SET);
- offset = in.readUint32LE();
- size = in.readUint32LE();
-
- in.seek(offset, SEEK_SET);
- _bgSoundStream = Audio::makeWAVStream(in.readStream(size), DisposeAfterUse::YES);
- in.close();
- } else {
- _bgSoundStream = Audio::makeWAVStream(_fileStream->readStream(size), DisposeAfterUse::YES);
- }
- } else {
- _bgSoundStream = Audio::SeekableAudioStream::openStreamFile(baseName);
- }
+ start();
if (_bgSoundStream != NULL) {
_vm->_mixer->stopHandle(_bgSound);
@@ -344,8 +318,7 @@ void MoviePlayerDXA::nextFrame() {
}
if (_vm->_interactiveVideo == TYPE_LOOPING && endOfVideo()) {
- _fileStream->seek(_firstFrameOffset);
- _curFrame = -1;
+ rewind();
startSound();
}
@@ -374,13 +347,15 @@ bool MoviePlayerDXA::processFrame() {
copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, screen->pitch);
_vm->_system->unlockScreen();
- Common::Rational soundTime(_mixer->getSoundElapsedTime(_bgSound), 1000);
- if ((_bgSoundStream == NULL) || ((soundTime * getFrameRate()).toInt() / 1000 < getCurFrame() + 1)) {
+ uint32 soundTime = _mixer->getSoundElapsedTime(_bgSound);
+ uint32 nextFrameStartTime = ((Video::VideoDecoder::VideoTrack *)getTrack(0))->getNextFrameStartTime();
+
+ if ((_bgSoundStream == NULL) || soundTime < nextFrameStartTime) {
if (_bgSoundStream && _mixer->isSoundHandleActive(_bgSound)) {
- while (_mixer->isSoundHandleActive(_bgSound) && (soundTime * getFrameRate()).toInt() < getCurFrame()) {
+ while (_mixer->isSoundHandleActive(_bgSound) && soundTime < nextFrameStartTime) {
_vm->_system->delayMillis(10);
- soundTime = Common::Rational(_mixer->getSoundElapsedTime(_bgSound), 1000);
+ soundTime = _mixer->getSoundElapsedTime(_bgSound);
}
// In case the background sound ends prematurely, update
// _ticks so that we can still fall back on the no-sound
@@ -399,14 +374,35 @@ bool MoviePlayerDXA::processFrame() {
return false;
}
-void MoviePlayerDXA::updateVolume() {
- if (g_system->getMixer()->isSoundHandleActive(_bgSound))
- g_system->getMixer()->setChannelVolume(_bgSound, getVolume());
-}
+void MoviePlayerDXA::readSoundData(Common::SeekableReadStream *stream) {
+ uint32 tag = stream->readUint32BE();
+
+ if (tag == MKTAG('W','A','V','E')) {
+ uint32 size = stream->readUint32BE();
+
+ if (_sequenceNum) {
+ Common::File in;
+
+ stream->skip(size);
+
+ in.open("audio.wav");
+ if (!in.isOpen()) {
+ error("Can't read offset file 'audio.wav'");
+ }
+
+ in.seek(_sequenceNum * 8, SEEK_SET);
+ uint32 offset = in.readUint32LE();
+ size = in.readUint32LE();
-void MoviePlayerDXA::updateBalance() {
- if (g_system->getMixer()->isSoundHandleActive(_bgSound))
- g_system->getMixer()->setChannelBalance(_bgSound, getBalance());
+ in.seek(offset, SEEK_SET);
+ _bgSoundStream = Audio::makeWAVStream(in.readStream(size), DisposeAfterUse::YES);
+ in.close();
+ } else {
+ _bgSoundStream = Audio::makeWAVStream(stream->readStream(size), DisposeAfterUse::YES);
+ }
+ } else {
+ _bgSoundStream = Audio::SeekableAudioStream::openStreamFile(baseName);
+ }
}
///////////////////////////////////////////////////////////////////////////////
@@ -415,7 +411,7 @@ void MoviePlayerDXA::updateBalance() {
MoviePlayerSMK::MoviePlayerSMK(AGOSEngine_Feeble *vm, const char *name)
- : MoviePlayer(vm), SmackerDecoder(vm->_mixer) {
+ : MoviePlayer(vm), SmackerDecoder() {
debug(0, "Creating SMK cutscene player");
memset(baseName, 0, sizeof(baseName));
@@ -435,8 +431,6 @@ bool MoviePlayerSMK::load() {
CursorMan.showMouse(false);
- _firstFrameOffset = _fileStream->pos();
-
return true;
}
@@ -445,6 +439,10 @@ void MoviePlayerSMK::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) {
uint w = getWidth();
const Graphics::Surface *surface = decodeNextFrame();
+
+ if (!surface)
+ return;
+
byte *src = (byte *)surface->pixels;
dst += y * pitch + x;
@@ -455,7 +453,7 @@ void MoviePlayerSMK::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) {
} while (--h);
if (hasDirtyPalette())
- setSystemPalette();
+ g_system->getPaletteManager()->setPalette(getPalette(), 0, 256);
}
void MoviePlayerSMK::playVideo() {
@@ -468,6 +466,7 @@ void MoviePlayerSMK::stopVideo() {
}
void MoviePlayerSMK::startSound() {
+ start();
}
void MoviePlayerSMK::handleNextFrame() {
@@ -477,10 +476,8 @@ void MoviePlayerSMK::handleNextFrame() {
}
void MoviePlayerSMK::nextFrame() {
- if (_vm->_interactiveVideo == TYPE_LOOPING && endOfVideo()) {
- _fileStream->seek(_firstFrameOffset);
- _curFrame = -1;
- }
+ if (_vm->_interactiveVideo == TYPE_LOOPING && endOfVideo())
+ rewind();
if (!endOfVideo()) {
decodeNextFrame();
@@ -503,7 +500,7 @@ bool MoviePlayerSMK::processFrame() {
uint32 waitTime = getTimeToNextFrame();
- if (!waitTime) {
+ if (!waitTime && !endOfVideoTracks()) {
warning("dropped frame %i", getCurFrame());
return false;
}
diff --git a/engines/agos/animation.h b/engines/agos/animation.h
index d1ff074b03..9e31fced6d 100644
--- a/engines/agos/animation.h
+++ b/engines/agos/animation.h
@@ -67,9 +67,6 @@ protected:
virtual void handleNextFrame();
virtual bool processFrame() = 0;
virtual void startSound() {}
-
-protected:
- uint32 _firstFrameOffset;
};
class MoviePlayerDXA : public MoviePlayer, Video::DXADecoder {
@@ -84,9 +81,7 @@ public:
virtual void stopVideo();
protected:
- // VideoDecoder API
- void updateVolume();
- void updateBalance();
+ void readSoundData(Common::SeekableReadStream *stream);
private:
void handleNextFrame();
diff --git a/engines/cine/anim.cpp b/engines/cine/anim.cpp
index 410fcca1f3..60168831a1 100644
--- a/engines/cine/anim.cpp
+++ b/engines/cine/anim.cpp
@@ -682,9 +682,10 @@ void convert8BBP2(byte *dest, byte *source, int16 width, int16 height) {
* Load image set
* @param resourceName Image set filename
* @param idx Target index in animDataTable (-1 if any empty space will do)
+ * @param frameIndex frame of animation to load (-1 for all frames)
* @return The number of the animDataTable entry after the loaded image set (-1 if error)
*/
-int loadSet(const char *resourceName, int16 idx) {
+int loadSet(const char *resourceName, int16 idx, int16 frameIndex =-1 ) {
AnimHeader2Struct header2;
uint16 numSpriteInAnim;
int16 foundFileIdx = findFileInBundle(resourceName);
@@ -708,7 +709,17 @@ int loadSet(const char *resourceName, int16 idx) {
entry = idx < 0 ? emptyAnimSpace() : idx;
assert(entry >= 0);
- for (int16 i = 0; i < numSpriteInAnim; i++, entry++) {
+ int16 startFrame = 0;
+ int16 endFrame = numSpriteInAnim;
+
+ if(frameIndex>=0)
+ {
+ startFrame = frameIndex;
+ endFrame = frameIndex+1;
+ ptr += 0x10 * frameIndex;
+ }
+
+ for (int16 i = startFrame; i < endFrame; i++, entry++) {
Common::MemoryReadStream readS(ptr, 0x10);
header2.field_0 = readS.readUint32BE();
@@ -767,7 +778,7 @@ int loadSeq(const char *resourceName, int16 idx) {
* @return The number of the animDataTable entry after the loaded resource (-1 if error)
* @todo Implement loading of all resource types
*/
-int loadResource(const char *resourceName, int16 idx) {
+int loadResource(const char *resourceName, int16 idx, int16 frameIndex) {
int result = -1; // Return an error by default
if (strstr(resourceName, ".SPL")) {
result = loadSpl(resourceName, idx);
@@ -778,7 +789,7 @@ int loadResource(const char *resourceName, int16 idx) {
} else if (strstr(resourceName, ".ANM")) {
result = loadAni(resourceName, idx);
} else if (strstr(resourceName, ".SET")) {
- result = loadSet(resourceName, idx);
+ result = loadSet(resourceName, idx, frameIndex);
} else if (strstr(resourceName, ".SEQ")) {
result = loadSeq(resourceName, idx);
} else if (strstr(resourceName, ".H32")) {
diff --git a/engines/cine/anim.h b/engines/cine/anim.h
index 9c06c260ce..c5130aab82 100644
--- a/engines/cine/anim.h
+++ b/engines/cine/anim.h
@@ -98,7 +98,7 @@ public:
void freeAnimDataTable();
void freeAnimDataRange(byte startIdx, byte numIdx);
-int loadResource(const char *resourceName, int16 idx = -1);
+int loadResource(const char *resourceName, int16 idx = -1, int16 frameIndex = -1);
void loadResourcesFromSave(Common::SeekableReadStream &fHandle, enum CineSaveGameFormat saveGameFormat);
void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency);
diff --git a/engines/cine/bg_list.cpp b/engines/cine/bg_list.cpp
index 693fea3294..36ecf53dea 100644
--- a/engines/cine/bg_list.cpp
+++ b/engines/cine/bg_list.cpp
@@ -39,9 +39,9 @@ uint32 var8;
* @param objIdx Sprite description
*/
void addToBGList(int16 objIdx) {
- renderer->incrustSprite(g_cine->_objectTable[objIdx]);
-
createBgIncrustListElement(objIdx, 0);
+
+ renderer->incrustSprite(g_cine->_bgIncrustList.back());
}
/**
@@ -49,9 +49,9 @@ void addToBGList(int16 objIdx) {
* @param objIdx Sprite description
*/
void addSpriteFilledToBGList(int16 objIdx) {
- renderer->incrustMask(g_cine->_objectTable[objIdx]);
-
createBgIncrustListElement(objIdx, 1);
+
+ renderer->incrustMask(g_cine->_bgIncrustList.back());
}
/**
@@ -103,9 +103,9 @@ void loadBgIncrustFromSave(Common::SeekableReadStream &fHandle) {
g_cine->_bgIncrustList.push_back(tmp);
if (tmp.param == 0) {
- renderer->incrustSprite(g_cine->_objectTable[tmp.objIdx]);
+ renderer->incrustSprite(tmp);
} else {
- renderer->incrustMask(g_cine->_objectTable[tmp.objIdx]);
+ renderer->incrustMask(tmp);
}
}
}
diff --git a/engines/cine/cine.cpp b/engines/cine/cine.cpp
index 6b94c33c31..bbe2cd4896 100644
--- a/engines/cine/cine.cpp
+++ b/engines/cine/cine.cpp
@@ -189,6 +189,8 @@ void CineEngine::initialize() {
g_cine->_messageTable.clear();
resetObjectTable();
+ disableSystemMenu = 1;
+
var8 = 0;
var2 = var3 = var4 = var5 = 0;
diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp
index d448f134ff..7a988227f6 100644
--- a/engines/cine/gfx.cpp
+++ b/engines/cine/gfx.cpp
@@ -113,7 +113,7 @@ FWRenderer::FWRenderer() : _background(NULL), _backupPal(), _cmd(""),
assert(_backBuffer);
memset(_backBuffer, 0, _screenSize);
- memset(_bgName, 0, sizeof(_bgName));
+ memset(_bgName, 0, sizeof (_bgName));
}
@@ -174,7 +174,8 @@ void FWRenderer::fillSprite(const ObjectStruct &obj, uint8 color) {
* @param obj Object info
* @param fillColor Sprite color
*/
-void FWRenderer::incrustMask(const ObjectStruct &obj, uint8 color) {
+void FWRenderer::incrustMask(const BGIncrust &incrust, uint8 color) {
+ const ObjectStruct &obj = g_cine->_objectTable[incrust.objIdx];
const byte *data = g_cine->_animDataTable[obj.frame].data();
int x, y, width, height;
@@ -218,7 +219,9 @@ void FWRenderer::drawSprite(const ObjectStruct &obj) {
* Draw color sprite on background
* @param obj Object info
*/
-void FWRenderer::incrustSprite(const ObjectStruct &obj) {
+void FWRenderer::incrustSprite(const BGIncrust &incrust) {
+ const ObjectStruct &obj = g_cine->_objectTable[incrust.objIdx];
+
const byte *data = g_cine->_animDataTable[obj.frame].data();
const byte *mask = g_cine->_animDataTable[obj.frame].mask();
int x, y, width, height;
@@ -246,14 +249,16 @@ void FWRenderer::drawCommand() {
unsigned int i;
int x = 10, y = _cmdY;
- drawPlainBox(x, y, 301, 11, 0);
- drawBorder(x - 1, y - 1, 302, 12, 2);
+ if(disableSystemMenu == 0) {
+ drawPlainBox(x, y, 301, 11, 0);
+ drawBorder(x - 1, y - 1, 302, 12, 2);
- x += 2;
- y += 2;
+ x += 2;
+ y += 2;
- for (i = 0; i < _cmd.size(); i++) {
- x = drawChar(_cmd[i], x, y);
+ for (i = 0; i < _cmd.size(); i++) {
+ x = drawChar(_cmd[i], x, y);
+ }
}
}
@@ -298,10 +303,11 @@ void FWRenderer::drawMessage(const char *str, int x, int y, int width, int color
for (i = 0; str[i]; i++, line--) {
// Fit line of text into textbox
if (!line) {
- while (str[i] == ' ') i++;
+ while (str[i] == ' ')
+ i++;
line = fitLine(str + i, tw, words, cw);
- if (str[i + line] != '\0' && str[i + line] != 0x7C && words) {
+ if ( str[i + line] != '\0' && str[i + line] != 0x7C && words) {
space = (tw - cw) / words;
extraSpace = (tw - cw) % words;
} else {
@@ -1119,7 +1125,8 @@ void OSRenderer::clear() {
* @param obj Object info
* @param fillColor Sprite color
*/
-void OSRenderer::incrustMask(const ObjectStruct &obj, uint8 color) {
+void OSRenderer::incrustMask(const BGIncrust &incrust, uint8 color) {
+ const ObjectStruct &obj = g_cine->_objectTable[incrust.objIdx];
const byte *data = g_cine->_animDataTable[obj.frame].data();
int x, y, width, height;
@@ -1154,15 +1161,16 @@ void OSRenderer::drawSprite(const ObjectStruct &obj) {
* Draw color sprite
* @param obj Object info
*/
-void OSRenderer::incrustSprite(const ObjectStruct &obj) {
- const byte *data = g_cine->_animDataTable[obj.frame].data();
+void OSRenderer::incrustSprite(const BGIncrust &incrust) {
+ const ObjectStruct &obj = g_cine->_objectTable[incrust.objIdx];
+ const byte *data = g_cine->_animDataTable[incrust.frame].data();
int x, y, width, height, transColor;
- x = obj.x;
- y = obj.y;
+ x = incrust.x;
+ y = incrust.y;
transColor = obj.part;
- width = g_cine->_animDataTable[obj.frame]._realWidth;
- height = g_cine->_animDataTable[obj.frame]._height;
+ width = g_cine->_animDataTable[incrust.frame]._realWidth;
+ height = g_cine->_animDataTable[incrust.frame]._height;
if (_bgTable[_currentBg].bg) {
drawSpriteRaw2(data, transColor, width, height, _bgTable[_currentBg].bg, x, y);
@@ -1416,7 +1424,7 @@ void OSRenderer::selectBg(unsigned int idx) {
if (_bgTable[idx].bg) {
assert(_bgTable[idx].pal.isValid() && !(_bgTable[idx].pal.empty()));
- _currentBg = idx;
+ _currentBg = idx;
} else
warning("OSRenderer::selectBg(%d) - attempt to select null background", idx);
reloadPalette();
@@ -1742,23 +1750,23 @@ void OSRenderer::drawSprite(overlay *overlayPtr, const byte *spritePtr, int16 wi
// draw the mask based on next objects in the list
Common::List<overlay>::iterator it;
- for (it = g_cine->_overlayList.begin(); it != g_cine->_overlayList.end(); ++it) {
- if (&(*it) == overlayPtr) {
+ for (it = g_cine->_overlayList.begin(); it != g_cine->_overlayList.end(); ++it) {
+ if(&(*it) == overlayPtr) {
break;
}
}
- while (it != g_cine->_overlayList.end()) {
+ while(it != g_cine->_overlayList.end()) {
overlay *pCurrentOverlay = &(*it);
if ((pCurrentOverlay->type == 5) || ((pCurrentOverlay->type == 21) && (pCurrentOverlay->x == overlayPtr->objIdx))) {
AnimData *sprite = &g_cine->_animDataTable[g_cine->_objectTable[it->objIdx].frame];
if (pMask == NULL) {
- pMask = new byte[width * height];
+ pMask = new byte[width*height];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
- byte spriteColor = spritePtr[width * i + j];
+ byte spriteColor= spritePtr[width * i + j];
pMask[width * i + j] = spriteColor;
}
}
@@ -1769,7 +1777,7 @@ void OSRenderer::drawSprite(overlay *overlayPtr, const byte *spritePtr, int16 wi
int inMaskX = (g_cine->_objectTable[it->objIdx].x + i) - x;
int inMaskY = (g_cine->_objectTable[it->objIdx].y + j) - y;
- if (inMaskX >= 0 && inMaskX < width) {
+ if (inMaskX >=0 && inMaskX < width) {
if (inMaskY >= 0 && inMaskY < height) {
if (sprite->_bpp == 1) {
if (!sprite->getColor(i, j)) {
@@ -1780,23 +1788,27 @@ void OSRenderer::drawSprite(overlay *overlayPtr, const byte *spritePtr, int16 wi
}
}
}
-
-
}
it++;
}
// now, draw with the mask we created
- if (pMask) {
+ if(pMask) {
spritePtr = pMask;
}
+
+ // ignore transparent color in 1bpp
+ if (bpp == 1) {
+ transparentColor = 1;
+ }
+
{
for (int i = 0; i < height; i++) {
byte *destPtr = page + x + y * 320;
destPtr += i * 320;
for (int j = 0; j < width; j++) {
- byte color = *(spritePtr++);
+ byte color= *(spritePtr++);
if ((transparentColor != color) && x + j >= 0 && x + j < 320 && i + y >= 0 && i + y < 200) {
*(destPtr++) = color;
} else {
diff --git a/engines/cine/gfx.h b/engines/cine/gfx.h
index 6ff5b08b77..3434cf9fc2 100644
--- a/engines/cine/gfx.h
+++ b/engines/cine/gfx.h
@@ -27,6 +27,7 @@
#include "common/rect.h"
#include "common/stack.h"
#include "cine/object.h"
+#include "cine/bg_list.h"
namespace Cine {
@@ -177,8 +178,8 @@ public:
void drawFrame();
void setCommand(Common::String cmd);
- virtual void incrustMask(const ObjectStruct &obj, uint8 color = 0);
- virtual void incrustSprite(const ObjectStruct &obj);
+ virtual void incrustMask(const BGIncrust &incrust, uint8 color = 0);
+ virtual void incrustSprite(const BGIncrust &incrust);
virtual void loadBg16(const byte *bg, const char *name, unsigned int idx = 0);
virtual void loadCt16(const byte *ct, const char *name);
@@ -239,8 +240,8 @@ public:
void clear();
- void incrustMask(const ObjectStruct &obj, uint8 color = 0);
- void incrustSprite(const ObjectStruct &obj);
+ void incrustMask(const BGIncrust &incrust, uint8 color = 0);
+ void incrustSprite(const BGIncrust &incrust);
void loadBg16(const byte *bg, const char *name, unsigned int idx = 0);
void loadCt16(const byte *ct, const char *name);
diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp
index 971830ce8f..f13f38a45e 100644
--- a/engines/cine/main_loop.cpp
+++ b/engines/cine/main_loop.cpp
@@ -56,6 +56,12 @@ static void processEvent(Common::Event &event) {
case Common::EVENT_RBUTTONDOWN:
mouseRight = 1;
break;
+ case Common::EVENT_LBUTTONUP:
+ mouseLeft = 0;
+ break;
+ case Common::EVENT_RBUTTONUP:
+ mouseRight = 0;
+ break;
case Common::EVENT_MOUSEMOVE:
break;
case Common::EVENT_KEYDOWN:
@@ -115,7 +121,7 @@ static void processEvent(Common::Event &event) {
}
break;
case Common::KEYCODE_F10:
- if (!disableSystemMenu && !inMenu) {
+ if (!inMenu) {
g_cine->makeSystemMenu();
}
break;
@@ -214,8 +220,6 @@ void manageEvents() {
g_sound->update();
mouseData.left = mouseLeft;
mouseData.right = mouseRight;
- mouseLeft = 0;
- mouseRight = 0;
}
void getMouseData(uint16 param, uint16 *pButton, uint16 *pX, uint16 *pY) {
@@ -311,6 +315,7 @@ void CineEngine::mainLoop(int bootScriptIdx) {
// HACK: Force amount of oxygen left to maximum during Operation Stealth's first arcade sequence.
// This makes it possible to pass the arcade sequence for now.
// FIXME: Remove the hack and make the first arcade sequence normally playable.
+ /*
if (g_cine->getGameType() == Cine::GType_OS) {
Common::String bgName(renderer->getBgName());
// Check if the background is one of the three backgrounds
@@ -320,7 +325,7 @@ void CineEngine::mainLoop(int bootScriptIdx) {
// Force the amount of oxygen left to the maximum.
g_cine->_objectTable[oxygenObjNum].x = maxOxygen;
}
- }
+ }*/
// HACK: In Operation Stealth after the first arcade sequence jump player's position to avoid getting stuck.
// After the first arcade sequence the player comes up stairs from
@@ -379,8 +384,8 @@ void CineEngine::mainLoop(int bootScriptIdx) {
playerAction = false;
_messageLen <<= 3;
- if (_messageLen < 0x800)
- _messageLen = 0x800;
+ if (_messageLen < 800)
+ _messageLen = 800;
do {
manageEvents();
diff --git a/engines/cine/saveload.cpp b/engines/cine/saveload.cpp
index 223099a587..20952eea52 100644
--- a/engines/cine/saveload.cpp
+++ b/engines/cine/saveload.cpp
@@ -991,7 +991,7 @@ void CineEngine::makeSave(char *saveFileName) {
* at a time.
*/
void loadResourcesFromSave(Common::SeekableReadStream &fHandle, enum CineSaveGameFormat saveGameFormat) {
- int16 currentAnim, foundFileIdx;
+ int16 foundFileIdx;
char *animName, part[256], name[10];
strcpy(part, currentPartName);
@@ -1001,10 +1001,10 @@ void loadResourcesFromSave(Common::SeekableReadStream &fHandle, enum CineSaveGam
const int entrySize = ((saveGameFormat == ANIMSIZE_23) ? 23 : 30);
const int fileStartPos = fHandle.pos();
- currentAnim = 0;
- while (currentAnim < NUM_MAX_ANIMDATA) {
+
+ for(int resourceIndex=0; resourceIndex<NUM_MAX_ANIMDATA; resourceIndex++) {
// Seek to the start of the current animation's entry
- fHandle.seek(fileStartPos + currentAnim * entrySize);
+ fHandle.seek(fileStartPos + resourceIndex * entrySize);
// Read in the current animation entry
fHandle.readUint16BE(); // width
fHandle.readUint16BE();
@@ -1019,7 +1019,7 @@ void loadResourcesFromSave(Common::SeekableReadStream &fHandle, enum CineSaveGam
}
foundFileIdx = fHandle.readSint16BE();
- fHandle.readSint16BE(); // frame
+ int16 frameIndex = fHandle.readSint16BE(); // frame
fHandle.read(name, 10);
// Handle variables only present in animation entries of size 23
@@ -1029,7 +1029,7 @@ void loadResourcesFromSave(Common::SeekableReadStream &fHandle, enum CineSaveGam
// Don't try to load invalid entries.
if (foundFileIdx < 0 || !validPtr) {
- currentAnim++; // Jump over the invalid entry
+ //resourceIndex++; // Jump over the invalid entry
continue;
}
@@ -1041,9 +1041,7 @@ void loadResourcesFromSave(Common::SeekableReadStream &fHandle, enum CineSaveGam
animName = g_cine->_partBuffer[foundFileIdx].partName;
loadRelatedPalette(animName); // Is this for Future Wars only?
- const int16 prevAnim = currentAnim;
- currentAnim = loadResource(animName, currentAnim);
- assert(currentAnim > prevAnim); // Make sure we advance forward
+ loadResource(animName, resourceIndex, frameIndex);
}
loadPart(part);
diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp
index 66150cc5b2..9cbe3c3fab 100644
--- a/engines/cine/script_fw.cpp
+++ b/engines/cine/script_fw.cpp
@@ -533,7 +533,6 @@ void RawScript::setData(const FWScriptInfo &info, const byte *data) {
* @return Precalculated script labels
*/
const ScriptVars &RawScript::labels() const {
- assert(_data);
return _labels;
}
@@ -687,7 +686,7 @@ const char *FWScript::getNextString() {
* @param pos Restored script position
*/
void FWScript::load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) {
- assert(pos < _script._size);
+ assert(pos <= _script._size);
_labels = labels;
_localVars = local;
_compare = compare;
@@ -705,13 +704,15 @@ void FWScript::load(const ScriptVars &labels, const ScriptVars &local, uint16 co
int FWScript::execute() {
int ret = 0;
- while (!ret) {
- _line = _pos;
- byte opcode = getNextByte();
- OpFunc handler = _info->opcodeHandler(opcode);
+ if(_script._size) {
+ while (!ret) {
+ _line = _pos;
+ byte opcode = getNextByte();
+ OpFunc handler = _info->opcodeHandler(opcode);
- if (handler) {
- ret = (this->*handler)();
+ if (handler) {
+ ret = (this->*handler)();
+ }
}
}
@@ -1861,7 +1862,7 @@ int FWScript::o1_disableSystemMenu() {
byte param = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: disableSystemMenu(%d)", _line, param);
- disableSystemMenu = (param != 0);
+ disableSystemMenu = param;
return 0;
}
diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp
index 9b73ae1101..eccd71cf05 100644
--- a/engines/cine/various.cpp
+++ b/engines/cine/various.cpp
@@ -36,7 +36,7 @@
namespace Cine {
-bool disableSystemMenu = false;
+int16 disableSystemMenu = 0;
bool inMenu;
int16 commandVar3[4];
@@ -341,7 +341,7 @@ void CineEngine::makeSystemMenu() {
int16 mouseX, mouseY, mouseButton;
int16 selectedSave;
- if (!disableSystemMenu) {
+ if (disableSystemMenu != 1) {
inMenu = true;
do {
@@ -544,14 +544,16 @@ int16 buildObjectListCommand(int16 param) {
int16 selectSubObject(int16 x, int16 y, int16 param) {
int16 listSize = buildObjectListCommand(param);
- int16 selectedObject;
+ int16 selectedObject = -1;
bool osExtras = g_cine->getGameType() == Cine::GType_OS;
if (!listSize) {
return -2;
}
- selectedObject = makeMenuChoice(objectListCommand, listSize, x, y, 140, osExtras);
+ if (disableSystemMenu == 0) {
+ selectedObject = makeMenuChoice(objectListCommand, listSize, x, y, 140, osExtras);
+ }
if (selectedObject == -1)
return -1;
@@ -691,9 +693,6 @@ int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X,
int16 var_4;
SelectionMenu *menu;
- if (disableSystemMenu)
- return -1;
-
paramY = (height * 9) + 10;
if (X + width > 319) {
@@ -810,14 +809,18 @@ void makeActionMenu() {
getMouseData(mouseUpdateStatus, &mouseButton, &mouseX, &mouseY);
if (g_cine->getGameType() == Cine::GType_OS) {
- playerCommand = makeMenuChoice(defaultActionCommand, 6, mouseX, mouseY, 70, true);
+ if(disableSystemMenu == 0) {
+ playerCommand = makeMenuChoice(defaultActionCommand, 6, mouseX, mouseY, 70, true);
+ }
if (playerCommand >= 8000) {
playerCommand -= 8000;
canUseOnObject = canUseOnItemTable[playerCommand];
}
} else {
- playerCommand = makeMenuChoice(defaultActionCommand, 6, mouseX, mouseY, 70);
+ if(disableSystemMenu == 0) {
+ playerCommand = makeMenuChoice(defaultActionCommand, 6, mouseX, mouseY, 70);
+ }
}
inMenu = false;
diff --git a/engines/cine/various.h b/engines/cine/various.h
index 0c1883c323..813619816d 100644
--- a/engines/cine/various.h
+++ b/engines/cine/various.h
@@ -41,7 +41,7 @@ void makeActionMenu();
void waitPlayerInput();
void setTextWindow(uint16 param1, uint16 param2, uint16 param3, uint16 param4);
-extern bool disableSystemMenu;
+extern int16 disableSystemMenu;
extern bool inMenu;
extern CommandeType currentSaveName[10];
diff --git a/engines/lastexpress/data/background.cpp b/engines/lastexpress/data/background.cpp
index 3d866c26f9..60379251a3 100644
--- a/engines/lastexpress/data/background.cpp
+++ b/engines/lastexpress/data/background.cpp
@@ -107,6 +107,7 @@ byte *Background::decodeComponent(Common::SeekableReadStream *in, uint32 inSize,
return NULL;
// Initialize the decoding
+ memset(out, 0, outSize * sizeof(byte));
uint32 inPos = 0;
uint32 outPos = 0;
diff --git a/engines/lastexpress/data/subtitle.cpp b/engines/lastexpress/data/subtitle.cpp
index a9a8284588..4d19c02aa7 100644
--- a/engines/lastexpress/data/subtitle.cpp
+++ b/engines/lastexpress/data/subtitle.cpp
@@ -210,10 +210,10 @@ void SubtitleManager::setTime(uint16 time) {
_currentIndex = -1;
// Find the appropriate line to show
- for (int16 i = 0; i < (int16)_subtitles.size(); i++) {
+ for (uint i = 0; i < _subtitles.size(); i++) {
if ((time >= _subtitles[i]->getTimeStart()) && (time <= _subtitles[i]->getTimeStop())) {
// Keep the index of the line to show
- _currentIndex = i;
+ _currentIndex = (int16)i;
return;
}
}
@@ -237,7 +237,7 @@ Common::Rect SubtitleManager::draw(Graphics::Surface *surface) {
// Draw the current line
assert(_currentIndex >= 0 && _currentIndex < (int16)_subtitles.size());
- return _subtitles[_currentIndex]->draw(surface, _font);
+ return _subtitles[(uint16)_currentIndex]->draw(surface, _font);
}
} // End of namespace LastExpress
diff --git a/engines/lastexpress/debug.cpp b/engines/lastexpress/debug.cpp
index f89ad8b80d..db3a3e3962 100644
--- a/engines/lastexpress/debug.cpp
+++ b/engines/lastexpress/debug.cpp
@@ -85,7 +85,6 @@ Debugger::Debugger(LastExpressEngine *engine) : _engine(engine), _command(NULL),
DCmd_Register("entity", WRAP_METHOD(Debugger, cmdEntity));
// Misc
- DCmd_Register("loadgame", WRAP_METHOD(Debugger, cmdLoadGame));
DCmd_Register("chapter", WRAP_METHOD(Debugger, cmdSwitchChapter));
DCmd_Register("clear", WRAP_METHOD(Debugger, cmdClear));
@@ -139,6 +138,9 @@ void Debugger::copyCommand(int argc, const char **argv) {
for (int i = 0; i < _numParams; i++) {
_commandParams[i] = (char *)malloc(strlen(argv[i]) + 1);
+ if (_commandParams[i] == NULL)
+ error("[Debugger::copyCommand] Cannot allocate memory for command parameters");
+
memset(_commandParams[i], 0, strlen(argv[i]) + 1);
strcpy(_commandParams[i], argv[i]);
}
@@ -152,9 +154,18 @@ void Debugger::callCommand() {
(*_command)(_numParams, const_cast<const char **>(_commandParams));
}
-void Debugger::loadArchive(ArchiveIndex index) const {
- _engine->getResourceManager()->loadArchive(index);
- getScenes()->loadSceneDataFile(index);
+bool Debugger::loadArchive(int index) {
+ if (index < 1 || index > 3) {
+ DebugPrintf("Invalid cd number (was: %d, valid: [1-3])\n", index);
+ return false;
+ }
+
+ if (!_engine->getResourceManager()->loadArchive((ArchiveIndex)index))
+ return false;
+
+ getScenes()->loadSceneDataFile((ArchiveIndex)index);
+
+ return true;
}
// Restore loaded archive
@@ -233,8 +244,10 @@ bool Debugger::cmdListFiles(int argc, const char **argv) {
Common::String filter(const_cast<char *>(argv[1]));
// Load the proper archive
- if (argc == 3)
- loadArchive((ArchiveIndex)getNumber(argv[2]));
+ if (argc == 3) {
+ if (!loadArchive(getNumber(argv[2])))
+ return true;
+ }
Common::ArchiveMemberList list;
int count = _engine->getResourceManager()->listMatchingMembers(list, filter);
@@ -317,8 +330,10 @@ bool Debugger::cmdShowFrame(int argc, const char **argv) {
Common::String filename(const_cast<char *>(argv[1]));
filename += ".seq";
- if (argc == 4)
- loadArchive((ArchiveIndex)getNumber(argv[3]));
+ if (argc == 4) {
+ if (!loadArchive(getNumber(argv[3])))
+ return true;
+ }
if (!_engine->getResourceManager()->hasFile(filename)) {
DebugPrintf("Cannot find file: %s\n", filename.c_str());
@@ -377,8 +392,10 @@ bool Debugger::cmdShowBg(int argc, const char **argv) {
if (argc == 2 || argc == 3) {
Common::String filename(const_cast<char *>(argv[1]));
- if (argc == 3)
- loadArchive((ArchiveIndex)getNumber(argv[2]));
+ if (argc == 3) {
+ if (!loadArchive(getNumber(argv[2])))
+ return true;
+ }
if (!_engine->getResourceManager()->hasFile(filename + ".BG")) {
DebugPrintf("Cannot find file: %s\n", (filename + ".BG").c_str());
@@ -430,8 +447,10 @@ bool Debugger::cmdPlaySeq(int argc, const char **argv) {
Common::String filename(const_cast<char *>(argv[1]));
filename += ".seq";
- if (argc == 3)
- loadArchive((ArchiveIndex)getNumber(argv[2]));
+ if (argc == 3) {
+ if (!loadArchive(getNumber(argv[2])))
+ return true;
+ }
if (!_engine->getResourceManager()->hasFile(filename)) {
DebugPrintf("Cannot find file: %s\n", filename.c_str());
@@ -505,8 +524,10 @@ bool Debugger::cmdPlaySeq(int argc, const char **argv) {
bool Debugger::cmdPlaySnd(int argc, const char **argv) {
if (argc == 2 || argc == 3) {
- if (argc == 3)
- loadArchive((ArchiveIndex)getNumber(argv[2]));
+ if (argc == 3) {
+ if (!loadArchive(getNumber(argv[2])))
+ return true;
+ }
// Add .SND at the end of the filename if needed
Common::String name(const_cast<char *>(argv[1]));
@@ -520,7 +541,7 @@ bool Debugger::cmdPlaySnd(int argc, const char **argv) {
_engine->_system->getMixer()->stopAll();
- _soundStream->load(getArchive(name));
+ _soundStream->load(getArchive(name), 16);
if (argc == 3)
restoreArchive();
@@ -542,8 +563,10 @@ bool Debugger::cmdPlaySbe(int argc, const char **argv) {
if (argc == 2 || argc == 3) {
Common::String filename(const_cast<char *>(argv[1]));
- if (argc == 3)
- loadArchive((ArchiveIndex)getNumber(argv[2]));
+ if (argc == 3) {
+ if (!loadArchive(getNumber(argv[2])))
+ return true;
+ }
filename += ".sbe";
@@ -605,8 +628,10 @@ bool Debugger::cmdPlayNis(int argc, const char **argv) {
if (argc == 2 || argc == 3) {
Common::String name(const_cast<char *>(argv[1]));
- if (argc == 3)
- loadArchive((ArchiveIndex)getNumber(argv[2]));
+ if (argc == 3) {
+ if (!loadArchive(getNumber(argv[2])))
+ return true;
+ }
// If we got a nis filename, check that the file exists
if (name.contains('.') && !_engine->getResourceManager()->hasFile(name)) {
@@ -662,8 +687,10 @@ bool Debugger::cmdLoadScene(int argc, const char **argv) {
SceneIndex index = (SceneIndex)getNumber(argv[1]);
// Check args
- if (argc == 3)
- loadArchive((ArchiveIndex)getNumber(argv[2]));
+ if (argc == 3) {
+ if (!loadArchive(getNumber(argv[2])))
+ return true;
+ }
if (index > 2500) {
DebugPrintf("Error: invalid index value (0-2500)");
@@ -1091,30 +1118,6 @@ label_error:
}
/**
- * Command: loads a game
- *
- * @param argc The argument count.
- * @param argv The values.
- *
- * @return true if it was handled, false otherwise
- */
-bool Debugger::cmdLoadGame(int argc, const char **argv) {
- if (argc == 2) {
- int id = getNumber(argv[1]);
-
- if (id == 0 || id > 6)
- goto error;
-
- getSaveLoad()->loadGame((GameId)(id - 1));
- } else {
-error:
- DebugPrintf("Syntax: loadgame <id> (id=1-6)\n");
- }
-
- return true;
-}
-
-/**
* Command: switch to a specific chapter
*
* @param argc The argument count.
diff --git a/engines/lastexpress/debug.h b/engines/lastexpress/debug.h
index d9ba6f47a1..532cb83717 100644
--- a/engines/lastexpress/debug.h
+++ b/engines/lastexpress/debug.h
@@ -79,7 +79,6 @@ private:
bool cmdShow(int argc, const char **argv);
bool cmdEntity(int argc, const char **argv);
- bool cmdLoadGame(int argc, const char **argv);
bool cmdSwitchChapter(int argc, const char **argv);
bool cmdClear(int argc, const char **argv);
@@ -87,7 +86,7 @@ private:
void copyCommand(int argc, const char **argv);
int getNumber(const char *arg) const;
- void loadArchive(ArchiveIndex index) const;
+ bool loadArchive(int index);
void restoreArchive() const;
Debuglet *_command;
diff --git a/engines/lastexpress/entities/abbot.cpp b/engines/lastexpress/entities/abbot.cpp
index e0fe429520..406b017d3a 100644
--- a/engines/lastexpress/entities/abbot.cpp
+++ b/engines/lastexpress/entities/abbot.cpp
@@ -58,10 +58,10 @@ Abbot::Abbot(LastExpressEngine *engine) : Entity(engine, kEntityAbbot) {
ADD_CALLBACK_FUNCTION(Abbot, chapter2);
ADD_CALLBACK_FUNCTION(Abbot, chapter3);
ADD_CALLBACK_FUNCTION(Abbot, chapter3Handler);
- ADD_CALLBACK_FUNCTION(Abbot, function19);
- ADD_CALLBACK_FUNCTION(Abbot, function20);
- ADD_CALLBACK_FUNCTION(Abbot, function21);
- ADD_CALLBACK_FUNCTION(Abbot, function22);
+ ADD_CALLBACK_FUNCTION(Abbot, conversationWithBoutarel);
+ ADD_CALLBACK_FUNCTION(Abbot, readPaper);
+ ADD_CALLBACK_FUNCTION(Abbot, goToLunch);
+ ADD_CALLBACK_FUNCTION(Abbot, haveLunch);
ADD_CALLBACK_FUNCTION(Abbot, function23);
ADD_CALLBACK_FUNCTION(Abbot, function24);
ADD_CALLBACK_FUNCTION(Abbot, function25);
@@ -259,7 +259,7 @@ IMPLEMENT_FUNCTION(18, Abbot, chapter3Handler)
getData()->entityPosition = kPosition_6470;
getData()->location = kLocationInsideCompartment;
- setup_function19();
+ setup_conversationWithBoutarel();
break;
}
break;
@@ -272,7 +272,7 @@ IMPLEMENT_FUNCTION(18, Abbot, chapter3Handler)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(19, Abbot, function19)
+IMPLEMENT_FUNCTION(19, Abbot, conversationWithBoutarel)
switch (savepoint.action) {
default:
break;
@@ -311,21 +311,21 @@ IMPLEMENT_FUNCTION(19, Abbot, function19)
case 3:
getSavePoints()->push(kEntityAbbot, kEntityBoutarel, kAction122288808);
- setup_function20();
+ setup_readPaper();
break;
}
}
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(20, Abbot, function20)
+IMPLEMENT_FUNCTION(20, Abbot, readPaper)
switch (savepoint.action) {
default:
break;
case kActionNone:
if (getState()->time > kTime1966500 && getEntities()->isInRestaurant(kEntityBoutarel))
- setup_function21();
+ setup_goToLunch();
break;
case kActionDefault:
@@ -335,7 +335,7 @@ IMPLEMENT_FUNCTION(20, Abbot, function20)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(21, Abbot, function21)
+IMPLEMENT_FUNCTION(21, Abbot, goToLunch)
switch (savepoint.action) {
default:
break;
@@ -393,7 +393,7 @@ IMPLEMENT_FUNCTION(21, Abbot, function21)
break;
case 7:
- setup_function22();
+ setup_haveLunch();
break;
}
break;
@@ -409,7 +409,7 @@ IMPLEMENT_FUNCTION(21, Abbot, function21)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(22, Abbot, function22)
+IMPLEMENT_FUNCTION(22, Abbot, haveLunch)
switch (savepoint.action) {
default:
break;
@@ -1547,7 +1547,7 @@ IMPLEMENT_FUNCTION(45, Abbot, function45)
getData()->car = kCarRedSleeping;
getData()->location = kLocationOutsideCompartment;
- RESET_ENTITY_STATE(kEntityVerges, Verges, setup_function38);
+ RESET_ENTITY_STATE(kEntityVerges, Verges, setup_resetState);
getEntities()->drawSequenceLeft(kEntityAbbot, "617Ec");
getEntities()->enterCompartment(kEntityAbbot, kObjectCompartmentC, true);
diff --git a/engines/lastexpress/entities/abbot.h b/engines/lastexpress/entities/abbot.h
index ce52bb68ce..dc3e86db54 100644
--- a/engines/lastexpress/entities/abbot.h
+++ b/engines/lastexpress/entities/abbot.h
@@ -156,10 +156,10 @@ public:
* Handle Chapter 3 events
*/
DECLARE_FUNCTION(chapter3Handler)
- DECLARE_FUNCTION(function19)
- DECLARE_FUNCTION(function20)
- DECLARE_FUNCTION(function21)
- DECLARE_FUNCTION(function22)
+ DECLARE_FUNCTION(conversationWithBoutarel)
+ DECLARE_FUNCTION(readPaper)
+ DECLARE_FUNCTION(goToLunch)
+ DECLARE_FUNCTION(haveLunch)
DECLARE_FUNCTION(function23)
DECLARE_FUNCTION(function24)
DECLARE_FUNCTION(function25)
diff --git a/engines/lastexpress/entities/august.cpp b/engines/lastexpress/entities/august.cpp
index 67d810fde2..dbae7bad20 100644
--- a/engines/lastexpress/entities/august.cpp
+++ b/engines/lastexpress/entities/august.cpp
@@ -3530,7 +3530,7 @@ IMPLEMENT_FUNCTION(69, August, unhookCars)
getScenes()->loadSceneFromPosition(kCarRestaurant, 85, 1);
getSavePoints()->pushAll(kEntityAugust, kActionProceedChapter5);
- RESET_ENTITY_STATE(kEntityVerges, Verges, setup_function42)
+ RESET_ENTITY_STATE(kEntityVerges, Verges, setup_end)
}
break;
}
diff --git a/engines/lastexpress/entities/chapters.cpp b/engines/lastexpress/entities/chapters.cpp
index a2f3a3d871..d373432710 100644
--- a/engines/lastexpress/entities/chapters.cpp
+++ b/engines/lastexpress/entities/chapters.cpp
@@ -1851,7 +1851,7 @@ void Chapters::enterExitHelper(bool isEnteringStation) {
callbackAction();
}
-void Chapters::playSteam() {
+void Chapters::playSteam() const {
getSoundQueue()->resetState();
getSound()->playSteam((CityIndex)ENTITY_PARAM(0, 4));
ENTITY_PARAM(0, 2) = 0;
diff --git a/engines/lastexpress/entities/chapters.h b/engines/lastexpress/entities/chapters.h
index ddb3de3bea..fb52ea3ee4 100644
--- a/engines/lastexpress/entities/chapters.h
+++ b/engines/lastexpress/entities/chapters.h
@@ -157,7 +157,7 @@ private:
bool timeCheckExitStation(TimeValue timeValue, uint &parameter, byte callback, const char *sequence);
void enterExitStation(const SavePoint &savepoint, bool isEnteringStation);
void enterExitHelper(bool isEnteringStation);
- void playSteam();
+ void playSteam() const;
};
} // End of namespace LastExpress
diff --git a/engines/lastexpress/entities/entity.cpp b/engines/lastexpress/entities/entity.cpp
index 2deca291f6..dad5e67392 100644
--- a/engines/lastexpress/entities/entity.cpp
+++ b/engines/lastexpress/entities/entity.cpp
@@ -26,10 +26,15 @@
#include "lastexpress/game/action.h"
#include "lastexpress/game/entities.h"
+#include "lastexpress/game/logic.h"
#include "lastexpress/game/object.h"
#include "lastexpress/game/savegame.h"
+#include "lastexpress/game/savepoint.h"
+#include "lastexpress/game/state.h"
#include "lastexpress/game/scenes.h"
+#include "lastexpress/lastexpress.h"
+
namespace LastExpress {
//////////////////////////////////////////////////////////////////////////
@@ -45,12 +50,14 @@ EntityData::EntityCallData::~EntityCallData() {
SAFE_DELETE(sequence3);
}
-void EntityData::EntityCallData::syncString(Common::Serializer &s, Common::String &string, int length) {
+void EntityData::EntityCallData::syncString(Common::Serializer &s, Common::String &string, uint length) const {
char seqName[13];
memset(&seqName, 0, length);
- if (s.isSaving()) strcpy((char *)&seqName, string.c_str());
- s.syncBytes((byte *)&seqName, length);
+ if (s.isSaving())
+ strcpy((char *)&seqName, string.c_str());
+
+ s.syncBytes((byte *)&seqName, length);
if (s.isLoading())
string = seqName;
@@ -110,7 +117,7 @@ EntityData::EntityParameters *EntityData::getParameters(uint callback, byte inde
return _parameters[callback].parameters[index];
}
-int EntityData::getCallback(uint callback) const {
+byte EntityData::getCallback(uint callback) const {
if (callback >= 16)
error("[EntityData::getCallback] Invalid callback value (was: %d, max: 16)", callback);
@@ -818,7 +825,7 @@ void Entity::setupIISS(const char *name, uint index, uint param1, uint param2, c
// Helper functions
//////////////////////////////////////////////////////////////////////////
-bool Entity::updateParameter(uint &parameter, uint timeType, uint delta) {
+bool Entity::updateParameter(uint &parameter, uint timeType, uint delta) const {
if (!parameter)
parameter = (uint)(timeType + delta);
@@ -830,7 +837,7 @@ bool Entity::updateParameter(uint &parameter, uint timeType, uint delta) {
return true;
}
-bool Entity::updateParameterTime(TimeValue timeValue, bool check, uint &parameter, uint delta) {
+bool Entity::updateParameterTime(TimeValue timeValue, bool check, uint &parameter, uint delta) const {
if (getState()->time <= timeValue) {
if (check || !parameter)
parameter = (uint)(getState()->time + delta);
@@ -844,7 +851,7 @@ bool Entity::updateParameterTime(TimeValue timeValue, bool check, uint &paramete
return true;
}
-bool Entity::updateParameterCheck(uint &parameter, uint timeType, uint delta) {
+bool Entity::updateParameterCheck(uint &parameter, uint timeType, uint delta) const {
if (parameter && parameter >= timeType)
return false;
@@ -854,7 +861,7 @@ bool Entity::updateParameterCheck(uint &parameter, uint timeType, uint delta) {
return true;
}
-bool Entity::timeCheck(TimeValue timeValue, uint &parameter, Common::Functor0<void> *function) {
+bool Entity::timeCheck(TimeValue timeValue, uint &parameter, Common::Functor0<void> *function) const {
if (getState()->time > timeValue && !parameter) {
parameter = 1;
(*function)();
@@ -929,14 +936,14 @@ bool Entity::timeCheckCar(TimeValue timeValue, uint &parameter, byte callback, C
return false;
}
-void Entity::timeCheckSavepoint(TimeValue timeValue, uint &parameter, EntityIndex entity1, EntityIndex entity2, ActionIndex action) {
+void Entity::timeCheckSavepoint(TimeValue timeValue, uint &parameter, EntityIndex entity1, EntityIndex entity2, ActionIndex action) const {
if (getState()->time > timeValue && !parameter) {
parameter = 1;
getSavePoints()->push(entity1, entity2, action);
}
}
-void Entity::timeCheckObject(TimeValue timeValue, uint &parameter, ObjectIndex object, ObjectLocation location) {
+void Entity::timeCheckObject(TimeValue timeValue, uint &parameter, ObjectIndex object, ObjectLocation location) const {
if (getState()->time > timeValue && !parameter) {
parameter = 1;
getObjects()->updateLocation2(object, location);
diff --git a/engines/lastexpress/entities/entity.h b/engines/lastexpress/entities/entity.h
index 3601f34f6f..c67d13db9e 100644
--- a/engines/lastexpress/entities/entity.h
+++ b/engines/lastexpress/entities/entity.h
@@ -25,13 +25,8 @@
#include "lastexpress/shared.h"
-#include "lastexpress/game/logic.h"
-#include "lastexpress/game/savepoint.h"
-#include "lastexpress/game/state.h"
-
#include "lastexpress/sound/sound.h"
-#include "lastexpress/lastexpress.h"
#include "lastexpress/helpers.h"
#include "common/array.h"
@@ -827,7 +822,7 @@ public:
* @param string The string.
* @param length Length of the string.
*/
- void syncString(Common::Serializer &s, Common::String &string, int length);
+ void syncString(Common::Serializer &s, Common::String &string, uint length) const;
// Serializable
void saveLoadWithSerializer(Common::Serializer &s);
@@ -850,8 +845,8 @@ public:
EntityParameters *getCurrentParameters(byte index = 0) { return getParameters(_data.currentCall, index); }
EntityCallParameters *getCurrentCallParameters() { return &_parameters[_data.currentCall]; }
- int getCallback(uint callback) const;
- int getCurrentCallback() { return getCallback(_data.currentCall); }
+ byte getCallback(uint callback) const;
+ byte getCurrentCallback() { return getCallback(_data.currentCall); }
void setCallback(uint callback, byte index);
void setCurrentCallback(uint index) { setCallback(_data.currentCall, index); }
@@ -1089,18 +1084,18 @@ protected:
// Helper functions
//////////////////////////////////////////////////////////////////////////
- bool updateParameter(uint &parameter, uint timeType, uint delta);
- bool updateParameterCheck(uint &parameter, uint timeType, uint delta);
- bool updateParameterTime(TimeValue timeValue, bool check, uint &parameter, uint delta);
+ bool updateParameter(uint &parameter, uint timeType, uint delta) const;
+ bool updateParameterCheck(uint &parameter, uint timeType, uint delta) const;
+ bool updateParameterTime(TimeValue timeValue, bool check, uint &parameter, uint delta) const;
- bool timeCheck(TimeValue timeValue, uint &parameter, Common::Functor0<void> *function);
+ bool timeCheck(TimeValue timeValue, uint &parameter, Common::Functor0<void> *function) const;
bool timeCheckCallback(TimeValue timeValue, uint &parameter, byte callback, Common::Functor0<void> *function);
bool timeCheckCallback(TimeValue timeValue, uint &parameter, byte callback, const char *str, Common::Functor1<const char *, void> *function);
bool timeCheckCallback(TimeValue timeValue, uint &parameter, byte callback, bool check, Common::Functor1<bool, void> *function);
bool timeCheckCallbackInventory(TimeValue timeValue, uint &parameter, byte callback, Common::Functor0<void> *function);
bool timeCheckCar(TimeValue timeValue, uint &parameter, byte callback, Common::Functor0<void> *function);
- void timeCheckSavepoint(TimeValue timeValue, uint &parameter, EntityIndex entity1, EntityIndex entity2, ActionIndex action);
- void timeCheckObject(TimeValue timeValue, uint &parameter, ObjectIndex index, ObjectLocation location);
+ void timeCheckSavepoint(TimeValue timeValue, uint &parameter, EntityIndex entity1, EntityIndex entity2, ActionIndex action) const;
+ void timeCheckObject(TimeValue timeValue, uint &parameter, ObjectIndex index, ObjectLocation location) const;
bool timeCheckCallbackAction(TimeValue timeValue, uint &parameter);
bool timeCheckPlaySoundUpdatePosition(TimeValue timeValue, uint &parameter, byte callback, const char* sound, EntityPosition position);
diff --git a/engines/lastexpress/entities/verges.cpp b/engines/lastexpress/entities/verges.cpp
index 867f122d8f..d9ddb0a4d1 100644
--- a/engines/lastexpress/entities/verges.cpp
+++ b/engines/lastexpress/entities/verges.cpp
@@ -46,40 +46,40 @@ Verges::Verges(LastExpressEngine *engine) : Entity(engine, kEntityVerges) {
ADD_CALLBACK_FUNCTION(Verges, callbackActionRestaurantOrSalon);
ADD_CALLBACK_FUNCTION(Verges, savegame);
ADD_CALLBACK_FUNCTION(Verges, updateEntity);
- ADD_CALLBACK_FUNCTION(Verges, function9);
- ADD_CALLBACK_FUNCTION(Verges, function10);
+ ADD_CALLBACK_FUNCTION(Verges, walkBetweenCars);
+ ADD_CALLBACK_FUNCTION(Verges, makeAnnouncement);
ADD_CALLBACK_FUNCTION(Verges, function11);
ADD_CALLBACK_FUNCTION(Verges, function12);
- ADD_CALLBACK_FUNCTION(Verges, function13);
+ ADD_CALLBACK_FUNCTION(Verges, baggageCar);
ADD_CALLBACK_FUNCTION(Verges, updateFromTime);
- ADD_CALLBACK_FUNCTION(Verges, function15);
- ADD_CALLBACK_FUNCTION(Verges, function16);
- ADD_CALLBACK_FUNCTION(Verges, function17);
+ ADD_CALLBACK_FUNCTION(Verges, dialog);
+ ADD_CALLBACK_FUNCTION(Verges, dialog2);
+ ADD_CALLBACK_FUNCTION(Verges, talkAboutPassengerList);
ADD_CALLBACK_FUNCTION(Verges, chapter1);
ADD_CALLBACK_FUNCTION(Verges, talkHarem);
ADD_CALLBACK_FUNCTION(Verges, talkPassengerList);
ADD_CALLBACK_FUNCTION(Verges, talkGendarmes);
- ADD_CALLBACK_FUNCTION(Verges, function22);
+ ADD_CALLBACK_FUNCTION(Verges, askMertensToRelayAugustInvitation);
ADD_CALLBACK_FUNCTION(Verges, function23);
ADD_CALLBACK_FUNCTION(Verges, policeGettingOffTrain);
- ADD_CALLBACK_FUNCTION(Verges, function25);
+ ADD_CALLBACK_FUNCTION(Verges, policeSearch);
ADD_CALLBACK_FUNCTION(Verges, chapter1Handler);
ADD_CALLBACK_FUNCTION(Verges, chapter2);
ADD_CALLBACK_FUNCTION(Verges, chapter2Handler);
ADD_CALLBACK_FUNCTION(Verges, chapter3);
ADD_CALLBACK_FUNCTION(Verges, function30);
- ADD_CALLBACK_FUNCTION(Verges, function31);
+ ADD_CALLBACK_FUNCTION(Verges, talkAboutMax);
ADD_CALLBACK_FUNCTION(Verges, function32);
ADD_CALLBACK_FUNCTION(Verges, function33);
ADD_CALLBACK_FUNCTION(Verges, function34);
- ADD_CALLBACK_FUNCTION(Verges, function35);
+ ADD_CALLBACK_FUNCTION(Verges, organizeConcertInvitations);
ADD_CALLBACK_FUNCTION(Verges, chapter4);
ADD_CALLBACK_FUNCTION(Verges, chapter4Handler);
- ADD_CALLBACK_FUNCTION(Verges, function38);
+ ADD_CALLBACK_FUNCTION(Verges, resetState);
ADD_CALLBACK_FUNCTION(Verges, chapter5);
ADD_CALLBACK_FUNCTION(Verges, chapter5Handler);
- ADD_CALLBACK_FUNCTION(Verges, function41);
- ADD_CALLBACK_FUNCTION(Verges, function42);
+ ADD_CALLBACK_FUNCTION(Verges, askPassengersToStayInCompartments);
+ ADD_CALLBACK_FUNCTION(Verges, end);
}
//////////////////////////////////////////////////////////////////////////
@@ -149,7 +149,7 @@ IMPLEMENT_FUNCTION_II(8, Verges, updateEntity, CarIndex, EntityPosition)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_S(9, Verges, function9)
+IMPLEMENT_FUNCTION_S(9, Verges, walkBetweenCars)
switch (savepoint.action) {
default:
break;
@@ -201,7 +201,7 @@ switch (savepoint.action) {
case 3:
setCallback(4);
- setup_function10(kCarGreenSleeping, kPosition_540, (char *)&params->seq1);
+ setup_makeAnnouncement(kCarGreenSleeping, kPosition_540, (char *)&params->seq1);
break;
case 4:
@@ -225,7 +225,7 @@ switch (savepoint.action) {
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_IIS(10, Verges, function10, CarIndex, EntityPosition)
+IMPLEMENT_FUNCTION_IIS(10, Verges, makeAnnouncement, CarIndex, EntityPosition)
switch (savepoint.action) {
default:
break;
@@ -404,7 +404,7 @@ IMPLEMENT_FUNCTION(12, Verges, function12)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_I(13, Verges, function13, bool)
+IMPLEMENT_FUNCTION_I(13, Verges, baggageCar, bool)
switch (savepoint.action) {
default:
break;
@@ -449,7 +449,7 @@ IMPLEMENT_FUNCTION_I(14, Verges, updateFromTime, uint32)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_IS(15, Verges, function15, EntityIndex)
+IMPLEMENT_FUNCTION_IS(15, Verges, dialog, EntityIndex)
switch (savepoint.action) {
default:
break;
@@ -486,7 +486,7 @@ IMPLEMENT_FUNCTION_IS(15, Verges, function15, EntityIndex)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION_ISS(16, Verges, function16, EntityIndex)
+IMPLEMENT_FUNCTION_ISS(16, Verges, dialog2, EntityIndex)
switch (savepoint.action) {
default:
break;
@@ -526,7 +526,7 @@ IMPLEMENT_FUNCTION_ISS(16, Verges, function16, EntityIndex)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(17, Verges, function17)
+IMPLEMENT_FUNCTION(17, Verges, talkAboutPassengerList)
switch (savepoint.action) {
default:
break;
@@ -548,7 +548,7 @@ IMPLEMENT_FUNCTION(17, Verges, function17)
case 2:
setCallback(3);
- setup_function15(kEntityMertens, "TRA1291");
+ setup_dialog(kEntityMertens, "TRA1291");
break;
case 3:
@@ -611,7 +611,7 @@ IMPLEMENT_FUNCTION(21, Verges, talkGendarmes)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(22, Verges, function22)
+IMPLEMENT_FUNCTION(22, Verges, askMertensToRelayAugustInvitation)
switch (savepoint.action) {
default:
break;
@@ -634,10 +634,10 @@ IMPLEMENT_FUNCTION(22, Verges, function22)
case 2:
if (getEvent(kEventMertensAskTylerCompartment) || getEvent(kEventMertensAskTylerCompartmentD) || getEvent(kEventMertensAugustWaiting)) {
setCallback(3);
- setup_function16(kEntityMertens, "TRA1200", "TRA1201");
+ setup_dialog2(kEntityMertens, "TRA1200", "TRA1201");
} else {
setCallback(4);
- setup_function16(kEntityMertens, "TRA1200A", "TRA1201");
+ setup_dialog2(kEntityMertens, "TRA1200A", "TRA1201");
}
break;
@@ -714,7 +714,7 @@ IMPLEMENT_FUNCTION(24, Verges, policeGettingOffTrain)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(25, Verges, function25)
+IMPLEMENT_FUNCTION(25, Verges, policeSearch)
switch (savepoint.action) {
default:
break;
@@ -774,10 +774,10 @@ IMPLEMENT_FUNCTION(25, Verges, function25)
if (getData()->car == kCarRedSleeping) {
setCallback(6);
- setup_function10(kCarGreenSleeping, kPosition_540, "TRA1005");
+ setup_makeAnnouncement(kCarGreenSleeping, kPosition_540, "TRA1005");
} else {
setCallback(7);
- setup_function10(kCarRedSleeping, kPosition_9460, "TRA1006");
+ setup_makeAnnouncement(kCarRedSleeping, kPosition_9460, "TRA1006");
}
break;
}
@@ -805,7 +805,7 @@ IMPLEMENT_FUNCTION(25, Verges, function25)
getSavePoints()->push(kEntityVerges, kEntityCoudert, kAction168254872);
setCallback(4);
- setup_function10(kCarRedSleeping, kPosition_9460, "TRA1006");
+ setup_makeAnnouncement(kCarRedSleeping, kPosition_9460, "TRA1006");
break;
case 4:
@@ -838,7 +838,7 @@ IMPLEMENT_FUNCTION(25, Verges, function25)
getSavePoints()->push(kEntityVerges, kEntityCoudert, kAction168254872);
setCallback(10);
- setup_function10(kCarGreenSleeping, kPosition_540, "TRA1006");
+ setup_makeAnnouncement(kCarGreenSleeping, kPosition_540, "TRA1006");
break;
case 10:
@@ -892,14 +892,14 @@ IMPLEMENT_FUNCTION(26, Verges, chapter1Handler)
label_callback1:
if (getEntities()->isInBaggageCarEntrance(kEntityPlayer)) {
setCallback(2);
- setup_function13(false);
+ setup_baggageCar(false);
break;
}
label_callback2:
if (ENTITY_PARAM(0, 7)) {
setCallback(3);
- setup_function25();
+ setup_policeSearch();
break;
}
@@ -907,7 +907,7 @@ label_callback3:
if (params->param6)
goto label_callback12;
- if (Entity::timeCheckCallback(kTimeChapter1, params->param7, 4, "TRA1001", WRAP_SETUP_FUNCTION_S(Verges, setup_function9)))
+ if (Entity::timeCheckCallback(kTimeChapter1, params->param7, 4, "TRA1001", WRAP_SETUP_FUNCTION_S(Verges, setup_walkBetweenCars)))
break;
label_callback4:
@@ -923,19 +923,19 @@ label_callback4:
}
label_callback8:
- if (Entity::timeCheckCallback(kTime1107000, CURRENT_PARAM(1, 1), 9, "TRA1001A", WRAP_SETUP_FUNCTION_S(Verges, setup_function9)))
+ if (Entity::timeCheckCallback(kTime1107000, CURRENT_PARAM(1, 1), 9, "TRA1001A", WRAP_SETUP_FUNCTION_S(Verges, setup_walkBetweenCars)))
break;
label_callback9:
- if (Entity::timeCheckCallback(kTime1134000, CURRENT_PARAM(1, 2), 10, "TRA1002", WRAP_SETUP_FUNCTION_S(Verges, setup_function9)))
+ if (Entity::timeCheckCallback(kTime1134000, CURRENT_PARAM(1, 2), 10, "TRA1002", WRAP_SETUP_FUNCTION_S(Verges, setup_walkBetweenCars)))
break;
label_callback10:
- if (Entity::timeCheckCallback(kTime1165500, CURRENT_PARAM(1, 3), 11, "TRA1003", WRAP_SETUP_FUNCTION_S(Verges, setup_function9)))
+ if (Entity::timeCheckCallback(kTime1165500, CURRENT_PARAM(1, 3), 11, "TRA1003", WRAP_SETUP_FUNCTION_S(Verges, setup_walkBetweenCars)))
break;
label_callback11:
- if (Entity::timeCheckCallback(kTime1225800, CURRENT_PARAM(1, 4), 12, "TRA1004", WRAP_SETUP_FUNCTION_S(Verges, setup_function9)))
+ if (Entity::timeCheckCallback(kTime1225800, CURRENT_PARAM(1, 4), 12, "TRA1004", WRAP_SETUP_FUNCTION_S(Verges, setup_walkBetweenCars)))
break;
label_callback12:
@@ -955,7 +955,7 @@ label_callback13:
label_callback14:
if (ENTITY_PARAM(0, 3) && !params->param4 && (getState()->time < kTime1134000 || getState()->time > kTime1156500)) {
setCallback(15);
- setup_function17();
+ setup_talkAboutPassengerList();
break;
}
@@ -963,14 +963,14 @@ label_callback15:
if (ENTITY_PARAM(0, 1) && !params->param5) {
if (getState()->time < kTime1134000 || getState()->time > kTime1156500) {
setCallback(16);
- setup_function22();
+ setup_askMertensToRelayAugustInvitation();
}
}
break;
case kActionOpenDoor:
setCallback(17);
- setup_function13(savepoint.param.intValue < 106 ? true : false);
+ setup_baggageCar(savepoint.param.intValue < 106 ? true : false);
break;
case kActionDefault:
@@ -1006,7 +1006,7 @@ label_callback15:
case 6:
setCallback(7);
- setup_function15(kEntityMertens, "TRA1202");
+ setup_dialog(kEntityMertens, "TRA1202");
break;
case 7:
@@ -1084,11 +1084,11 @@ IMPLEMENT_FUNCTION(28, Verges, chapter2Handler)
case kActionNone:
if (getEntities()->isInBaggageCarEntrance(kEntityPlayer)) {
setCallback(1);
- setup_function13(false);
+ setup_baggageCar(false);
}
label_callback_1:
- if (Entity::timeCheckCallback(kTime1818900, params->param1, 2, "Tra2177", WRAP_SETUP_FUNCTION_S(Verges, setup_function9)))
+ if (Entity::timeCheckCallback(kTime1818900, params->param1, 2, "Tra2177", WRAP_SETUP_FUNCTION_S(Verges, setup_walkBetweenCars)))
break;
label_callback_2:
@@ -1117,7 +1117,7 @@ label_callback_6:
if (ENTITY_PARAM(0, 3)) {
setCallback(7);
- setup_function17();
+ setup_talkAboutPassengerList();
}
break;
@@ -1130,7 +1130,7 @@ label_callback_6:
case kActionOpenDoor:
setCallback(8);
- setup_function13(savepoint.param.intValue < 106);
+ setup_baggageCar(savepoint.param.intValue < 106);
break;
case kActionDefault:
@@ -1155,7 +1155,7 @@ label_callback_6:
case 4:
setCallback(5);
- setup_function15(kEntityCoudert, "TRA2100");
+ setup_dialog(kEntityCoudert, "TRA2100");
break;
case 5:
@@ -1177,7 +1177,7 @@ IMPLEMENT_FUNCTION(29, Verges, chapter3)
break;
case kActionNone:
- setup_function23();
+ setup_function33();
break;
case kActionDefault:
@@ -1221,7 +1221,7 @@ IMPLEMENT_FUNCTION_S(30, Verges, function30)
case 2:
setCallback(3);
- setup_function15(kEntityCoudert, (char *)&params->seq1);
+ setup_dialog(kEntityCoudert, (char *)&params->seq1);
break;
case 3:
@@ -1238,7 +1238,7 @@ IMPLEMENT_FUNCTION_S(30, Verges, function30)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(31, Verges, function31)
+IMPLEMENT_FUNCTION(31, Verges, talkAboutMax)
switch (savepoint.action) {
default:
break;
@@ -1260,7 +1260,7 @@ IMPLEMENT_FUNCTION(31, Verges, function31)
case 2:
setCallback(3);
- setup_function15(kEntityCoudert, "TRA3015");
+ setup_dialog(kEntityCoudert, "TRA3015");
break;
case 3:
@@ -1289,7 +1289,7 @@ IMPLEMENT_FUNCTION(32, Verges, function32)
if (getState()->time > kTime2263500 && !params->param1) {
params->param1 = 1;
setCallback(5);
- setup_function10(kCarRedSleeping, kPosition_9460, "TRA3006");
+ setup_makeAnnouncement(kCarRedSleeping, kPosition_9460, "TRA3006");
break;
}
break;
@@ -1341,7 +1341,7 @@ IMPLEMENT_FUNCTION(32, Verges, function32)
case 3:
setCallback(4);
- setup_function10(kCarGreenSleeping, kPosition_540, "TRA3004");
+ setup_makeAnnouncement(kCarGreenSleeping, kPosition_540, "TRA3004");
break;
case 4:
@@ -1412,7 +1412,7 @@ IMPLEMENT_FUNCTION(33, Verges, function33)
getSavePoints()->push(kEntityVerges, kEntityAbbot, kAction192054567);
setCallback(6);
- setup_function9("Tra3010");
+ setup_walkBetweenCars("Tra3010");
break;
case 6:
@@ -1432,42 +1432,42 @@ IMPLEMENT_FUNCTION(34, Verges, function34)
case kActionNone:
if (getEntities()->isInBaggageCarEntrance(kEntityPlayer)) {
setCallback(1);
- setup_function13(false);
+ setup_baggageCar(false);
break;
}
label_callback_1:
if (ENTITY_PARAM(0, 4)) {
setCallback(2);
- setup_function31();
+ setup_talkAboutMax();
break;
}
label_callback_2:
if (ENTITY_PARAM(0, 3)) {
setCallback(3);
- setup_function17();
+ setup_talkAboutPassengerList();
break;
}
label_callback_3:
- if (Entity::timeCheckCallback(kTime1971000, params->param1, 4, "Tra3001", WRAP_SETUP_FUNCTION_S(Verges, setup_function9)))
+ if (Entity::timeCheckCallback(kTime1971000, params->param1, 4, "Tra3001", WRAP_SETUP_FUNCTION_S(Verges, setup_walkBetweenCars)))
break;
label_callback_4:
- if (Entity::timeCheckCallback(kTime1998000, params->param2, 5, "Tra3010a", WRAP_SETUP_FUNCTION_S(Verges, setup_function9)))
+ if (Entity::timeCheckCallback(kTime1998000, params->param2, 5, "Tra3010a", WRAP_SETUP_FUNCTION_S(Verges, setup_walkBetweenCars)))
break;
label_callback_5:
- if (Entity::timeCheckCallback(kTime2016000, params->param3, 6, WRAP_SETUP_FUNCTION(Verges, setup_function35)))
+ if (Entity::timeCheckCallback(kTime2016000, params->param3, 6, WRAP_SETUP_FUNCTION(Verges, setup_organizeConcertInvitations)))
break;
label_callback_6:
- if (Entity::timeCheckCallback(kTime2070000, params->param4, 7, "Tra3002", WRAP_SETUP_FUNCTION_S(Verges, setup_function9)))
+ if (Entity::timeCheckCallback(kTime2070000, params->param4, 7, "Tra3002", WRAP_SETUP_FUNCTION_S(Verges, setup_walkBetweenCars)))
break;
label_callback_7:
- if (Entity::timeCheckCallback(kTime2142000, params->param5, 8, "Tra3003", WRAP_SETUP_FUNCTION_S(Verges, setup_function9)))
+ if (Entity::timeCheckCallback(kTime2142000, params->param5, 8, "Tra3003", WRAP_SETUP_FUNCTION_S(Verges, setup_walkBetweenCars)))
break;
label_callback_8:
@@ -1480,7 +1480,7 @@ label_callback_9:
case kActionOpenDoor:
setCallback(11);
- setup_function13(savepoint.param.intValue < 106);
+ setup_baggageCar(savepoint.param.intValue < 106);
break;
case kActionCallback:
@@ -1520,7 +1520,7 @@ label_callback_9:
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(35, Verges, function35)
+IMPLEMENT_FUNCTION(35, Verges, organizeConcertInvitations)
switch (savepoint.action) {
default:
break;
@@ -1542,7 +1542,7 @@ IMPLEMENT_FUNCTION(35, Verges, function35)
case 2:
setCallback(3);
- setup_function15(kEntityMertens, "Tra3011A");
+ setup_dialog(kEntityMertens, "Tra3011A");
break;
case 3:
@@ -1554,7 +1554,7 @@ IMPLEMENT_FUNCTION(35, Verges, function35)
case 4:
setCallback(5);
- setup_function15(kEntityMertens, "Tra3011");
+ setup_dialog(kEntityMertens, "Tra3011");
break;
case 5:
@@ -1609,7 +1609,7 @@ IMPLEMENT_FUNCTION(37, Verges, chapter4Handler)
case kActionNone:
if (getEntities()->isInBaggageCarEntrance(kEntityPlayer)) {
setCallback(1);
- setup_function13(false);
+ setup_baggageCar(false);
break;
}
@@ -1617,42 +1617,42 @@ label_callback_1:
if (ENTITY_PARAM(0, 6)) {
if (ENTITY_PARAM(0, 3)) {
setCallback(2);
- setup_function17();
+ setup_talkAboutPassengerList();
break;
}
label_callback_2:
- if (Entity::timeCheckCallback(kTime2349000, params->param1, 3, "Tra1001", WRAP_SETUP_FUNCTION_S(Verges, setup_function9)))
+ if (Entity::timeCheckCallback(kTime2349000, params->param1, 3, "Tra1001", WRAP_SETUP_FUNCTION_S(Verges, setup_walkBetweenCars)))
break;
label_callback_3:
- if (Entity::timeCheckCallback(kTime2378700, params->param2, 4, "Tra4001", WRAP_SETUP_FUNCTION_S(Verges, setup_function9)))
+ if (Entity::timeCheckCallback(kTime2378700, params->param2, 4, "Tra4001", WRAP_SETUP_FUNCTION_S(Verges, setup_walkBetweenCars)))
break;
label_callback_4:
- if (Entity::timeCheckCallback(kTime2403000, params->param3, 5, "Tra1001A", WRAP_SETUP_FUNCTION_S(Verges, setup_function9)))
+ if (Entity::timeCheckCallback(kTime2403000, params->param3, 5, "Tra1001A", WRAP_SETUP_FUNCTION_S(Verges, setup_walkBetweenCars)))
break;
label_callback_5:
- if (Entity::timeCheckCallback(kTime2414700, params->param4, 6, "Tra4002", WRAP_SETUP_FUNCTION_S(Verges, setup_function9)))
+ if (Entity::timeCheckCallback(kTime2414700, params->param4, 6, "Tra4002", WRAP_SETUP_FUNCTION_S(Verges, setup_walkBetweenCars)))
break;
label_callback_6:
- if (Entity::timeCheckCallback(kTime2484000, params->param5, 7, "Tra4003", WRAP_SETUP_FUNCTION_S(Verges, setup_function9)))
+ if (Entity::timeCheckCallback(kTime2484000, params->param5, 7, "Tra4003", WRAP_SETUP_FUNCTION_S(Verges, setup_walkBetweenCars)))
break;
label_callback_7:
- if (Entity::timeCheckCallback(kTime2511000, params->param6, 8, "Tra4004", WRAP_SETUP_FUNCTION_S(Verges, setup_function9)))
+ if (Entity::timeCheckCallback(kTime2511000, params->param6, 8, "Tra4004", WRAP_SETUP_FUNCTION_S(Verges, setup_walkBetweenCars)))
break;
}
label_callback_8:
- Entity::timeCheckCallback(kTime2538000, params->param7, 9, "Tra4005", WRAP_SETUP_FUNCTION_S(Verges, setup_function9));
+ Entity::timeCheckCallback(kTime2538000, params->param7, 9, "Tra4005", WRAP_SETUP_FUNCTION_S(Verges, setup_walkBetweenCars));
break;
case kActionOpenDoor:
setCallback(10);
- setup_function13(savepoint.param.intValue < 106);
+ setup_baggageCar(savepoint.param.intValue < 106);
break;
case kActionDefault:
@@ -1697,7 +1697,7 @@ label_callback_8:
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(38, Verges, function38)
+IMPLEMENT_FUNCTION(38, Verges, resetState)
switch (savepoint.action) {
default:
break;
@@ -1803,14 +1803,14 @@ IMPLEMENT_FUNCTION(40, Verges, chapter5Handler)
getAction()->playAnimation(kEventCathFreePassengers);
getSavePoints()->pushAll(kEntityVerges, kActionProceedChapter5);
getScenes()->loadSceneFromPosition(kCarRedSleeping, 40);
- setup_function41();
+ setup_askPassengersToStayInCompartments();
}
break;
}
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(41, Verges, function41)
+IMPLEMENT_FUNCTION(41, Verges, askPassengersToStayInCompartments)
switch (savepoint.action) {
default:
break;
@@ -1822,7 +1822,7 @@ IMPLEMENT_FUNCTION(41, Verges, function41)
getData()->location = kLocationInsideCompartment;
setCallback(1);
- setup_function10(kCarRedSleeping, kPosition_2000, "Tra5001");
+ setup_makeAnnouncement(kCarRedSleeping, kPosition_2000, "Tra5001");
break;
case kActionCallback:
@@ -1852,7 +1852,7 @@ IMPLEMENT_FUNCTION(41, Verges, function41)
break;
case 4:
- setup_function42();
+ setup_end();
break;
}
break;
@@ -1860,7 +1860,7 @@ IMPLEMENT_FUNCTION(41, Verges, function41)
IMPLEMENT_FUNCTION_END
//////////////////////////////////////////////////////////////////////////
-IMPLEMENT_FUNCTION(42, Verges, function42)
+IMPLEMENT_FUNCTION(42, Verges, end)
if (savepoint.action == kActionDefault)
getEntities()->clearSequences(kEntityVerges);
IMPLEMENT_FUNCTION_END
@@ -1891,7 +1891,7 @@ void Verges::talk(const SavePoint &savepoint, const char *sound1, const char *so
case 2:
setCallback(3);
- setup_function15(kEntityCoudert, sound1);
+ setup_dialog(kEntityCoudert, sound1);
break;
case 3:
@@ -1901,7 +1901,7 @@ void Verges::talk(const SavePoint &savepoint, const char *sound1, const char *so
case 4:
setCallback(5);
- setup_function15(kEntityMertens, sound2);
+ setup_dialog(kEntityMertens, sound2);
break;
case 5:
diff --git a/engines/lastexpress/entities/verges.h b/engines/lastexpress/entities/verges.h
index 82381043d3..93cc190d1e 100644
--- a/engines/lastexpress/entities/verges.h
+++ b/engines/lastexpress/entities/verges.h
@@ -87,11 +87,11 @@ public:
*/
DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition)
- DECLARE_FUNCTION_1(function9, const char *soundName)
- DECLARE_FUNCTION_3(function10, CarIndex car, EntityPosition entityPosition, const char *soundName)
+ DECLARE_FUNCTION_1(walkBetweenCars, const char *soundName)
+ DECLARE_FUNCTION_3(makeAnnouncement, CarIndex car, EntityPosition entityPosition, const char *soundName)
DECLARE_FUNCTION(function11)
DECLARE_FUNCTION(function12)
- DECLARE_FUNCTION_1(function13, bool)
+ DECLARE_FUNCTION_1(baggageCar, bool)
/**
* Updates parameter 2 using time value
@@ -100,9 +100,9 @@ public:
*/
DECLARE_FUNCTION_1(updateFromTime, uint32 time)
- DECLARE_FUNCTION_2(function15, EntityIndex entity, const char *soundName)
- DECLARE_FUNCTION_3(function16, EntityIndex entityIndex, const char *soundName1, const char *soundName2)
- DECLARE_FUNCTION(function17)
+ DECLARE_FUNCTION_2(dialog, EntityIndex entity, const char *soundName)
+ DECLARE_FUNCTION_3(dialog2, EntityIndex entityIndex, const char *soundName1, const char *soundName2)
+ DECLARE_FUNCTION(talkAboutPassengerList)
/**
* Setup Chapter 1
@@ -112,10 +112,10 @@ public:
DECLARE_FUNCTION_NOSETUP(talkHarem)
DECLARE_FUNCTION(talkPassengerList)
DECLARE_FUNCTION(talkGendarmes)
- DECLARE_FUNCTION(function22)
+ DECLARE_FUNCTION(askMertensToRelayAugustInvitation)
DECLARE_FUNCTION(function23)
DECLARE_FUNCTION(policeGettingOffTrain)
- DECLARE_FUNCTION(function25)
+ DECLARE_FUNCTION(policeSearch)
/**
* Handle Chapter 1 events
@@ -138,11 +138,11 @@ public:
DECLARE_FUNCTION(chapter3)
DECLARE_FUNCTION_1(function30, const char *soundName)
- DECLARE_FUNCTION(function31)
+ DECLARE_FUNCTION(talkAboutMax)
DECLARE_FUNCTION(function32)
DECLARE_FUNCTION(function33)
DECLARE_FUNCTION(function34)
- DECLARE_FUNCTION(function35)
+ DECLARE_FUNCTION(organizeConcertInvitations)
/**
* Setup Chapter 4
@@ -154,7 +154,7 @@ public:
*/
DECLARE_FUNCTION(chapter4Handler)
- DECLARE_FUNCTION(function38)
+ DECLARE_FUNCTION(resetState)
/**
* Setup Chapter 5
@@ -166,8 +166,8 @@ public:
*/
DECLARE_FUNCTION(chapter5Handler)
- DECLARE_FUNCTION(function41)
- DECLARE_FUNCTION(function42)
+ DECLARE_FUNCTION(askPassengersToStayInCompartments)
+ DECLARE_FUNCTION(end)
private:
void talk(const SavePoint &savepoint, const char *sound1, const char *sound2);
diff --git a/engines/lastexpress/fight/fight.cpp b/engines/lastexpress/fight/fight.cpp
index b00c1732e7..49a9b85657 100644
--- a/engines/lastexpress/fight/fight.cpp
+++ b/engines/lastexpress/fight/fight.cpp
@@ -39,10 +39,8 @@
#include "lastexpress/game/state.h"
#include "lastexpress/sound/queue.h"
-#include "lastexpress/sound/sound.h"
#include "lastexpress/graphics.h"
-#include "lastexpress/helpers.h"
#include "lastexpress/lastexpress.h"
#include "lastexpress/resource.h"
diff --git a/engines/lastexpress/game/action.cpp b/engines/lastexpress/game/action.cpp
index 60a309518a..796abf2ce7 100644
--- a/engines/lastexpress/game/action.cpp
+++ b/engines/lastexpress/game/action.cpp
@@ -394,7 +394,7 @@ Action::Action(LastExpressEngine *engine) : _engine(engine) {
}
Action::~Action() {
- for (int i = 0; i < (int)_actions.size(); i++)
+ for (uint i = 0; i < _actions.size(); i++)
SAFE_DELETE(_actions[i]);
_actions.clear();
@@ -421,8 +421,6 @@ SceneIndex Action::processHotspot(const SceneHotspot &hotspot) {
// Action 0
IMPLEMENT_ACTION(dummy)
error("[Action::action_dummy] Dummy action function called (hotspot action: %d)", hotspot.action);
-
- return kSceneInvalid;
}
//////////////////////////////////////////////////////////////////////////
diff --git a/engines/lastexpress/game/beetle.cpp b/engines/lastexpress/game/beetle.cpp
index 2a72459697..d7a369ba40 100644
--- a/engines/lastexpress/game/beetle.cpp
+++ b/engines/lastexpress/game/beetle.cpp
@@ -94,7 +94,7 @@ void Beetle::load() {
// Check that all sequences are loaded properly
_data->isLoaded = true;
- for (int i = 0; i < (int)_data->sequences.size(); i++) {
+ for (uint i = 0; i < _data->sequences.size(); i++) {
if (!_data->sequences[i]->isLoaded()) {
_data->isLoaded = false;
break;
@@ -351,6 +351,9 @@ void Beetle::drawUpdate() {
}
void Beetle::invertDirection() {
+ if (!_data)
+ error("[Beetle::invertDirection] Sequences have not been loaded");
+
switch (_data->indexes[_data->offset]) {
default:
break;
diff --git a/engines/lastexpress/game/entities.cpp b/engines/lastexpress/game/entities.cpp
index 51db635bed..fafbd7cb64 100644
--- a/engines/lastexpress/game/entities.cpp
+++ b/engines/lastexpress/game/entities.cpp
@@ -181,7 +181,7 @@ Entities::Entities(LastExpressEngine *engine) : _engine(engine) {
Entities::~Entities() {
SAFE_DELETE(_header);
- for (int i = 0; i < (int)_entities.size(); i++)
+ for (uint i = 0; i < _entities.size(); i++)
SAFE_DELETE(_entities[i]);
_entities.clear();
@@ -669,7 +669,7 @@ void Entities::executeCallbacks() {
//////////////////////////////////////////////////////////////////////////
// Processing
//////////////////////////////////////////////////////////////////////////
-void Entities::incrementDirectionCounter(EntityData::EntityCallData *data) {
+void Entities::incrementDirectionCounter(EntityData::EntityCallData *data) const {
data->doProcessEntity = false;
if (data->direction == kDirectionRight || (data->direction == kDirectionSwitch && data->directionSwitch == kDirectionRight))
diff --git a/engines/lastexpress/game/entities.h b/engines/lastexpress/game/entities.h
index a9de7931f0..81aed627aa 100644
--- a/engines/lastexpress/game/entities.h
+++ b/engines/lastexpress/game/entities.h
@@ -344,7 +344,7 @@ private:
uint _positions[_positionsCount];
void executeCallbacks();
- void incrementDirectionCounter(EntityData::EntityCallData *data);
+ void incrementDirectionCounter(EntityData::EntityCallData *data) const;
void processEntity(EntityIndex entity);
void drawSequence(EntityIndex entity, const char *sequence, EntityDirection direction) const;
diff --git a/engines/lastexpress/game/inventory.cpp b/engines/lastexpress/game/inventory.cpp
index 52c00ece31..11e7369ee1 100644
--- a/engines/lastexpress/game/inventory.cpp
+++ b/engines/lastexpress/game/inventory.cpp
@@ -35,10 +35,8 @@
#include "lastexpress/menu/menu.h"
#include "lastexpress/sound/queue.h"
-#include "lastexpress/sound/sound.h"
#include "lastexpress/graphics.h"
-#include "lastexpress/helpers.h"
#include "lastexpress/lastexpress.h"
#include "lastexpress/resource.h"
@@ -621,7 +619,7 @@ void Inventory::drawEgg() const {
// Blinking egg: we need to blink the egg for delta time, with the blinking getting faster until it's always lit.
void Inventory::drawBlinkingEgg(uint ticks) {
- uint globalTimer = getGlobalTimer();
+ uint globalTimer = (uint)getGlobalTimer();
uint timerValue = (getProgress().jacket == kJacketGreen) ? 450 : 225;
if (globalTimer == timerValue || globalTimer == 900) {
@@ -655,7 +653,7 @@ void Inventory::drawBlinkingEgg(uint ticks) {
}
void Inventory::blinkEgg() {
- drawItem((CursorStyle)(getMenu()->getGameId() + 39), 608, 448, (_blinkingBrightness == 0) ? -1 : _blinkingBrightness);
+ drawItem((CursorStyle)(getMenu()->getGameId() + 39), 608, 448, (_blinkingBrightness == 0) ? -1 : (int16)_blinkingBrightness);
askForRedraw();
diff --git a/engines/lastexpress/game/logic.cpp b/engines/lastexpress/game/logic.cpp
index 1696f100ff..09104d1bf9 100644
--- a/engines/lastexpress/game/logic.cpp
+++ b/engines/lastexpress/game/logic.cpp
@@ -48,7 +48,6 @@
#include "lastexpress/sound/queue.h"
-#include "lastexpress/graphics.h"
#include "lastexpress/lastexpress.h"
#include "lastexpress/resource.h"
diff --git a/engines/lastexpress/game/savegame.cpp b/engines/lastexpress/game/savegame.cpp
index 360e99146a..021dc40bb9 100644
--- a/engines/lastexpress/game/savegame.cpp
+++ b/engines/lastexpress/game/savegame.cpp
@@ -78,7 +78,7 @@ uint32 SavegameStream::read(void *dataPtr, uint32 dataSize) {
uint32 SavegameStream::readUncompressed(void *dataPtr, uint32 dataSize) {
if ((int32)dataSize > size() - pos()) {
- dataSize = size() - pos();
+ dataSize = (uint32)(size() - pos());
_eos = true;
}
memcpy(dataPtr, getData() + pos(), dataSize);
@@ -230,7 +230,7 @@ uint32 SavegameStream::writeCompressed(const void *dataPtr, uint32 dataSize) {
if (*data != _previousValue || _repeatCount >= 255) {
if (_previousValue) {
writeBuffer(0xFF, true);
- writeBuffer(_repeatCount, true);
+ writeBuffer((uint8)_repeatCount, true);
writeBuffer(_previousValue, true);
_previousValue = *data++;
@@ -255,7 +255,7 @@ uint32 SavegameStream::writeCompressed(const void *dataPtr, uint32 dataSize) {
}
writeBuffer(0xFD, true);
- writeBuffer(_repeatCount, true);
+ writeBuffer((uint8)_repeatCount, true);
_previousValue = *data++;
_valueCount = 1;
@@ -348,11 +348,12 @@ uint32 SavegameStream::readCompressed(void *dataPtr, uint32 dataSize) {
// Constructors
//////////////////////////////////////////////////////////////////////////
-SaveLoad::SaveLoad(LastExpressEngine *engine) : _engine(engine), _savegame(NULL), _gameTicksLastSavegame(0) {
+SaveLoad::SaveLoad(LastExpressEngine *engine) : _engine(engine), _savegame(NULL), _gameTicksLastSavegame(0), _entity(kEntityPlayer) {
}
SaveLoad::~SaveLoad() {
clear(true);
+ _savegame = NULL;
// Zero passed pointers
_engine = NULL;
@@ -481,10 +482,10 @@ void SaveLoad::clear(bool clearStream) {
// Save & Load
//////////////////////////////////////////////////////////////////////////
-// Load game
-void SaveLoad::loadGame(GameId id) {
+// Load last saved game
+void SaveLoad::loadLastGame() {
if (!_savegame)
- error("[SaveLoad::loadGame] No savegame stream present");
+ error("[SaveLoad::loadLastGame] No savegame stream present");
// Rewind current savegame
_savegame->seek(0);
@@ -521,7 +522,29 @@ void SaveLoad::loadGame(GameId id) {
}
// Load a specific game entry
-void SaveLoad::loadGame(GameId id, uint32 index) {
+void SaveLoad::loadGame(uint32 index) {
+ if (!_savegame)
+ error("[SaveLoad::loadLastGame] No savegame stream present");
+
+ // Rewind current savegame
+ _savegame->seek(0);
+
+ // Write main header (with selected index)
+ SavegameMainHeader header;
+ header.count = index;
+ header.brightness = getState()->brightness;
+ header.volume = getState()->volume;
+
+ Common::Serializer ser(NULL, _savegame);
+ header.saveLoadWithSerializer(ser);
+
+ // TODO
+ // Go to the entry
+ // Load the entry
+ // Get offset (main and entry)
+ // Write main header again with correct entry offset
+ // Setup game and start
+
error("[SaveLoad::loadGame] Not implemented! (only loading the last entry is working for now)");
}
@@ -550,7 +573,7 @@ void SaveLoad::saveGame(SavegameType type, EntityIndex entity, uint32 value) {
entry.saveLoadWithSerializer(ser);
if (!entry.isValid()) {
- error("[SaveLoad::saveGame] Invalid entry. This savegame might be corrupted");
+ warning("[SaveLoad::saveGame] Invalid entry. This savegame might be corrupted");
_savegame->seek(header.offset);
} else if (getState()->time < entry.time || (type == kSavegameTypeTickInterval && getState()->time == entry.time)) {
// Not ready to save a game, skipping!
@@ -634,6 +657,9 @@ bool SaveLoad::loadMainHeader(Common::InSaveFile *stream, SavegameMainHeader *he
// Entries
//////////////////////////////////////////////////////////////////////////
uint32 SaveLoad::writeValue(Common::Serializer &ser, const char *name, Common::Functor1<Common::Serializer &, void> *function, uint size) {
+ if (!_savegame)
+ error("[SaveLoad::writeValue] Stream not initialized properly");
+
debugC(kLastExpressDebugSavegame, "Savegame: Writing %s: %u bytes", name, size);
uint32 prevPosition = (uint32)_savegame->pos();
@@ -652,6 +678,9 @@ uint32 SaveLoad::writeValue(Common::Serializer &ser, const char *name, Common::F
}
uint32 SaveLoad::readValue(Common::Serializer &ser, const char *name, Common::Functor1<Common::Serializer &, void> *function, uint size) {
+ if (!_savegame)
+ error("[SaveLoad::readValue] Stream not initialized properly");
+
debugC(kLastExpressDebugSavegame, "Savegame: Reading %s: %u bytes", name, size);
uint32 prevPosition = (uint32)_savegame->pos();
diff --git a/engines/lastexpress/game/savegame.h b/engines/lastexpress/game/savegame.h
index 8656b2ee86..361957227e 100644
--- a/engines/lastexpress/game/savegame.h
+++ b/engines/lastexpress/game/savegame.h
@@ -153,8 +153,8 @@ public:
uint32 init(GameId id, bool resetHeaders);
// Save & Load
- void loadGame(GameId id);
- void loadGame(GameId id, uint32 index);
+ void loadLastGame();
+ void loadGame(uint32 index);
void saveGame(SavegameType type, EntityIndex entity, uint32 value);
void loadVolumeBrightness();
diff --git a/engines/lastexpress/game/savepoint.cpp b/engines/lastexpress/game/savepoint.cpp
index 6b2dfc5930..8d14ec386b 100644
--- a/engines/lastexpress/game/savepoint.cpp
+++ b/engines/lastexpress/game/savepoint.cpp
@@ -202,7 +202,7 @@ void SavePoints::callAndProcess() {
// Misc
//////////////////////////////////////////////////////////////////////////
bool SavePoints::updateEntityFromData(const SavePoint &savepoint) {
- for (int i = 0; i < (int)_data.size(); i++) {
+ for (uint i = 0; i < _data.size(); i++) {
// Not a data savepoint!
if (!_data[i].entity1)
@@ -210,7 +210,7 @@ bool SavePoints::updateEntityFromData(const SavePoint &savepoint) {
// Found our data!
if (_data[i].entity1 == savepoint.entity1 && _data[i].action == savepoint.action) {
- debugC(8, kLastExpressDebugLogic, "Update entity from data: entity1=%s, action=%s, param=%d", ENTITY_NAME(_data[i].entity1), ACTION_NAME(_data[i].action), _data[i].param);
+ debugC(8, kLastExpressDebugLogic, "Update entity from data: entity1=%s, action=%s, param=%u", ENTITY_NAME(_data[i].entity1), ACTION_NAME(_data[i].action), _data[i].param);
// the SavePoint param value is the index of the entity call parameter to update
getEntities()->get(_data[i].entity1)->getParamData()->updateParameters(_data[i].param);
diff --git a/engines/lastexpress/game/scenes.cpp b/engines/lastexpress/game/scenes.cpp
index 3cda900757..a2c7226b93 100644
--- a/engines/lastexpress/game/scenes.cpp
+++ b/engines/lastexpress/game/scenes.cpp
@@ -739,7 +739,7 @@ void SceneManager::resetQueue() {
_queue.clear();
}
-void SceneManager::setCoordinates(Common::Rect rect) {
+void SceneManager::setCoordinates(const Common::Rect &rect) {
_flagCoordinates = true;
if (_coords.right > rect.right)
diff --git a/engines/lastexpress/game/scenes.h b/engines/lastexpress/game/scenes.h
index a866c65111..1c7ae85f98 100644
--- a/engines/lastexpress/game/scenes.h
+++ b/engines/lastexpress/game/scenes.h
@@ -79,7 +79,7 @@ public:
void removeAndRedraw(SequenceFrame **frame, bool doRedraw);
void resetQueue();
void setCoordinates(SequenceFrame *frame);
- void setCoordinates(Common::Rect rect);
+ void setCoordinates(const Common::Rect &rect);
// Helpers
SceneIndex getSceneIndexFromPosition(CarIndex car, Position position, int param3 = -1);
diff --git a/engines/lastexpress/menu/menu.cpp b/engines/lastexpress/menu/menu.cpp
index 6a453aee99..c48e55bb55 100644
--- a/engines/lastexpress/menu/menu.cpp
+++ b/engines/lastexpress/menu/menu.cpp
@@ -916,13 +916,13 @@ void Menu::startGame() {
if (_lastIndex == _index) {
setGlobalTimer(0);
if (_index) {
- getSaveLoad()->loadGame(_gameId);
+ getSaveLoad()->loadLastGame();
} else {
getLogic()->resetState();
getEntities()->setup(true, kEntityPlayer);
}
} else {
- getSaveLoad()->loadGame(_gameId, _index);
+ getSaveLoad()->loadGame(_index);
}
}
diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp
index f2a063e45f..3d22657124 100644
--- a/engines/lastexpress/sound/entry.cpp
+++ b/engines/lastexpress/sound/entry.cpp
@@ -116,10 +116,8 @@ void SoundEntry::close() {
}
void SoundEntry::play() {
- if (!_stream) {
+ if (!_stream)
error("[SoundEntry::play] stream has been disposed");
- return;
- }
// Prepare sound stream
if (!_soundStream)
diff --git a/engines/lastexpress/sound/queue.cpp b/engines/lastexpress/sound/queue.cpp
index d72acfd8a0..8904b48930 100644
--- a/engines/lastexpress/sound/queue.cpp
+++ b/engines/lastexpress/sound/queue.cpp
@@ -67,6 +67,8 @@ void SoundQueue::handleTimer() {
for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) {
SoundEntry *entry = (*i);
+ if (entry == NULL)
+ error("[SoundQueue::handleTimer] Invalid entry found in sound queue");
// When the entry has stopped playing, we remove his buffer
if (entry->isFinished()) {
@@ -123,6 +125,8 @@ void SoundQueue::updateQueue() {
for (Common::List<SoundEntry *>::iterator it = _soundList.begin(); it != _soundList.end(); ++it) {
SoundEntry *entry = *it;
+ if (entry == NULL)
+ error("[SoundQueue::updateQueue] Invalid entry found in sound queue");
// Original removes the entry data from the cache and sets the archive as not loaded
// and if the sound data buffer is not full, loads a new entry to be played based on
@@ -179,6 +183,8 @@ void SoundQueue::clearQueue() {
for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) {
SoundEntry *entry = (*i);
+ if (entry == NULL)
+ error("[SoundQueue::clearQueue] Invalid entry found in sound queue");
// Delete entry
entry->close();
diff --git a/engines/mohawk/myst_stacks/dni.cpp b/engines/mohawk/myst_stacks/dni.cpp
index cae165ccf0..d103105c2d 100644
--- a/engines/mohawk/myst_stacks/dni.cpp
+++ b/engines/mohawk/myst_stacks/dni.cpp
@@ -109,7 +109,7 @@ void Dni::o_handPage(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
_vm->setMainCursor(kDefaultMystCursor);
// Play movie end (atrus leaving)
- _vm->_video->setVideoBounds(atrus, Audio::Timestamp(0, 14813, 600), Audio::Timestamp(0xFFFFFFFF));
+ _vm->_video->setVideoBounds(atrus, Audio::Timestamp(0, 14813, 600), _vm->_video->getDuration(atrus));
_vm->_video->setVideoLooping(atrus, false);
_atrusLeft = true;
diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp
index 18d609c513..0ed4f38b53 100644
--- a/engines/mohawk/video.cpp
+++ b/engines/mohawk/video.cpp
@@ -29,6 +29,7 @@
#include "common/textconsole.h"
#include "common/system.h"
+#include "graphics/palette.h"
#include "graphics/surface.h"
#include "video/qt_decoder.h"
@@ -43,13 +44,12 @@ void VideoEntry::clear() {
loop = false;
enabled = false;
start = Audio::Timestamp(0, 1);
- end = Audio::Timestamp(0xFFFFFFFF, 1); // Largest possible, there is an endOfVideo() check anyway
filename.clear();
id = -1;
}
bool VideoEntry::endOfVideo() {
- return !video || video->endOfVideo() || video->getTime() >= (uint)end.msecs();
+ return !video || video->endOfVideo();
}
VideoManager::VideoManager(MohawkEngine* vm) : _vm(vm) {
@@ -207,7 +207,7 @@ bool VideoManager::updateMovies() {
// Remove any videos that are over
if (_videoStreams[i].endOfVideo()) {
if (_videoStreams[i].loop) {
- _videoStreams[i]->seekToTime(_videoStreams[i].start);
+ _videoStreams[i]->seek(_videoStreams[i].start);
} else {
// Check the video time one last time before deleting it
_vm->doVideoTimer(i, true);
@@ -239,7 +239,7 @@ bool VideoManager::updateMovies() {
frame = convertedFrame;
} else if (pixelFormat.bytesPerPixel == 1 && _videoStreams[i]->hasDirtyPalette()) {
// Set the palette when running in 8bpp mode only
- _videoStreams[i]->setSystemPalette();
+ _vm->_system->getPaletteManager()->setPalette(_videoStreams[i]->getPalette(), 0, 256);
}
// Clip the width/height to make sure we stay on the screen (Myst does this a few times)
@@ -394,6 +394,8 @@ VideoHandle VideoManager::createVideoHandle(uint16 id, uint16 x, uint16 y, bool
entry.loop = loop;
entry.enabled = true;
+ entry->start();
+
// Search for any deleted videos so we can take a formerly used slot
for (uint32 i = 0; i < _videoStreams.size(); i++)
if (!_videoStreams[i].video) {
@@ -430,6 +432,7 @@ VideoHandle VideoManager::createVideoHandle(const Common::String &filename, uint
entry->loadStream(file);
entry->setVolume(volume);
+ entry->start();
// Search for any deleted videos so we can take a formerly used slot
for (uint32 i = 0; i < _videoStreams.size(); i++)
@@ -492,7 +495,7 @@ uint32 VideoManager::getTime(VideoHandle handle) {
uint32 VideoManager::getDuration(VideoHandle handle) {
assert(handle != NULL_VID_HANDLE);
- return _videoStreams[handle]->getDuration();
+ return _videoStreams[handle]->getDuration().msecs();
}
bool VideoManager::endOfVideo(VideoHandle handle) {
@@ -511,14 +514,13 @@ bool VideoManager::isVideoPlaying() {
void VideoManager::setVideoBounds(VideoHandle handle, Audio::Timestamp start, Audio::Timestamp end) {
assert(handle != NULL_VID_HANDLE);
_videoStreams[handle].start = start;
- _videoStreams[handle].end = end;
- _videoStreams[handle]->seekToTime(start);
+ _videoStreams[handle]->setEndTime(end);
+ _videoStreams[handle]->seek(start);
}
void VideoManager::drawVideoFrame(VideoHandle handle, Audio::Timestamp time) {
assert(handle != NULL_VID_HANDLE);
- _videoStreams[handle].end = Audio::Timestamp(0xffffffff, 1);
- _videoStreams[handle]->seekToTime(time);
+ _videoStreams[handle]->seek(time);
updateMovies();
delete _videoStreams[handle].video;
_videoStreams[handle].clear();
@@ -526,7 +528,7 @@ void VideoManager::drawVideoFrame(VideoHandle handle, Audio::Timestamp time) {
void VideoManager::seekToTime(VideoHandle handle, Audio::Timestamp time) {
assert(handle != NULL_VID_HANDLE);
- _videoStreams[handle]->seekToTime(time);
+ _videoStreams[handle]->seek(time);
}
void VideoManager::setVideoLooping(VideoHandle handle, bool loop) {
diff --git a/engines/mohawk/video.h b/engines/mohawk/video.h
index 98bcadfb53..9dddcde09b 100644
--- a/engines/mohawk/video.h
+++ b/engines/mohawk/video.h
@@ -45,19 +45,19 @@ struct MLSTRecord {
struct VideoEntry {
// Playback variables
- Video::SeekableVideoDecoder *video;
+ Video::VideoDecoder *video;
uint16 x;
uint16 y;
bool loop;
bool enabled;
- Audio::Timestamp start, end;
+ Audio::Timestamp start;
// Identification
Common::String filename; // External video files
int id; // Internal Mohawk files
// Helper functions
- Video::SeekableVideoDecoder *operator->() const { assert(video); return video; } // TODO: Remove this eventually
+ Video::VideoDecoder *operator->() const { assert(video); return video; } // TODO: Remove this eventually
void clear();
bool endOfVideo();
};
diff --git a/engines/saga/introproc_saga2.cpp b/engines/saga/introproc_saga2.cpp
index b6470370af..260eca98e6 100644
--- a/engines/saga/introproc_saga2.cpp
+++ b/engines/saga/introproc_saga2.cpp
@@ -32,6 +32,7 @@
#include "common/keyboard.h"
#include "common/system.h"
#include "common/textconsole.h"
+#include "graphics/palette.h"
#include "graphics/surface.h"
#include "video/smk_decoder.h"
@@ -92,7 +93,7 @@ int Scene::FTA2EndProc(FTA2Endings whichEnding) {
}
void Scene::playMovie(const char *filename) {
- Video::SmackerDecoder *smkDecoder = new Video::SmackerDecoder(_vm->_mixer);
+ Video::SmackerDecoder *smkDecoder = new Video::SmackerDecoder();
if (!smkDecoder->loadFile(filename))
return;
@@ -101,6 +102,8 @@ void Scene::playMovie(const char *filename) {
uint16 y = (g_system->getHeight() - smkDecoder->getHeight()) / 2;
bool skipVideo = false;
+ smkDecoder->start();
+
while (!_vm->shouldQuit() && !smkDecoder->endOfVideo() && !skipVideo) {
if (smkDecoder->needsUpdate()) {
const Graphics::Surface *frame = smkDecoder->decodeNextFrame();
@@ -108,7 +111,7 @@ void Scene::playMovie(const char *filename) {
_vm->_system->copyRectToScreen(frame->pixels, frame->pitch, x, y, frame->w, frame->h);
if (smkDecoder->hasDirtyPalette())
- smkDecoder->setSystemPalette();
+ _vm->_system->getPaletteManager()->setPalette(smkDecoder->getPalette(), 0, 256);
_vm->_system->updateScreen();
}
diff --git a/engines/saga/shorten.cpp b/engines/saga/shorten.cpp
index 5efc8d1f67..69c27b6a6b 100644
--- a/engines/saga/shorten.cpp
+++ b/engines/saga/shorten.cpp
@@ -519,9 +519,6 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by
if (maxLPC > 0)
free(lpc);
- if (size > 0)
- free(unpackedBuffer);
-
delete gReader;
return unpackedBuffer;
}
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index 564bbbbd79..1889d53480 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -250,20 +250,18 @@ void Console::postEnter() {
#endif
if (_videoFile.hasSuffix(".seq")) {
- SeqDecoder *seqDecoder = new SeqDecoder();
- seqDecoder->setFrameDelay(_videoFrameDelay);
- videoDecoder = seqDecoder;
+ videoDecoder = new SEQDecoder(_videoFrameDelay);
#ifdef ENABLE_SCI32
} else if (_videoFile.hasSuffix(".vmd")) {
- videoDecoder = new Video::VMDDecoder(g_system->getMixer());
+ videoDecoder = new Video::AdvancedVMDDecoder();
} else if (_videoFile.hasSuffix(".rbt")) {
- videoDecoder = new RobotDecoder(g_system->getMixer(), _engine->getPlatform() == Common::kPlatformMacintosh);
+ videoDecoder = new RobotDecoder(_engine->getPlatform() == Common::kPlatformMacintosh);
} else if (_videoFile.hasSuffix(".duk")) {
duckMode = true;
- videoDecoder = new Video::AviDecoder(g_system->getMixer());
+ videoDecoder = new Video::AVIDecoder();
#endif
} else if (_videoFile.hasSuffix(".avi")) {
- videoDecoder = new Video::AviDecoder(g_system->getMixer());
+ videoDecoder = new Video::AVIDecoder();
} else {
warning("Unrecognized video type");
}
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index 685b3c0bd3..8b3afeef99 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -771,20 +771,23 @@ reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) {
}
break;
case 3: { // remap to gray
- // Example call: QFG4 room 490 (Baba Yaga's hut) - params are color 253, 75% and 0
+ // Example call: QFG4 room 490 (Baba Yaga's hut) - params are color 253, 75% and 0.
+ // In this room, it's used for the cloud before Baba Yaga appears.
int16 color = argv[1].toSint16();
int16 percent = argv[2].toSint16(); // 0 - 100
- uint16 unk3 = (argc >= 4) ? argv[3].toUint16() : 0;
- warning("kRemapColors: RemapToGray color %d by %d percent (unk3 = %d)", color, percent, unk3);
- // TODO
+ if (argc >= 4)
+ warning("RemapToGray called with 4 parameters, unknown parameter is %d", argv[3].toUint16());
+ g_sci->_gfxPalette->setRemappingPercentGray(color, percent);
}
break;
case 4: { // remap to percent gray
- //int16 unk1 = argv[1].toSint16();
- //uint16 unk2 = argv[2].toUint16();
- //uint16 unk3 = argv[3].toUint16();
- //uint16 unk4 = (argc >= 5) ? argv[4].toUint16() : 0;
- kStub(s, argc, argv);
+ // Example call: QFG4 rooms 530/535 (swamp) - params are 253, 100%, 200
+ int16 color = argv[1].toSint16();
+ int16 percent = argv[2].toSint16(); // 0 - 100
+ // argv[3] is unknown (a number, e.g. 200) - start color, perhaps?
+ if (argc >= 5)
+ warning("RemapToGrayPercent called with 5 parameters, unknown parameter is %d", argv[4].toUint16());
+ g_sci->_gfxPalette->setRemappingPercentGray(color, percent);
}
break;
case 5: { // don't map to range
diff --git a/engines/sci/engine/kmath.cpp b/engines/sci/engine/kmath.cpp
index a643fbe37a..4b8fadbb84 100644
--- a/engines/sci/engine/kmath.cpp
+++ b/engines/sci/engine/kmath.cpp
@@ -84,27 +84,10 @@ reg_t kSqrt(EngineState *s, int argc, reg_t *argv) {
* accurate.
*/
uint16 kGetAngleWorker(int16 x1, int16 y1, int16 x2, int16 y2) {
- // TODO: This has been implemented based on behavior observed with a test
- // program created with SCI Studio. However, the return values have subtle
- // differences from the original, which uses custom implementation of atan().
- // The differences in the return values are the cause of bug #3540976
- // and perhaps bug #3037267 as well.
- // The results of this function match the expected results of SCI0, but not
- // SCI1 (hence the bug in Longbow). We need to find the point in history
- // when this function was changed.
-
- // HACK: Return the expected value for Longbow, scene 150 (bug #3540976).
- // This is a temporary solution, till the function returns the expected
- // results.
- if (g_sci->getGameId() == GID_LONGBOW && g_sci->getEngineState()->currentRoomNumber() == 150) {
- if (x1 == 207 && y1 == 88 && x2 == 107 && y2 == 184)
- return 226;
- }
-
-#if 0
- // A simpler atan2-based implementation
- return (int16)(360 - atan2((double)(x1 - x2), (double)(y1 - y2)) * 57.2958) % 360;
-#endif
+ // SCI1 games (QFG2 and newer) use a simple atan implementation. SCI0 games
+ // use a somewhat less accurate calculation (below).
+ if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY)
+ return (int16)(360 - atan2((double)(x1 - x2), (double)(y1 - y2)) * 57.2958) % 360;
int16 xRel = x2 - x1;
int16 yRel = y1 - y2; // y-axis is mirrored.
diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp
index cb2a763da9..6bf9aff2fe 100644
--- a/engines/sci/engine/kvideo.cpp
+++ b/engines/sci/engine/kvideo.cpp
@@ -50,6 +50,8 @@ void playVideo(Video::VideoDecoder *videoDecoder, VideoState videoState) {
if (!videoDecoder)
return;
+ videoDecoder->start();
+
byte *scaleBuffer = 0;
byte bytesPerPixel = videoDecoder->getPixelFormat().bytesPerPixel;
uint16 width = videoDecoder->getWidth();
@@ -162,9 +164,8 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) {
} else {
// DOS SEQ
// SEQ's are called with no subops, just the string and delay
- SeqDecoder *seqDecoder = new SeqDecoder();
- seqDecoder->setFrameDelay(argv[1].toUint16()); // Time between frames in ticks
- videoDecoder = seqDecoder;
+ // Time is specified as ticks
+ videoDecoder = new SEQDecoder(argv[1].toUint16());
if (!videoDecoder->loadFile(filename)) {
warning("Failed to open movie file %s", filename.c_str());
@@ -190,7 +191,7 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) {
switch (argv[0].toUint16()) {
case 0: {
Common::String filename = s->_segMan->getString(argv[1]);
- videoDecoder = new Video::AviDecoder(g_system->getMixer());
+ videoDecoder = new Video::AVIDecoder();
if (filename.equalsIgnoreCase("gk2a.avi")) {
// HACK: Switch to 16bpp graphics for Indeo3.
@@ -252,6 +253,7 @@ reg_t kRobot(EngineState *s, int argc, reg_t *argv) {
int16 y = argv[5].toUint16();
warning("kRobot(init), id %d, obj %04x:%04x, flag %d, x=%d, y=%d", id, PRINT_REG(obj), flag, x, y);
g_sci->_robotDecoder->load(id);
+ g_sci->_robotDecoder->start();
g_sci->_robotDecoder->setPos(x, y);
}
break;
@@ -267,13 +269,13 @@ reg_t kRobot(EngineState *s, int argc, reg_t *argv) {
warning("kRobot(%d)", subop);
break;
case 8: // sync
- //if (false) { // debug: automatically skip all robot videos
- if ((uint32)g_sci->_robotDecoder->getCurFrame() != g_sci->_robotDecoder->getFrameCount() - 1) {
- writeSelector(s->_segMan, argv[1], SELECTOR(signal), NULL_REG);
- } else {
+ //if (true) { // debug: automatically skip all robot videos
+ if (g_sci->_robotDecoder->endOfVideo()) {
g_sci->_robotDecoder->close();
// Signal the engine scripts that the video is done
writeSelector(s->_segMan, argv[1], SELECTOR(signal), SIGNAL_REG);
+ } else {
+ writeSelector(s->_segMan, argv[1], SELECTOR(signal), NULL_REG);
}
break;
default:
@@ -348,7 +350,7 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) {
break;
}
case 6: // Play
- videoDecoder = new Video::VMDDecoder(g_system->getMixer());
+ videoDecoder = new Video::AdvancedVMDDecoder();
if (s->_videoState.fileName.empty()) {
// Happens in Lighthouse
@@ -406,7 +408,7 @@ reg_t kPlayDuck(EngineState *s, int argc, reg_t *argv) {
s->_videoState.reset();
s->_videoState.fileName = Common::String::format("%d.duk", argv[1].toUint16());
- videoDecoder = new Video::AviDecoder(g_system->getMixer());
+ videoDecoder = new Video::AVIDecoder();
if (!videoDecoder->loadFile(s->_videoState.fileName)) {
warning("Could not open Duck %s", s->_videoState.fileName.c_str());
diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp
index a4c2355e8f..9fa0368784 100644
--- a/engines/sci/engine/workarounds.cpp
+++ b/engines/sci/engine/workarounds.cpp
@@ -399,7 +399,7 @@ const SciWorkaroundEntry kUnLoad_workarounds[] = {
{ GID_LSL6, 740, 740, 0, "showCartoon", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during ending, 4 additional parameters are passed by accident
{ GID_LSL6HIRES, 130, 130, 0, "recruitLarryScr", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during intro, a 3rd parameter is passed by accident
{ GID_SQ1, 43, 303, 0, "slotGuy", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // when leaving ulence flats bar, parameter 1 is not passed - script error
- { GID_QFG4, 770, 110, 0, "dreamer", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during the dream sequence, a 3rd parameter is passed by accident
+ { GID_QFG4, -1, 110, 0, "dreamer", "dispose", -1, 0, { WORKAROUND_IGNORE, 0 } }, // during the dream sequence, a 3rd parameter is passed by accident
SCI_WORKAROUNDENTRY_TERMINATOR
};
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index 0098728e5d..968014c032 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -28,6 +28,7 @@
#include "common/system.h"
#include "common/textconsole.h"
#include "engines/engine.h"
+#include "graphics/palette.h"
#include "graphics/surface.h"
#include "sci/sci.h"
@@ -488,7 +489,7 @@ void GfxFrameout::showVideo() {
uint16 y = videoDecoder->getPos().y;
if (videoDecoder->hasDirtyPalette())
- videoDecoder->setSystemPalette();
+ g_system->getPaletteManager()->setPalette(videoDecoder->getPalette(), 0, 256);
while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) {
if (videoDecoder->needsUpdate()) {
@@ -497,7 +498,7 @@ void GfxFrameout::showVideo() {
g_system->copyRectToScreen(frame->pixels, frame->pitch, x, y, frame->w, frame->h);
if (videoDecoder->hasDirtyPalette())
- videoDecoder->setSystemPalette();
+ g_system->getPaletteManager()->setPalette(videoDecoder->getPalette(), 0, 256);
g_system->updateScreen();
}
@@ -728,7 +729,9 @@ void GfxFrameout::kernelFrameout() {
g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect);
}
- // FIXME: When does this happen, and why?
+ // Don't attempt to draw sprites that are outside the visible
+ // screen area. An example is the random people walking in
+ // Jackson Square in GK1.
if (itemEntry->celRect.bottom < 0 || itemEntry->celRect.top >= _screen->getDisplayHeight() ||
itemEntry->celRect.right < 0 || itemEntry->celRect.left >= _screen->getDisplayWidth())
continue;
diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp
index 68104b0ac8..53d69cdcca 100644
--- a/engines/sci/graphics/palette.cpp
+++ b/engines/sci/graphics/palette.cpp
@@ -375,6 +375,27 @@ void GfxPalette::setRemappingPercent(byte color, byte percent) {
_remappingType[color] = kRemappingByPercent;
}
+void GfxPalette::setRemappingPercentGray(byte color, byte percent) {
+ _remapOn = true;
+
+ // We need to defer the setup of the remapping table every time the screen
+ // palette is changed, so that kernelFindColor() can find the correct
+ // colors. Set it once here, in case the palette stays the same and update
+ // it on each palette change by copySysPaletteToScreen().
+ _remappingPercentToSet = percent;
+
+ // Note: This is not what the original does, but the results are the same visually
+ for (int i = 0; i < 256; i++) {
+ byte rComponent = _sysPalette.colors[i].r * _remappingPercentToSet * 0.30 / 100;
+ byte gComponent = _sysPalette.colors[i].g * _remappingPercentToSet * 0.59 / 100;
+ byte bComponent = _sysPalette.colors[i].b * _remappingPercentToSet * 0.11 / 100;
+ byte luminosity = rComponent + gComponent + bComponent;
+ _remappingByPercent[i] = kernelFindColor(luminosity, luminosity, luminosity);
+ }
+
+ _remappingType[color] = kRemappingByPercent;
+}
+
void GfxPalette::setRemappingRange(byte color, byte from, byte to, byte base) {
_remapOn = true;
diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h
index 9898315897..e974781d49 100644
--- a/engines/sci/graphics/palette.h
+++ b/engines/sci/graphics/palette.h
@@ -61,6 +61,7 @@ public:
void resetRemapping();
void setRemappingPercent(byte color, byte percent);
+ void setRemappingPercentGray(byte color, byte percent);
void setRemappingRange(byte color, byte from, byte to, byte base);
bool isRemapped(byte color) const {
return _remapOn && (_remappingType[color] != kRemappingNone);
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index d43a9d06fc..42ae00b525 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -632,7 +632,7 @@ void SciEngine::initGraphics() {
_gfxPaint = _gfxPaint32;
_gfxText32 = new GfxText32(_gamestate->_segMan, _gfxCache, _gfxScreen);
_gfxControls32 = new GfxControls32(_gamestate->_segMan, _gfxCache, _gfxScreen, _gfxText32);
- _robotDecoder = new RobotDecoder(g_system->getMixer(), getPlatform() == Common::kPlatformMacintosh);
+ _robotDecoder = new RobotDecoder(getPlatform() == Common::kPlatformMacintosh);
_gfxFrameout = new GfxFrameout(_gamestate->_segMan, _resMan, _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette, _gfxPaint32);
} else {
#endif
diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp
index 123dd21894..528bb51393 100644
--- a/engines/sci/sound/audio.cpp
+++ b/engines/sci/sound/audio.cpp
@@ -67,7 +67,8 @@ int AudioPlayer::startAudio(uint16 module, uint32 number) {
if (audioStream) {
_wPlayFlag = false;
- _mixer->playStream(Audio::Mixer::kSpeechSoundType, &_audioHandle, audioStream);
+ Audio::Mixer::SoundType soundType = (module == 65535) ? Audio::Mixer::kSFXSoundType : Audio::Mixer::kSpeechSoundType;
+ _mixer->playStream(soundType, &_audioHandle, audioStream);
return sampleLen;
} else {
// Don't throw a warning in this case. getAudioStream() already has. Some games
diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp
index cbb5cab4fe..5d32f40f18 100644
--- a/engines/sci/sound/soundcmd.cpp
+++ b/engines/sci/sound/soundcmd.cpp
@@ -96,7 +96,7 @@ void SoundCommandParser::initSoundResource(MusicEntry *newSound) {
if (_useDigitalSFX || !newSound->soundRes) {
int sampleLen;
newSound->pStreamAud = _audio->getAudioStream(newSound->resourceId, 65535, &sampleLen);
- newSound->soundType = Audio::Mixer::kSpeechSoundType;
+ newSound->soundType = Audio::Mixer::kSFXSoundType;
}
}
@@ -367,29 +367,36 @@ reg_t SoundCommandParser::kDoSoundFade(int argc, reg_t *argv, reg_t acc) {
case 4: // SCI01+
case 5: // SCI1+ (SCI1 late sound scheme), with fade and continue
- musicSlot->fadeTo = CLIP<uint16>(argv[1].toUint16(), 0, MUSIC_VOLUME_MAX);
- // Check if the song is already at the requested volume. If it is, don't
- // perform any fading. Happens for example during the intro of Longbow.
- if (musicSlot->fadeTo == musicSlot->volume)
- return acc;
-
- // sometimes we get objects in that position, fix it up (ffs. workarounds)
- if (!argv[1].getSegment())
- musicSlot->fadeStep = volume > musicSlot->fadeTo ? -argv[3].toUint16() : argv[3].toUint16();
- else
- musicSlot->fadeStep = volume > musicSlot->fadeTo ? -5 : 5;
- musicSlot->fadeTickerStep = argv[2].toUint16() * 16667 / _music->soundGetTempo();
- musicSlot->fadeTicker = 0;
-
if (argc == 5) {
// TODO: We currently treat this argument as a boolean, but may
// have to handle different non-zero values differently. (e.g.,
- // some KQ6 scripts pass 3 here)
- musicSlot->stopAfterFading = (argv[4].toUint16() != 0);
+ // some KQ6 scripts pass 3 here).
+ // There is a script bug in KQ6, room 460 (the room with the flying
+ // books). An object is passed here, which should not be treated as
+ // a true flag. Fixes bugs #3555404 and #3291115.
+ musicSlot->stopAfterFading = (argv[4].isNumber() && argv[4].toUint16() != 0);
} else {
musicSlot->stopAfterFading = false;
}
+ musicSlot->fadeTo = CLIP<uint16>(argv[1].toUint16(), 0, MUSIC_VOLUME_MAX);
+ // Check if the song is already at the requested volume. If it is, don't
+ // perform any fading. Happens for example during the intro of Longbow.
+ if (musicSlot->fadeTo != musicSlot->volume) {
+ // sometimes we get objects in that position, fix it up (ffs. workarounds)
+ if (!argv[1].getSegment())
+ musicSlot->fadeStep = volume > musicSlot->fadeTo ? -argv[3].toUint16() : argv[3].toUint16();
+ else
+ musicSlot->fadeStep = volume > musicSlot->fadeTo ? -5 : 5;
+ musicSlot->fadeTickerStep = argv[2].toUint16() * 16667 / _music->soundGetTempo();
+ } else {
+ // Stop the music, if requested. Fixes bug #3555404.
+ if (musicSlot->stopAfterFading)
+ processStopSound(obj, false);
+ }
+
+ musicSlot->fadeTicker = 0;
+
// WORKAROUND/HACK: In the labyrinth in KQ6, when falling in the pit and
// lighting the lantern, the game scripts perform a fade in of the game
// music, but set it to stop after fading. Remove that flag here. This is
diff --git a/engines/sci/video/robot_decoder.cpp b/engines/sci/video/robot_decoder.cpp
index ebcfac6054..608c77136f 100644
--- a/engines/sci/video/robot_decoder.cpp
+++ b/engines/sci/video/robot_decoder.cpp
@@ -22,11 +22,13 @@
#include "common/archive.h"
#include "common/stream.h"
+#include "common/substream.h"
#include "common/system.h"
#include "common/textconsole.h"
#include "common/util.h"
#include "graphics/surface.h"
+#include "audio/audiostream.h"
#include "audio/decoders/raw.h"
#include "sci/resource.h"
@@ -63,57 +65,26 @@ namespace Sci {
// our graphics engine, it looks just like a part of the room. A RBT can move
// around the screen and go behind other objects. (...)
-#ifdef ENABLE_SCI32
-
-enum robotPalTypes {
+enum RobotPalTypes {
kRobotPalVariable = 0,
kRobotPalConstant = 1
};
-RobotDecoder::RobotDecoder(Audio::Mixer *mixer, bool isBigEndian) {
- _surface = 0;
- _width = 0;
- _height = 0;
+RobotDecoder::RobotDecoder(bool isBigEndian) {
_fileStream = 0;
- _audioStream = 0;
- _dirtyPalette = false;
_pos = Common::Point(0, 0);
- _mixer = mixer;
_isBigEndian = isBigEndian;
+ _frameTotalSize = 0;
}
RobotDecoder::~RobotDecoder() {
close();
}
-bool RobotDecoder::load(GuiResourceId id) {
- // TODO: RAMA's robot 1003 cannot be played (shown at the menu screen) -
- // its drawn at odd coordinates. SV can't play it either (along with some
- // others), so it must be some new functionality added in RAMA's robot
- // videos. Skip it for now.
- if (g_sci->getGameId() == GID_RAMA && id == 1003)
- return false;
-
- // TODO: The robot video in the Lighthouse demo gets stuck
- if (g_sci->getGameId() == GID_LIGHTHOUSE && id == 16)
- return false;
-
- Common::String fileName = Common::String::format("%d.rbt", id);
- Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(fileName);
-
- if (!stream) {
- warning("Unable to open robot file %s", fileName.c_str());
- return false;
- }
-
- return loadStream(stream);
-}
-
bool RobotDecoder::loadStream(Common::SeekableReadStream *stream) {
close();
_fileStream = new Common::SeekableSubReadStreamEndian(stream, 0, stream->size(), _isBigEndian, DisposeAfterUse::YES);
- _surface = new Graphics::Surface();
readHeaderChunk();
@@ -125,131 +96,60 @@ bool RobotDecoder::loadStream(Common::SeekableReadStream *stream) {
if (_header.version < 4 || _header.version > 6)
error("Unknown robot version: %d", _header.version);
- if (_header.hasSound) {
- _audioStream = Audio::makeQueuingAudioStream(11025, false);
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &_audioHandle, _audioStream, -1, getVolume(), getBalance());
- }
+ RobotVideoTrack *videoTrack = new RobotVideoTrack(_header.frameCount);
+ addTrack(videoTrack);
- readPaletteChunk(_header.paletteDataSize);
- readFrameSizesChunk();
- calculateVideoDimensions();
- _surface->create(_width, _height, Graphics::PixelFormat::createFormatCLUT8());
+ if (_header.hasSound)
+ addTrack(new RobotAudioTrack());
+ videoTrack->readPaletteChunk(_fileStream, _header.paletteDataSize);
+ readFrameSizesChunk();
+ videoTrack->calculateVideoDimensions(_fileStream, _frameTotalSize);
return true;
}
-void RobotDecoder::readHeaderChunk() {
- // Header (60 bytes)
- _fileStream->skip(6);
- _header.version = _fileStream->readUint16();
- _header.audioChunkSize = _fileStream->readUint16();
- _header.audioSilenceSize = _fileStream->readUint16();
- _fileStream->skip(2);
- _header.frameCount = _fileStream->readUint16();
- _header.paletteDataSize = _fileStream->readUint16();
- _header.unkChunkDataSize = _fileStream->readUint16();
- _fileStream->skip(5);
- _header.hasSound = _fileStream->readByte();
- _fileStream->skip(34);
-
- // Some videos (e.g. robot 1305 in Phantasmagoria and
- // robot 184 in Lighthouse) have an unknown chunk before
- // the palette chunk (probably used for sound preloading).
- // Skip it here.
- if (_header.unkChunkDataSize)
- _fileStream->skip(_header.unkChunkDataSize);
-}
-
-void RobotDecoder::readPaletteChunk(uint16 chunkSize) {
- byte *paletteData = new byte[chunkSize];
- _fileStream->read(paletteData, chunkSize);
-
- // SCI1.1 palette
- byte palFormat = paletteData[32];
- uint16 palColorStart = paletteData[25];
- uint16 palColorCount = READ_SCI11ENDIAN_UINT16(paletteData + 29);
+bool RobotDecoder::load(GuiResourceId id) {
+ // TODO: RAMA's robot 1003 cannot be played (shown at the menu screen) -
+ // its drawn at odd coordinates. SV can't play it either (along with some
+ // others), so it must be some new functionality added in RAMA's robot
+ // videos. Skip it for now.
+ if (g_sci->getGameId() == GID_RAMA && id == 1003)
+ return false;
+
+ // TODO: The robot video in the Lighthouse demo gets stuck
+ if (g_sci->getGameId() == GID_LIGHTHOUSE && id == 16)
+ return false;
- int palOffset = 37;
- memset(_palette, 0, 256 * 3);
+ Common::String fileName = Common::String::format("%d.rbt", id);
+ Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(fileName);
- for (uint16 colorNo = palColorStart; colorNo < palColorStart + palColorCount; colorNo++) {
- if (palFormat == kRobotPalVariable)
- palOffset++;
- _palette[colorNo * 3 + 0] = paletteData[palOffset++];
- _palette[colorNo * 3 + 1] = paletteData[palOffset++];
- _palette[colorNo * 3 + 2] = paletteData[palOffset++];
+ if (!stream) {
+ warning("Unable to open robot file %s", fileName.c_str());
+ return false;
}
- _dirtyPalette = true;
- delete[] paletteData;
+ return loadStream(stream);
}
+void RobotDecoder::close() {
+ VideoDecoder::close();
-void RobotDecoder::readFrameSizesChunk() {
- // The robot video file contains 2 tables, with one entry for each frame:
- // - A table containing the size of the image in each video frame
- // - A table containing the total size of each video frame.
- // In v5 robots, the tables contain 16-bit integers, whereas in v6 robots,
- // they contain 32-bit integers.
-
- _frameTotalSize = new uint32[_header.frameCount];
-
- // TODO: The table reading code can probably be removed once the
- // audio chunk size is figured out (check the TODO inside processNextFrame())
-#if 0
- // We don't need any of the two tables to play the video, so we ignore
- // both of them.
- uint16 wordSize = _header.version == 6 ? 4 : 2;
- _fileStream->skip(_header.frameCount * wordSize * 2);
-#else
- switch (_header.version) {
- case 4:
- case 5: // sizes are 16-bit integers
- // Skip table with frame image sizes, as we don't need it
- _fileStream->skip(_header.frameCount * 2);
- for (int i = 0; i < _header.frameCount; ++i)
- _frameTotalSize[i] = _fileStream->readUint16();
- break;
- case 6: // sizes are 32-bit integers
- // Skip table with frame image sizes, as we don't need it
- _fileStream->skip(_header.frameCount * 4);
- for (int i = 0; i < _header.frameCount; ++i)
- _frameTotalSize[i] = _fileStream->readUint32();
- break;
- default:
- error("Can't yet handle index table for robot version %d", _header.version);
- }
-#endif
-
- // 2 more unknown tables
- _fileStream->skip(1024 + 512);
+ delete _fileStream;
+ _fileStream = 0;
- // Pad to nearest 2 kilobytes
- uint32 curPos = _fileStream->pos();
- if (curPos & 0x7ff)
- _fileStream->seek((curPos & ~0x7ff) + 2048);
+ delete[] _frameTotalSize;
+ _frameTotalSize = 0;
}
-void RobotDecoder::calculateVideoDimensions() {
- // This is an O(n) operation, as each frame has a different size.
- // We need to know the actual frame size to have a constant video size.
- uint32 pos = _fileStream->pos();
-
- for (uint32 curFrame = 0; curFrame < _header.frameCount; curFrame++) {
- _fileStream->skip(4);
- uint16 frameWidth = _fileStream->readUint16();
- uint16 frameHeight = _fileStream->readUint16();
- if (frameWidth > _width)
- _width = frameWidth;
- if (frameHeight > _height)
- _height = frameHeight;
- _fileStream->skip(_frameTotalSize[curFrame] - 8);
- }
+void RobotDecoder::readNextPacket() {
+ // Get our track
+ RobotVideoTrack *videoTrack = (RobotVideoTrack *)getTrack(0);
+ videoTrack->increaseCurFrame();
+ Graphics::Surface *surface = videoTrack->getSurface();
- _fileStream->seek(pos);
-}
+ if (videoTrack->endOfTrack())
+ return;
-const Graphics::Surface *RobotDecoder::decodeNextFrame() {
// Read frame image header (24 bytes)
_fileStream->skip(3);
byte frameScale = _fileStream->readByte();
@@ -258,23 +158,28 @@ const Graphics::Surface *RobotDecoder::decodeNextFrame() {
_fileStream->skip(4); // unknown, almost always 0
uint16 frameX = _fileStream->readUint16();
uint16 frameY = _fileStream->readUint16();
+
// TODO: In v4 robot files, frameX and frameY have a different meaning.
// Set them both to 0 for v4 for now, so that robots in PQ:SWAT show up
// correctly.
if (_header.version == 4)
frameX = frameY = 0;
+
uint16 compressedSize = _fileStream->readUint16();
uint16 frameFragments = _fileStream->readUint16();
_fileStream->skip(4); // unknown
uint32 decompressedSize = frameWidth * frameHeight * frameScale / 100;
+
// FIXME: A frame's height + position can go off limits... why? With the
// following, we cut the contents to fit the frame
- uint16 scaledHeight = CLIP<uint16>(decompressedSize / frameWidth, 0, _height - frameY);
+ uint16 scaledHeight = CLIP<uint16>(decompressedSize / frameWidth, 0, surface->h - frameY);
+
// FIXME: Same goes for the frame's width + position. In this case, we
// modify the position to fit the contents on screen.
- if (frameWidth + frameX > _width)
- frameX = _width - frameWidth;
- assert (frameWidth + frameX <= _width && scaledHeight + frameY <= _height);
+ if (frameWidth + frameX > surface->w)
+ frameX = surface->w - frameWidth;
+
+ assert(frameWidth + frameX <= surface->w && scaledHeight + frameY <= surface->h);
DecompressorLZS lzs;
byte *decompressedFrame = new byte[decompressedSize];
@@ -305,24 +210,23 @@ const Graphics::Surface *RobotDecoder::decodeNextFrame() {
// Copy over the decompressed frame
byte *inFrame = decompressedFrame;
- byte *outFrame = (byte *)_surface->pixels;
+ byte *outFrame = (byte *)surface->pixels;
// Black out the surface
- memset(outFrame, 0, _width * _height);
+ memset(outFrame, 0, surface->w * surface->h);
// Move to the correct y coordinate
- outFrame += _width * frameY;
+ outFrame += surface->w * frameY;
for (uint16 y = 0; y < scaledHeight; y++) {
memcpy(outFrame + frameX, inFrame, frameWidth);
inFrame += frameWidth;
- outFrame += _width;
+ outFrame += surface->w;
}
delete[] decompressedFrame;
- // +1 because we start with frame number -1
- uint32 audioChunkSize = _frameTotalSize[_curFrame + 1] - (24 + compressedSize);
+ uint32 audioChunkSize = _frameTotalSize[videoTrack->getCurFrame()] - (24 + compressedSize);
// TODO: The audio chunk size below is usually correct, but there are some
// exceptions (e.g. robot 4902 in Phantasmagoria, towards its end)
@@ -337,51 +241,166 @@ const Graphics::Surface *RobotDecoder::decodeNextFrame() {
// Queue the next audio frame
// FIXME: For some reason, there are audio hiccups/gaps
if (_header.hasSound) {
- _fileStream->skip(8); // header
- _audioStream->queueBuffer(g_sci->_audio->getDecodedRobotAudioFrame(_fileStream, audioChunkSize - 8),
- (audioChunkSize - 8) * 2, DisposeAfterUse::NO,
- Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN);
+ RobotAudioTrack *audioTrack = (RobotAudioTrack *)getTrack(1);
+ _fileStream->skip(8); // header
+ audioChunkSize -= 8;
+ audioTrack->queueBuffer(g_sci->_audio->getDecodedRobotAudioFrame(_fileStream, audioChunkSize), audioChunkSize * 2);
} else {
_fileStream->skip(audioChunkSize);
- }
-
- if (_curFrame == -1)
- _startTime = g_system->getMillis();
+ }
+}
- _curFrame++;
+void RobotDecoder::readHeaderChunk() {
+ // Header (60 bytes)
+ _fileStream->skip(6);
+ _header.version = _fileStream->readUint16();
+ _header.audioChunkSize = _fileStream->readUint16();
+ _header.audioSilenceSize = _fileStream->readUint16();
+ _fileStream->skip(2);
+ _header.frameCount = _fileStream->readUint16();
+ _header.paletteDataSize = _fileStream->readUint16();
+ _header.unkChunkDataSize = _fileStream->readUint16();
+ _fileStream->skip(5);
+ _header.hasSound = _fileStream->readByte();
+ _fileStream->skip(34);
- return _surface;
+ // Some videos (e.g. robot 1305 in Phantasmagoria and
+ // robot 184 in Lighthouse) have an unknown chunk before
+ // the palette chunk (probably used for sound preloading).
+ // Skip it here.
+ if (_header.unkChunkDataSize)
+ _fileStream->skip(_header.unkChunkDataSize);
}
-void RobotDecoder::close() {
- if (!_fileStream)
- return;
+void RobotDecoder::readFrameSizesChunk() {
+ // The robot video file contains 2 tables, with one entry for each frame:
+ // - A table containing the size of the image in each video frame
+ // - A table containing the total size of each video frame.
+ // In v5 robots, the tables contain 16-bit integers, whereas in v6 robots,
+ // they contain 32-bit integers.
- delete _fileStream;
- _fileStream = 0;
+ _frameTotalSize = new uint32[_header.frameCount];
+ // TODO: The table reading code can probably be removed once the
+ // audio chunk size is figured out (check the TODO inside processNextFrame())
+#if 0
+ // We don't need any of the two tables to play the video, so we ignore
+ // both of them.
+ uint16 wordSize = _header.version == 6 ? 4 : 2;
+ _fileStream->skip(_header.frameCount * wordSize * 2);
+#else
+ switch (_header.version) {
+ case 4:
+ case 5: // sizes are 16-bit integers
+ // Skip table with frame image sizes, as we don't need it
+ _fileStream->skip(_header.frameCount * 2);
+ for (int i = 0; i < _header.frameCount; ++i)
+ _frameTotalSize[i] = _fileStream->readUint16();
+ break;
+ case 6: // sizes are 32-bit integers
+ // Skip table with frame image sizes, as we don't need it
+ _fileStream->skip(_header.frameCount * 4);
+ for (int i = 0; i < _header.frameCount; ++i)
+ _frameTotalSize[i] = _fileStream->readUint32();
+ break;
+ default:
+ error("Can't yet handle index table for robot version %d", _header.version);
+ }
+#endif
+
+ // 2 more unknown tables
+ _fileStream->skip(1024 + 512);
+
+ // Pad to nearest 2 kilobytes
+ uint32 curPos = _fileStream->pos();
+ if (curPos & 0x7ff)
+ _fileStream->seek((curPos & ~0x7ff) + 2048);
+}
+
+RobotDecoder::RobotVideoTrack::RobotVideoTrack(int frameCount) : _frameCount(frameCount) {
+ _surface = new Graphics::Surface();
+ _curFrame = -1;
+ _dirtyPalette = false;
+}
+
+RobotDecoder::RobotVideoTrack::~RobotVideoTrack() {
_surface->free();
delete _surface;
- _surface = 0;
+}
- if (_header.hasSound) {
- _mixer->stopHandle(_audioHandle);
- //delete _audioStream; _audioStream = 0;
+uint16 RobotDecoder::RobotVideoTrack::getWidth() const {
+ return _surface->w;
+}
+
+uint16 RobotDecoder::RobotVideoTrack::getHeight() const {
+ return _surface->h;
+}
+
+Graphics::PixelFormat RobotDecoder::RobotVideoTrack::getPixelFormat() const {
+ return _surface->format;
+}
+
+void RobotDecoder::RobotVideoTrack::readPaletteChunk(Common::SeekableSubReadStreamEndian *stream, uint16 chunkSize) {
+ byte *paletteData = new byte[chunkSize];
+ stream->read(paletteData, chunkSize);
+
+ // SCI1.1 palette
+ byte palFormat = paletteData[32];
+ uint16 palColorStart = paletteData[25];
+ uint16 palColorCount = READ_SCI11ENDIAN_UINT16(paletteData + 29);
+
+ int palOffset = 37;
+ memset(_palette, 0, 256 * 3);
+
+ for (uint16 colorNo = palColorStart; colorNo < palColorStart + palColorCount; colorNo++) {
+ if (palFormat == kRobotPalVariable)
+ palOffset++;
+ _palette[colorNo * 3 + 0] = paletteData[palOffset++];
+ _palette[colorNo * 3 + 1] = paletteData[palOffset++];
+ _palette[colorNo * 3 + 2] = paletteData[palOffset++];
}
- reset();
+ _dirtyPalette = true;
+ delete[] paletteData;
}
-void RobotDecoder::updateVolume() {
- if (g_system->getMixer()->isSoundHandleActive(_audioHandle))
- g_system->getMixer()->setChannelVolume(_audioHandle, getVolume());
+void RobotDecoder::RobotVideoTrack::calculateVideoDimensions(Common::SeekableSubReadStreamEndian *stream, uint32 *frameSizes) {
+ // This is an O(n) operation, as each frame has a different size.
+ // We need to know the actual frame size to have a constant video size.
+ uint32 pos = stream->pos();
+
+ uint16 width = 0, height = 0;
+
+ for (int curFrame = 0; curFrame < _frameCount; curFrame++) {
+ stream->skip(4);
+ uint16 frameWidth = stream->readUint16();
+ uint16 frameHeight = stream->readUint16();
+ if (frameWidth > width)
+ width = frameWidth;
+ if (frameHeight > height)
+ height = frameHeight;
+ stream->skip(frameSizes[curFrame] - 8);
+ }
+
+ stream->seek(pos);
+
+ _surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
}
-void RobotDecoder::updateBalance() {
- if (g_system->getMixer()->isSoundHandleActive(_audioHandle))
- g_system->getMixer()->setChannelBalance(_audioHandle, getBalance());
+RobotDecoder::RobotAudioTrack::RobotAudioTrack() {
+ _audioStream = Audio::makeQueuingAudioStream(11025, false);
}
-#endif
+RobotDecoder::RobotAudioTrack::~RobotAudioTrack() {
+ delete _audioStream;
+}
+
+void RobotDecoder::RobotAudioTrack::queueBuffer(byte *buffer, int size) {
+ _audioStream->queueBuffer(buffer, size, DisposeAfterUse::YES, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN);
+}
+
+Audio::AudioStream *RobotDecoder::RobotAudioTrack::getAudioStream() const {
+ return _audioStream;
+}
} // End of namespace Sci
diff --git a/engines/sci/video/robot_decoder.h b/engines/sci/video/robot_decoder.h
index e9cefe7d91..ebc3262939 100644
--- a/engines/sci/video/robot_decoder.h
+++ b/engines/sci/video/robot_decoder.h
@@ -25,84 +25,103 @@
#include "common/rational.h"
#include "common/rect.h"
-#include "common/stream.h"
-#include "common/substream.h"
-#include "audio/audiostream.h"
-#include "audio/mixer.h"
-#include "graphics/pixelformat.h"
#include "video/video_decoder.h"
-namespace Sci {
+namespace Audio {
+class QueuingAudioStream;
+}
-#ifdef ENABLE_SCI32
-
-struct RobotHeader {
- // 6 bytes, identifier bytes
- uint16 version;
- uint16 audioChunkSize;
- uint16 audioSilenceSize;
- // 2 bytes, unknown
- uint16 frameCount;
- uint16 paletteDataSize;
- uint16 unkChunkDataSize;
- // 5 bytes, unknown
- byte hasSound;
- // 34 bytes, unknown
-};
+namespace Common {
+class SeekableSubReadStreamEndian;
+}
+
+namespace Sci {
-class RobotDecoder : public Video::FixedRateVideoDecoder {
+class RobotDecoder : public Video::VideoDecoder {
public:
- RobotDecoder(Audio::Mixer *mixer, bool isBigEndian);
+ RobotDecoder(bool isBigEndian);
virtual ~RobotDecoder();
bool loadStream(Common::SeekableReadStream *stream);
bool load(GuiResourceId id);
void close();
-
- bool isVideoLoaded() const { return _fileStream != 0; }
- uint16 getWidth() const { return _width; }
- uint16 getHeight() const { return _height; }
- uint32 getFrameCount() const { return _header.frameCount; }
- const Graphics::Surface *decodeNextFrame();
- Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); }
- const byte *getPalette() { _dirtyPalette = false; return _palette; }
- bool hasDirtyPalette() const { return _dirtyPalette; }
+
void setPos(uint16 x, uint16 y) { _pos = Common::Point(x, y); }
Common::Point getPos() const { return _pos; }
protected:
- // VideoDecoder API
- void updateVolume();
- void updateBalance();
-
- // FixedRateVideoDecoder API
- Common::Rational getFrameRate() const { return Common::Rational(60, 10); }
-
+ void readNextPacket();
+
private:
+ class RobotVideoTrack : public FixedRateVideoTrack {
+ public:
+ RobotVideoTrack(int frameCount);
+ ~RobotVideoTrack();
+
+ uint16 getWidth() const;
+ uint16 getHeight() const;
+ Graphics::PixelFormat getPixelFormat() const;
+ int getCurFrame() const { return _curFrame; }
+ int getFrameCount() const { return _frameCount; }
+ const Graphics::Surface *decodeNextFrame() { return _surface; }
+ const byte *getPalette() const { _dirtyPalette = false; return _palette; }
+ bool hasDirtyPalette() const { return _dirtyPalette; }
+
+ void readPaletteChunk(Common::SeekableSubReadStreamEndian *stream, uint16 chunkSize);
+ void calculateVideoDimensions(Common::SeekableSubReadStreamEndian *stream, uint32 *frameSizes);
+ Graphics::Surface *getSurface() { return _surface; }
+ void increaseCurFrame() { _curFrame++; }
+
+ protected:
+ Common::Rational getFrameRate() const { return Common::Rational(60, 10); }
+
+ private:
+ int _frameCount;
+ int _curFrame;
+ byte _palette[256 * 3];
+ mutable bool _dirtyPalette;
+ Graphics::Surface *_surface;
+ };
+
+ class RobotAudioTrack : public AudioTrack {
+ public:
+ RobotAudioTrack();
+ ~RobotAudioTrack();
+
+ Audio::Mixer::SoundType getSoundType() const { return Audio::Mixer::kMusicSoundType; }
+
+ void queueBuffer(byte *buffer, int size);
+
+ protected:
+ Audio::AudioStream *getAudioStream() const;
+
+ private:
+ Audio::QueuingAudioStream *_audioStream;
+ };
+
+ struct RobotHeader {
+ // 6 bytes, identifier bytes
+ uint16 version;
+ uint16 audioChunkSize;
+ uint16 audioSilenceSize;
+ // 2 bytes, unknown
+ uint16 frameCount;
+ uint16 paletteDataSize;
+ uint16 unkChunkDataSize;
+ // 5 bytes, unknown
+ byte hasSound;
+ // 34 bytes, unknown
+ } _header;
+
void readHeaderChunk();
- void readPaletteChunk(uint16 chunkSize);
void readFrameSizesChunk();
- void calculateVideoDimensions();
-
- void freeData();
- RobotHeader _header;
Common::Point _pos;
bool _isBigEndian;
+ uint32 *_frameTotalSize;
Common::SeekableSubReadStreamEndian *_fileStream;
-
- uint16 _width;
- uint16 _height;
- uint32 *_frameTotalSize;
- byte _palette[256 * 3];
- bool _dirtyPalette;
- Graphics::Surface *_surface;
- Audio::QueuingAudioStream *_audioStream;
- Audio::SoundHandle _audioHandle;
- Audio::Mixer *_mixer;
};
-#endif
} // End of namespace Sci
diff --git a/engines/sci/video/seq_decoder.cpp b/engines/sci/video/seq_decoder.cpp
index abd64911a7..a7b6346eca 100644
--- a/engines/sci/video/seq_decoder.cpp
+++ b/engines/sci/video/seq_decoder.cpp
@@ -41,33 +41,44 @@ enum seqFrameTypes {
kSeqFrameDiff = 1
};
-SeqDecoder::SeqDecoder() {
- _fileStream = 0;
- _surface = 0;
- _dirtyPalette = false;
+SEQDecoder::SEQDecoder(uint frameDelay) : _frameDelay(frameDelay) {
}
-SeqDecoder::~SeqDecoder() {
+SEQDecoder::~SEQDecoder() {
close();
}
-bool SeqDecoder::loadStream(Common::SeekableReadStream *stream) {
+bool SEQDecoder::loadStream(Common::SeekableReadStream *stream) {
close();
+ addTrack(new SEQVideoTrack(stream, _frameDelay));
+
+ return true;
+}
+
+SEQDecoder::SEQVideoTrack::SEQVideoTrack(Common::SeekableReadStream *stream, uint frameDelay) {
+ assert(stream);
+ assert(frameDelay != 0);
_fileStream = stream;
+ _frameDelay = frameDelay;
+ _curFrame = -1;
+
_surface = new Graphics::Surface();
_surface->create(SEQ_SCREEN_WIDTH, SEQ_SCREEN_HEIGHT, Graphics::PixelFormat::createFormatCLUT8());
_frameCount = _fileStream->readUint16LE();
- // Set palette
- int paletteChunkSize = _fileStream->readUint32LE();
- readPaletteChunk(paletteChunkSize);
+ // Set initial palette
+ readPaletteChunk(_fileStream->readUint32LE());
+}
- return true;
+SEQDecoder::SEQVideoTrack::~SEQVideoTrack() {
+ delete _fileStream;
+ _surface->free();
+ delete _surface;
}
-void SeqDecoder::readPaletteChunk(uint16 chunkSize) {
+void SEQDecoder::SEQVideoTrack::readPaletteChunk(uint16 chunkSize) {
byte *paletteData = new byte[chunkSize];
_fileStream->read(paletteData, chunkSize);
@@ -91,23 +102,7 @@ void SeqDecoder::readPaletteChunk(uint16 chunkSize) {
delete[] paletteData;
}
-void SeqDecoder::close() {
- if (!_fileStream)
- return;
-
- _frameDelay = 0;
-
- delete _fileStream;
- _fileStream = 0;
-
- _surface->free();
- delete _surface;
- _surface = 0;
-
- reset();
-}
-
-const Graphics::Surface *SeqDecoder::decodeNextFrame() {
+const Graphics::Surface *SEQDecoder::SEQVideoTrack::decodeNextFrame() {
int16 frameWidth = _fileStream->readUint16LE();
int16 frameHeight = _fileStream->readUint16LE();
int16 frameLeft = _fileStream->readUint16LE();
@@ -142,9 +137,6 @@ const Graphics::Surface *SeqDecoder::decodeNextFrame() {
delete[] buf;
}
- if (_curFrame == -1)
- _startTime = g_system->getMillis();
-
_curFrame++;
return _surface;
}
@@ -159,7 +151,7 @@ const Graphics::Surface *SeqDecoder::decodeNextFrame() {
} \
memcpy(dest + writeRow * SEQ_SCREEN_WIDTH + writeCol, litData + litPos, n);
-bool SeqDecoder::decodeFrame(byte *rleData, int rleSize, byte *litData, int litSize, byte *dest, int left, int width, int height, int colorKey) {
+bool SEQDecoder::SEQVideoTrack::decodeFrame(byte *rleData, int rleSize, byte *litData, int litSize, byte *dest, int left, int width, int height, int colorKey) {
int writeRow = 0;
int writeCol = left;
int litPos = 0;
@@ -237,4 +229,9 @@ bool SeqDecoder::decodeFrame(byte *rleData, int rleSize, byte *litData, int litS
return true;
}
+const byte *SEQDecoder::SEQVideoTrack::getPalette() const {
+ _dirtyPalette = false;
+ return _palette;
+}
+
} // End of namespace Sci
diff --git a/engines/sci/video/seq_decoder.h b/engines/sci/video/seq_decoder.h
index 800a3c9024..890f349feb 100644
--- a/engines/sci/video/seq_decoder.h
+++ b/engines/sci/video/seq_decoder.h
@@ -40,44 +40,49 @@ namespace Sci {
/**
* Implementation of the Sierra SEQ decoder, used in KQ6 DOS floppy/CD and GK1 DOS
*/
-class SeqDecoder : public Video::FixedRateVideoDecoder {
+class SEQDecoder : public Video::VideoDecoder {
public:
- SeqDecoder();
- virtual ~SeqDecoder();
+ SEQDecoder(uint frameDelay);
+ virtual ~SEQDecoder();
bool loadStream(Common::SeekableReadStream *stream);
- void close();
-
- void setFrameDelay(int frameDelay) { _frameDelay = frameDelay; }
-
- bool isVideoLoaded() const { return _fileStream != 0; }
- uint16 getWidth() const { return SEQ_SCREEN_WIDTH; }
- uint16 getHeight() const { return SEQ_SCREEN_HEIGHT; }
- uint32 getFrameCount() const { return _frameCount; }
- const Graphics::Surface *decodeNextFrame();
- Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); }
- const byte *getPalette() { _dirtyPalette = false; return _palette; }
- bool hasDirtyPalette() const { return _dirtyPalette; }
-
-protected:
- Common::Rational getFrameRate() const { assert(_frameDelay); return Common::Rational(60, _frameDelay); }
private:
- enum {
- SEQ_SCREEN_WIDTH = 320,
- SEQ_SCREEN_HEIGHT = 200
+ class SEQVideoTrack : public FixedRateVideoTrack {
+ public:
+ SEQVideoTrack(Common::SeekableReadStream *stream, uint frameDelay);
+ ~SEQVideoTrack();
+
+ uint16 getWidth() const { return SEQ_SCREEN_WIDTH; }
+ uint16 getHeight() const { return SEQ_SCREEN_HEIGHT; }
+ Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); }
+ int getCurFrame() const { return _curFrame; }
+ int getFrameCount() const { return _frameCount; }
+ const Graphics::Surface *decodeNextFrame();
+ const byte *getPalette() const;
+ bool hasDirtyPalette() const { return _dirtyPalette; }
+
+ protected:
+ Common::Rational getFrameRate() const { return Common::Rational(60, _frameDelay); }
+
+ private:
+ enum {
+ SEQ_SCREEN_WIDTH = 320,
+ SEQ_SCREEN_HEIGHT = 200
+ };
+
+ void readPaletteChunk(uint16 chunkSize);
+ bool decodeFrame(byte *rleData, int rleSize, byte *litData, int litSize, byte *dest, int left, int width, int height, int colorKey);
+
+ Common::SeekableReadStream *_fileStream;
+ int _curFrame, _frameCount;
+ byte _palette[256 * 3];
+ mutable bool _dirtyPalette;
+ Graphics::Surface *_surface;
+ uint _frameDelay;
};
- void readPaletteChunk(uint16 chunkSize);
- bool decodeFrame(byte *rleData, int rleSize, byte *litData, int litSize, byte *dest, int left, int width, int height, int colorKey);
-
- uint16 _width, _height;
- uint16 _frameDelay;
- Common::SeekableReadStream *_fileStream;
- byte _palette[256 * 3];
- bool _dirtyPalette;
- uint32 _frameCount;
- Graphics::Surface *_surface;
+ uint _frameDelay;
};
} // End of namespace Sci
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index 87305921c9..5404c7f8b1 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -20,9 +20,6 @@
*
*/
-// FIXME: Avoid using printf
-#define FORBIDDEN_SYMBOL_EXCEPTION_printf
-
#include "base/plugins.h"
#include "common/archive.h"
@@ -1066,15 +1063,19 @@ Common::Error ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) co
// unknown MD5, or with a medium debug level in case of a known MD5 (for
// debugging purposes).
if (!findInMD5Table(res.md5.c_str())) {
- printf("Your game version appears to be unknown. If this is *NOT* a fan-modified\n");
- printf("version (in particular, not a fan-made translation), please, report the\n");
- printf("following data to the ScummVM team along with name of the game you tried\n");
- printf("to add and its version/language/etc.:\n");
+ Common::String md5Warning;
+
+ md5Warning = "Your game version appears to be unknown. If this is *NOT* a fan-modified\n";
+ md5Warning += "version (in particular, not a fan-made translation), please, report the\n";
+ md5Warning += "following data to the ScummVM team along with name of the game you tried\n";
+ md5Warning += "to add and its version/language/etc.:\n";
- printf(" SCUMM gameid '%s', file '%s', MD5 '%s'\n\n",
+ md5Warning += Common::String::format(" SCUMM gameid '%s', file '%s', MD5 '%s'\n\n",
res.game.gameid,
generateFilenameForDetection(res.fp.pattern, res.fp.genMethod).c_str(),
res.md5.c_str());
+
+ g_system->logMessage(LogMessageType::kWarning, md5Warning.c_str());
} else {
debug(1, "Using MD5 '%s'", res.md5.c_str());
}
diff --git a/engines/scumm/he/animation_he.cpp b/engines/scumm/he/animation_he.cpp
index 40e99c26a8..be17a3b305 100644
--- a/engines/scumm/he/animation_he.cpp
+++ b/engines/scumm/he/animation_he.cpp
@@ -40,7 +40,7 @@ MoviePlayer::MoviePlayer(ScummEngine_v90he *vm, Audio::Mixer *mixer) : _vm(vm) {
_video = new Video::BinkDecoder();
else
#endif
- _video = new Video::SmackerDecoder(mixer);
+ _video = new Video::SmackerDecoder();
_flags = 0;
_wizResNum = 0;
@@ -61,11 +61,16 @@ int MoviePlayer::load(const char *filename, int flags, int image) {
if (_video->isVideoLoaded())
_video->close();
+ // Ensure that Bink will use our PixelFormat
+ _video->setDefaultHighColorFormat(g_system->getScreenFormat());
+
if (!_video->loadFile(filename)) {
warning("Failed to load video file %s", filename);
return -1;
}
+ _video->start();
+
debug(1, "Playing video %s", filename);
if (flags & 2)
diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp
index ddafd964eb..f7add4eed2 100644
--- a/engines/sword1/animation.cpp
+++ b/engines/sword1/animation.cpp
@@ -37,6 +37,7 @@
#include "gui/message.h"
+#include "video/dxa_decoder.h"
#include "video/psx_decoder.h"
#include "video/smk_decoder.h"
@@ -96,9 +97,8 @@ static const char *const sequenceListPSX[20] = {
// Basic movie player
///////////////////////////////////////////////////////////////////////////////
-MoviePlayer::MoviePlayer(SwordEngine *vm, Text *textMan, ResMan *resMan, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Video::VideoDecoder *decoder, DecoderType decoderType)
- : _vm(vm), _textMan(textMan), _resMan(resMan), _snd(snd), _bgSoundHandle(bgSoundHandle), _system(system) {
- _bgSoundStream = NULL;
+MoviePlayer::MoviePlayer(SwordEngine *vm, Text *textMan, ResMan *resMan, OSystem *system, Video::VideoDecoder *decoder, DecoderType decoderType)
+ : _vm(vm), _textMan(textMan), _resMan(resMan), _system(system) {
_decoderType = decoderType;
_decoder = decoder;
@@ -107,7 +107,6 @@ MoviePlayer::MoviePlayer(SwordEngine *vm, Text *textMan, ResMan *resMan, Audio::
}
MoviePlayer::~MoviePlayer() {
- delete _bgSoundHandle;
delete _decoder;
}
@@ -116,16 +115,12 @@ MoviePlayer::~MoviePlayer() {
* @param id the id of the file
*/
bool MoviePlayer::load(uint32 id) {
- Common::File f;
Common::String filename;
- if (_decoderType == kVideoDecoderDXA)
- _bgSoundStream = Audio::SeekableAudioStream::openStreamFile(sequenceList[id]);
- else
- _bgSoundStream = NULL;
-
if (SwordEngine::_systemVars.showText) {
+ Common::File f;
filename = Common::String::format("%s.txt", sequenceList[id]);
+
if (f.open(filename)) {
Common::String line;
int lineNo = 0;
@@ -169,7 +164,6 @@ bool MoviePlayer::load(uint32 id) {
_movieTexts.push_back(MovieText(startFrame, endFrame, ptr, color));
lastEnd = endFrame;
}
- f.close();
}
}
@@ -189,6 +183,7 @@ bool MoviePlayer::load(uint32 id) {
// Need to load here in case it fails in which case we'd need
// to go back to paletted mode
if (_decoder->loadFile(filename)) {
+ _decoder->start();
return true;
} else {
initGraphics(g_system->getWidth(), g_system->getHeight(), true);
@@ -197,30 +192,27 @@ bool MoviePlayer::load(uint32 id) {
break;
}
- return _decoder->loadFile(filename.c_str());
-}
+ if (!_decoder->loadFile(filename))
+ return false;
-void MoviePlayer::play() {
- if (_bgSoundStream)
- _snd->playStream(Audio::Mixer::kSFXSoundType, _bgSoundHandle, _bgSoundStream);
+ // For DXA, also add the external sound file
+ if (_decoderType == kVideoDecoderDXA)
+ _decoder->addStreamFileTrack(sequenceList[id]);
- bool terminated = false;
+ _decoder->start();
+ return true;
+}
+void MoviePlayer::play() {
_textX = 0;
_textY = 0;
- terminated = !playVideo();
-
- if (terminated)
- _snd->stopHandle(*_bgSoundHandle);
+ playVideo();
_textMan->releaseText(2, false);
_movieTexts.clear();
- while (_snd->isSoundHandleActive(*_bgSoundHandle))
- _system->delayMillis(100);
-
// It's tempting to call _screen->fullRefresh() here to restore the old
// palette. However, that causes glitches with DXA movies, where the
// previous location would be momentarily drawn, before switching to
@@ -320,7 +312,7 @@ bool MoviePlayer::playVideo() {
}
if (_decoder->hasDirtyPalette()) {
- _decoder->setSystemPalette();
+ _vm->_system->getPaletteManager()->setPalette(_decoder->getPalette(), 0, 256);
if (!_movieTexts.empty()) {
// Look for the best color indexes to use to display the subtitles
@@ -506,24 +498,12 @@ void MoviePlayer::drawFramePSX(const Graphics::Surface *frame) {
scaledFrame.free();
}
-DXADecoderWithSound::DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle)
- : _mixer(mixer), _bgSoundHandle(bgSoundHandle) {
-}
-
-uint32 DXADecoderWithSound::getTime() const {
- if (_mixer->isSoundHandleActive(*_bgSoundHandle))
- return _mixer->getSoundElapsedTime(*_bgSoundHandle);
-
- return DXADecoder::getTime();
-}
-
///////////////////////////////////////////////////////////////////////////////
// Factory function for creating the appropriate cutscene player
///////////////////////////////////////////////////////////////////////////////
-MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *resMan, Audio::Mixer *snd, OSystem *system) {
+MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *resMan, OSystem *system) {
Common::String filename;
- Audio::SoundHandle *bgSoundHandle = new Audio::SoundHandle;
// For the PSX version, we'll try the PlayStation stream files
if (vm->isPsx()) {
@@ -534,7 +514,7 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *
#ifdef USE_RGB_COLOR
// All BS1 PSX videos run the videos at 2x speed
Video::VideoDecoder *psxDecoder = new Video::PSXStreamDecoder(Video::PSXStreamDecoder::kCD2x);
- return new MoviePlayer(vm, textMan, resMan, snd, system, bgSoundHandle, psxDecoder, kVideoDecoderPSX);
+ return new MoviePlayer(vm, textMan, resMan, system, psxDecoder, kVideoDecoderPSX);
#else
GUI::MessageDialog dialog(Common::String::format(_("PSX stream cutscene '%s' cannot be played in paletted mode"), filename.c_str()), _("OK"));
dialog.runModal();
@@ -546,20 +526,20 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *
filename = Common::String::format("%s.smk", sequenceList[id]);
if (Common::File::exists(filename)) {
- Video::SmackerDecoder *smkDecoder = new Video::SmackerDecoder(snd);
- return new MoviePlayer(vm, textMan, resMan, snd, system, bgSoundHandle, smkDecoder, kVideoDecoderSMK);
+ Video::SmackerDecoder *smkDecoder = new Video::SmackerDecoder();
+ return new MoviePlayer(vm, textMan, resMan, system, smkDecoder, kVideoDecoderSMK);
}
filename = Common::String::format("%s.dxa", sequenceList[id]);
if (Common::File::exists(filename)) {
#ifdef USE_ZLIB
- DXADecoderWithSound *dxaDecoder = new DXADecoderWithSound(snd, bgSoundHandle);
- return new MoviePlayer(vm, textMan, resMan, snd, system, bgSoundHandle, dxaDecoder, kVideoDecoderDXA);
+ Video::VideoDecoder *dxaDecoder = new Video::DXADecoder();
+ return new MoviePlayer(vm, textMan, resMan, system, dxaDecoder, kVideoDecoderDXA);
#else
GUI::MessageDialog dialog(_("DXA cutscenes found but ScummVM has been built without zlib support"), _("OK"));
dialog.runModal();
- return NULL;
+ return 0;
#endif
}
@@ -569,7 +549,7 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *
if (Common::File::exists(filename)) {
GUI::MessageDialog dialog(_("MPEG2 cutscenes are no longer supported"), _("OK"));
dialog.runModal();
- return NULL;
+ return 0;
}
if (!vm->isPsx() || scumm_stricmp(sequenceList[id], "enddemo") != 0) {
@@ -578,7 +558,7 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *
dialog.runModal();
}
- return NULL;
+ return 0;
}
} // End of namespace Sword1
diff --git a/engines/sword1/animation.h b/engines/sword1/animation.h
index c2ed86a1a3..d0c61f5eb3 100644
--- a/engines/sword1/animation.h
+++ b/engines/sword1/animation.h
@@ -23,16 +23,19 @@
#ifndef SWORD1_ANIMATION_H
#define SWORD1_ANIMATION_H
-#include "video/dxa_decoder.h"
-#include "video/video_decoder.h"
-
#include "common/list.h"
-#include "audio/audiostream.h"
-
#include "sword1/screen.h"
#include "sword1/sound.h"
+namespace Graphics {
+struct Surface;
+}
+
+namespace Video {
+class VideoDecoder;
+}
+
namespace Sword1 {
enum DecoderType {
@@ -55,21 +58,9 @@ public:
}
};
-class DXADecoderWithSound : public Video::DXADecoder {
-public:
- DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle);
- ~DXADecoderWithSound() {}
-
- uint32 getTime() const;
-
-private:
- Audio::Mixer *_mixer;
- Audio::SoundHandle *_bgSoundHandle;
-};
-
class MoviePlayer {
public:
- MoviePlayer(SwordEngine *vm, Text *textMan, ResMan *resMan, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Video::VideoDecoder *decoder, DecoderType decoderType);
+ MoviePlayer(SwordEngine *vm, Text *textMan, ResMan *resMan, OSystem *system, Video::VideoDecoder *decoder, DecoderType decoderType);
virtual ~MoviePlayer();
bool load(uint32 id);
void play();
@@ -78,7 +69,6 @@ protected:
SwordEngine *_vm;
Text *_textMan;
ResMan *_resMan;
- Audio::Mixer *_snd;
OSystem *_system;
Common::List<MovieText> _movieTexts;
int _textX, _textY, _textWidth, _textHeight;
@@ -88,8 +78,6 @@ protected:
DecoderType _decoderType;
Video::VideoDecoder *_decoder;
- Audio::SoundHandle *_bgSoundHandle;
- Audio::AudioStream *_bgSoundStream;
bool playVideo();
void performPostProcessing(byte *screen);
@@ -100,7 +88,7 @@ protected:
void convertColor(byte r, byte g, byte b, float &h, float &s, float &v);
};
-MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *resMan, Audio::Mixer *snd, OSystem *system);
+MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *resMan, OSystem *system);
} // End of namespace Sword1
diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp
index 8e04861edf..757d768780 100644
--- a/engines/sword1/logic.cpp
+++ b/engines/sword1/logic.cpp
@@ -959,7 +959,7 @@ int Logic::fnPlaySequence(Object *cpt, int32 id, int32 sequenceId, int32 d, int3
// meantime, we don't want any looping sound effects still playing.
_sound->quitScreen();
- MoviePlayer *player = makeMoviePlayer(sequenceId, _vm, _textMan, _resMan, _mixer, _system);
+ MoviePlayer *player = makeMoviePlayer(sequenceId, _vm, _textMan, _resMan, _system);
if (player) {
_screen->clearScreen();
if (player->load(sequenceId))
diff --git a/engines/sword2/animation.cpp b/engines/sword2/animation.cpp
index 5e3f8929e9..00260f789a 100644
--- a/engines/sword2/animation.cpp
+++ b/engines/sword2/animation.cpp
@@ -38,8 +38,11 @@
#include "sword2/screen.h"
#include "sword2/animation.h"
+#include "graphics/palette.h"
+
#include "gui/message.h"
+#include "video/dxa_decoder.h"
#include "video/smk_decoder.h"
#include "video/psx_decoder.h"
@@ -51,9 +54,8 @@ namespace Sword2 {
// Basic movie player
///////////////////////////////////////////////////////////////////////////////
-MoviePlayer::MoviePlayer(Sword2Engine *vm, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Video::VideoDecoder *decoder, DecoderType decoderType)
- : _vm(vm), _snd(snd), _bgSoundHandle(bgSoundHandle), _system(system) {
- _bgSoundStream = NULL;
+MoviePlayer::MoviePlayer(Sword2Engine *vm, OSystem *system, Video::VideoDecoder *decoder, DecoderType decoderType)
+ : _vm(vm), _system(system) {
_decoderType = decoderType;
_decoder = decoder;
@@ -62,7 +64,6 @@ MoviePlayer::MoviePlayer(Sword2Engine *vm, Audio::Mixer *snd, OSystem *system, A
}
MoviePlayer::~MoviePlayer() {
- delete _bgSoundHandle;
delete _decoder;
}
@@ -75,11 +76,6 @@ bool MoviePlayer::load(const char *name) {
if (_vm->shouldQuit())
return false;
- if (_decoderType == kVideoDecoderDXA)
- _bgSoundStream = Audio::SeekableAudioStream::openStreamFile(name);
- else
- _bgSoundStream = NULL;
-
_textSurface = NULL;
Common::String filename;
@@ -99,6 +95,7 @@ bool MoviePlayer::load(const char *name) {
// Need to load here in case it fails in which case we'd need
// to go back to paletted mode
if (_decoder->loadFile(filename)) {
+ _decoder->start();
return true;
} else {
initGraphics(640, 480, true);
@@ -106,7 +103,15 @@ bool MoviePlayer::load(const char *name) {
}
}
- return _decoder->loadFile(filename.c_str());
+ if (!_decoder->loadFile(filename))
+ return false;
+
+ // For DXA, also add the external sound file
+ if (_decoderType == kVideoDecoderDXA)
+ _decoder->addStreamFileTrack(name);
+
+ _decoder->start();
+ return true;
}
void MoviePlayer::play(MovieText *movieTexts, uint32 numMovieTexts, uint32 leadIn, uint32 leadOut) {
@@ -122,24 +127,15 @@ void MoviePlayer::play(MovieText *movieTexts, uint32 numMovieTexts, uint32 leadI
if (leadIn)
_vm->_sound->playMovieSound(leadIn, kLeadInSound);
- if (_bgSoundStream)
- _snd->playStream(Audio::Mixer::kSFXSoundType, _bgSoundHandle, _bgSoundStream);
-
- bool terminated = false;
-
- terminated = !playVideo();
+ bool terminated = !playVideo();
closeTextObject(_currentMovieText, NULL, 0);
if (terminated) {
- _snd->stopHandle(*_bgSoundHandle);
_vm->_sound->stopMovieSounds();
_vm->_sound->stopSpeech();
}
- while (_snd->isSoundHandleActive(*_bgSoundHandle))
- _system->delayMillis(100);
-
if (_decoderType == kVideoDecoderPSX) {
// Need to jump back to paletted color
initGraphics(640, 480, true);
@@ -336,7 +332,7 @@ bool MoviePlayer::playVideo() {
}
if (_decoder->hasDirtyPalette()) {
- _decoder->setSystemPalette();
+ _vm->_system->getPaletteManager()->setPalette(_decoder->getPalette(), 0, 256);
uint32 maxWeight = 0;
uint32 minWeight = 0xFFFFFFFF;
@@ -406,31 +402,19 @@ void MoviePlayer::drawFramePSX(const Graphics::Surface *frame) {
scaledFrame.free();
}
-DXADecoderWithSound::DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle)
- : _mixer(mixer), _bgSoundHandle(bgSoundHandle) {
-}
-
-uint32 DXADecoderWithSound::getTime() const {
- if (_mixer->isSoundHandleActive(*_bgSoundHandle))
- return _mixer->getSoundElapsedTime(*_bgSoundHandle);
-
- return DXADecoder::getTime();
-}
-
///////////////////////////////////////////////////////////////////////////////
// Factory function for creating the appropriate cutscene player
///////////////////////////////////////////////////////////////////////////////
-MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, Audio::Mixer *snd, OSystem *system, uint32 frameCount) {
+MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, OSystem *system, uint32 frameCount) {
Common::String filename;
- Audio::SoundHandle *bgSoundHandle = new Audio::SoundHandle;
filename = Common::String::format("%s.str", name);
if (Common::File::exists(filename)) {
#ifdef USE_RGB_COLOR
Video::VideoDecoder *psxDecoder = new Video::PSXStreamDecoder(Video::PSXStreamDecoder::kCD2x, frameCount);
- return new MoviePlayer(vm, snd, system, bgSoundHandle, psxDecoder, kVideoDecoderPSX);
+ return new MoviePlayer(vm, system, psxDecoder, kVideoDecoderPSX);
#else
GUI::MessageDialog dialog(_("PSX cutscenes found but ScummVM has been built without RGB color support"), _("OK"));
dialog.runModal();
@@ -441,16 +425,16 @@ MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, Audio::Mixer *s
filename = Common::String::format("%s.smk", name);
if (Common::File::exists(filename)) {
- Video::SmackerDecoder *smkDecoder = new Video::SmackerDecoder(snd);
- return new MoviePlayer(vm, snd, system, bgSoundHandle, smkDecoder, kVideoDecoderSMK);
+ Video::SmackerDecoder *smkDecoder = new Video::SmackerDecoder();
+ return new MoviePlayer(vm, system, smkDecoder, kVideoDecoderSMK);
}
filename = Common::String::format("%s.dxa", name);
if (Common::File::exists(filename)) {
#ifdef USE_ZLIB
- DXADecoderWithSound *dxaDecoder = new DXADecoderWithSound(snd, bgSoundHandle);
- return new MoviePlayer(vm, snd, system, bgSoundHandle, dxaDecoder, kVideoDecoderDXA);
+ Video::DXADecoder *dxaDecoder = new Video::DXADecoder();
+ return new MoviePlayer(vm, system, dxaDecoder, kVideoDecoderDXA);
#else
GUI::MessageDialog dialog(_("DXA cutscenes found but ScummVM has been built without zlib support"), _("OK"));
dialog.runModal();
diff --git a/engines/sword2/animation.h b/engines/sword2/animation.h
index 3d5c42b7f7..b2a243b2ca 100644
--- a/engines/sword2/animation.h
+++ b/engines/sword2/animation.h
@@ -25,12 +25,16 @@
#ifndef SWORD2_ANIMATION_H
#define SWORD2_ANIMATION_H
-#include "video/dxa_decoder.h"
-#include "video/video_decoder.h"
-#include "audio/mixer.h"
-
#include "sword2/screen.h"
+namespace Graphics {
+struct Surface;
+}
+
+namespace Video {
+class VideoDecoder;
+}
+
namespace Sword2 {
enum DecoderType {
@@ -55,20 +59,9 @@ struct MovieText {
}
};
-class DXADecoderWithSound : public Video::DXADecoder {
-public:
- DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle);
- ~DXADecoderWithSound() {}
-
- uint32 getTime() const;
-private:
- Audio::Mixer *_mixer;
- Audio::SoundHandle *_bgSoundHandle;
-};
-
class MoviePlayer {
public:
- MoviePlayer(Sword2Engine *vm, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Video::VideoDecoder *decoder, DecoderType decoderType);
+ MoviePlayer(Sword2Engine *vm, OSystem *system, Video::VideoDecoder *decoder, DecoderType decoderType);
virtual ~MoviePlayer();
bool load(const char *name);
@@ -76,7 +69,6 @@ public:
protected:
Sword2Engine *_vm;
- Audio::Mixer *_snd;
OSystem *_system;
MovieText *_movieTexts;
uint32 _numMovieTexts;
@@ -87,8 +79,6 @@ protected:
DecoderType _decoderType;
Video::VideoDecoder *_decoder;
- Audio::SoundHandle *_bgSoundHandle;
- Audio::AudioStream *_bgSoundStream;
uint32 _leadOut;
int _leadOutFrame;
@@ -105,7 +95,7 @@ protected:
uint32 getWhiteColor();
};
-MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, Audio::Mixer *snd, OSystem *system, uint32 frameCount);
+MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, OSystem *system, uint32 frameCount);
} // End of namespace Sword2
diff --git a/engines/sword2/function.cpp b/engines/sword2/function.cpp
index 836b252d6c..07fcaa094b 100644
--- a/engines/sword2/function.cpp
+++ b/engines/sword2/function.cpp
@@ -2139,7 +2139,7 @@ int32 Logic::fnPlaySequence(int32 *params) {
uint32 frameCount = Sword2Engine::isPsx() ? params[1] : 0;
- _moviePlayer = makeMoviePlayer(filename, _vm, _vm->_mixer, _vm->_system, frameCount);
+ _moviePlayer = makeMoviePlayer(filename, _vm, _vm->_system, frameCount);
if (_moviePlayer && _moviePlayer->load(filename)) {
_moviePlayer->play(_sequenceTextList, _sequenceTextLines, _smackerLeadIn, _smackerLeadOut);
diff --git a/engines/sword25/fmv/movieplayer.cpp b/engines/sword25/fmv/movieplayer.cpp
index 9ee13b4b6d..a95532ec65 100644
--- a/engines/sword25/fmv/movieplayer.cpp
+++ b/engines/sword25/fmv/movieplayer.cpp
@@ -61,6 +61,7 @@ bool MoviePlayer::loadMovie(const Common::String &filename, uint z) {
// Get the file and load it into the decoder
Common::SeekableReadStream *in = Kernel::getInstance()->getPackage()->getStream(filename);
_decoder.loadStream(in);
+ _decoder.start();
GraphicEngine *pGfx = Kernel::getInstance()->getGfx();
diff --git a/engines/sword25/fmv/movieplayer.h b/engines/sword25/fmv/movieplayer.h
index 1d256e56ba..2f5614b505 100644
--- a/engines/sword25/fmv/movieplayer.h
+++ b/engines/sword25/fmv/movieplayer.h
@@ -39,7 +39,7 @@
#include "sword25/gfx/bitmap.h"
#ifdef USE_THEORADEC
-#include "sword25/fmv/theora_decoder.h"
+#include "video/theora_decoder.h"
#endif
#define THEORA_INDIRECT_RENDERING
@@ -141,7 +141,7 @@ private:
#ifdef USE_THEORADEC
- TheoraDecoder _decoder;
+ Video::TheoraDecoder _decoder;
Graphics::Surface *_backSurface;
int _outX, _outY;
diff --git a/engines/sword25/fmv/theora_decoder.cpp b/engines/sword25/fmv/theora_decoder.cpp
deleted file mode 100644
index d38f5a26cf..0000000000
--- a/engines/sword25/fmv/theora_decoder.cpp
+++ /dev/null
@@ -1,565 +0,0 @@
-/* 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.
- *
- */
-
-/*
- * Source is based on the player example from libvorbis package,
- * available at: http://svn.xiph.org/trunk/theora/examples/player_example.c
- *
- * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE.
- * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS
- * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE
- * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.
- *
- * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009
- * by the Xiph.Org Foundation and contributors http://www.xiph.org/
- *
- */
-
-#include "sword25/fmv/theora_decoder.h"
-
-#ifdef USE_THEORADEC
-#include "common/system.h"
-#include "common/textconsole.h"
-#include "common/util.h"
-#include "graphics/yuv_to_rgb.h"
-#include "audio/decoders/raw.h"
-#include "sword25/kernel/common.h"
-
-namespace Sword25 {
-
-#define AUDIOFD_FRAGSIZE 10240
-
-static double rint(double v) {
- return floor(v + 0.5);
-}
-
-TheoraDecoder::TheoraDecoder(Audio::Mixer::SoundType soundType) {
- _fileStream = 0;
-
- _theoraPacket = 0;
- _vorbisPacket = 0;
- _theoraDecode = 0;
- _theoraSetup = 0;
- _nextFrameStartTime = 0.0;
-
- _soundType = soundType;
- _audStream = 0;
- _audHandle = new Audio::SoundHandle();
-
- ogg_sync_init(&_oggSync);
-
- _curFrame = -1;
- _audiobuf = (ogg_int16_t *)malloc(AUDIOFD_FRAGSIZE * sizeof(ogg_int16_t));
-
- reset();
-}
-
-TheoraDecoder::~TheoraDecoder() {
- close();
- delete _fileStream;
- delete _audHandle;
- free(_audiobuf);
-}
-
-void TheoraDecoder::queuePage(ogg_page *page) {
- if (_theoraPacket)
- ogg_stream_pagein(&_theoraOut, page);
-
- if (_vorbisPacket)
- ogg_stream_pagein(&_vorbisOut, page);
-}
-
-int TheoraDecoder::bufferData() {
- char *buffer = ogg_sync_buffer(&_oggSync, 4096);
- int bytes = _fileStream->read(buffer, 4096);
-
- ogg_sync_wrote(&_oggSync, bytes);
-
- return bytes;
-}
-
-bool TheoraDecoder::loadStream(Common::SeekableReadStream *stream) {
- close();
-
- _endOfAudio = false;
- _endOfVideo = false;
- _fileStream = stream;
-
- // start up Ogg stream synchronization layer
- ogg_sync_init(&_oggSync);
-
- // init supporting Vorbis structures needed in header parsing
- vorbis_info_init(&_vorbisInfo);
- vorbis_comment_init(&_vorbisComment);
-
- // init supporting Theora structures needed in header parsing
- th_comment_init(&_theoraComment);
- th_info_init(&_theoraInfo);
-
- // Ogg file open; parse the headers
- // Only interested in Vorbis/Theora streams
- bool foundHeader = false;
- while (!foundHeader) {
- int ret = bufferData();
-
- if (ret == 0)
- break;
-
- while (ogg_sync_pageout(&_oggSync, &_oggPage) > 0) {
- ogg_stream_state test;
-
- // is this a mandated initial header? If not, stop parsing
- if (!ogg_page_bos(&_oggPage)) {
- // don't leak the page; get it into the appropriate stream
- queuePage(&_oggPage);
- foundHeader = true;
- break;
- }
-
- ogg_stream_init(&test, ogg_page_serialno(&_oggPage));
- ogg_stream_pagein(&test, &_oggPage);
- ogg_stream_packetout(&test, &_oggPacket);
-
- // identify the codec: try theora
- if (!_theoraPacket && th_decode_headerin(&_theoraInfo, &_theoraComment, &_theoraSetup, &_oggPacket) >= 0) {
- // it is theora
- memcpy(&_theoraOut, &test, sizeof(test));
- _theoraPacket = 1;
- } else if (!_vorbisPacket && vorbis_synthesis_headerin(&_vorbisInfo, &_vorbisComment, &_oggPacket) >= 0) {
- // it is vorbis
- memcpy(&_vorbisOut, &test, sizeof(test));
- _vorbisPacket = 1;
- } else {
- // whatever it is, we don't care about it
- ogg_stream_clear(&test);
- }
- }
- // fall through to non-bos page parsing
- }
-
- // we're expecting more header packets.
- while ((_theoraPacket && _theoraPacket < 3) || (_vorbisPacket && _vorbisPacket < 3)) {
- int ret;
-
- // look for further theora headers
- while (_theoraPacket && (_theoraPacket < 3) && (ret = ogg_stream_packetout(&_theoraOut, &_oggPacket))) {
- if (ret < 0)
- error("Error parsing Theora stream headers; corrupt stream?");
-
- if (!th_decode_headerin(&_theoraInfo, &_theoraComment, &_theoraSetup, &_oggPacket))
- error("Error parsing Theora stream headers; corrupt stream?");
-
- _theoraPacket++;
- }
-
- // look for more vorbis header packets
- while (_vorbisPacket && (_vorbisPacket < 3) && (ret = ogg_stream_packetout(&_vorbisOut, &_oggPacket))) {
- if (ret < 0)
- error("Error parsing Vorbis stream headers; corrupt stream?");
-
- if (vorbis_synthesis_headerin(&_vorbisInfo, &_vorbisComment, &_oggPacket))
- error("Error parsing Vorbis stream headers; corrupt stream?");
-
- _vorbisPacket++;
-
- if (_vorbisPacket == 3)
- break;
- }
-
- // The header pages/packets will arrive before anything else we
- // care about, or the stream is not obeying spec
-
- if (ogg_sync_pageout(&_oggSync, &_oggPage) > 0) {
- queuePage(&_oggPage); // demux into the appropriate stream
- } else {
- ret = bufferData(); // someone needs more data
-
- if (ret == 0)
- error("End of file while searching for codec headers.");
- }
- }
-
- // and now we have it all. initialize decoders
- if (_theoraPacket) {
- _theoraDecode = th_decode_alloc(&_theoraInfo, _theoraSetup);
- debugN(1, "Ogg logical stream %lx is Theora %dx%d %.02f fps",
- _theoraOut.serialno, _theoraInfo.pic_width, _theoraInfo.pic_height,
- (double)_theoraInfo.fps_numerator / _theoraInfo.fps_denominator);
-
- switch (_theoraInfo.pixel_fmt) {
- case TH_PF_420:
- debug(1, " 4:2:0 video");
- break;
- case TH_PF_422:
- debug(1, " 4:2:2 video");
- break;
- case TH_PF_444:
- debug(1, " 4:4:4 video");
- break;
- case TH_PF_RSVD:
- default:
- debug(1, " video\n (UNKNOWN Chroma sampling!)");
- break;
- }
-
- if (_theoraInfo.pic_width != _theoraInfo.frame_width || _theoraInfo.pic_height != _theoraInfo.frame_height)
- debug(1, " Frame content is %dx%d with offset (%d,%d).",
- _theoraInfo.frame_width, _theoraInfo.frame_height, _theoraInfo.pic_x, _theoraInfo.pic_y);
-
- switch (_theoraInfo.colorspace){
- case TH_CS_UNSPECIFIED:
- /* nothing to report */
- break;
- case TH_CS_ITU_REC_470M:
- debug(1, " encoder specified ITU Rec 470M (NTSC) color.");
- break;
- case TH_CS_ITU_REC_470BG:
- debug(1, " encoder specified ITU Rec 470BG (PAL) color.");
- break;
- default:
- debug(1, "warning: encoder specified unknown colorspace (%d).", _theoraInfo.colorspace);
- break;
- }
-
- debug(1, "Encoded by %s", _theoraComment.vendor);
- if (_theoraComment.comments) {
- debug(1, "theora comment header:");
- for (int i = 0; i < _theoraComment.comments; i++) {
- if (_theoraComment.user_comments[i]) {
- int len = _theoraComment.comment_lengths[i];
- char *value = (char *)malloc(len + 1);
- if (value) {
- memcpy(value, _theoraComment.user_comments[i], len);
- value[len] = '\0';
- debug(1, "\t%s", value);
- free(value);
- }
- }
- }
- }
-
- th_decode_ctl(_theoraDecode, TH_DECCTL_GET_PPLEVEL_MAX, &_ppLevelMax, sizeof(_ppLevelMax));
- _ppLevel = _ppLevelMax;
- th_decode_ctl(_theoraDecode, TH_DECCTL_SET_PPLEVEL, &_ppLevel, sizeof(_ppLevel));
- _ppInc = 0;
- } else {
- // tear down the partial theora setup
- th_info_clear(&_theoraInfo);
- th_comment_clear(&_theoraComment);
- }
-
- th_setup_free(_theoraSetup);
- _theoraSetup = 0;
-
- if (_vorbisPacket) {
- vorbis_synthesis_init(&_vorbisDSP, &_vorbisInfo);
- vorbis_block_init(&_vorbisDSP, &_vorbisBlock);
- debug(3, "Ogg logical stream %lx is Vorbis %d channel %ld Hz audio.",
- _vorbisOut.serialno, _vorbisInfo.channels, _vorbisInfo.rate);
-
- _audStream = Audio::makeQueuingAudioStream(_vorbisInfo.rate, _vorbisInfo.channels);
-
- // Get enough audio data to start us off
- while (_audStream->numQueuedStreams() == 0) {
- // Queue more data
- bufferData();
- while (ogg_sync_pageout(&_oggSync, &_oggPage) > 0)
- queuePage(&_oggPage);
-
- queueAudio();
- }
-
- if (_audStream)
- g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, _audHandle, _audStream, -1, getVolume(), getBalance());
- } else {
- // tear down the partial vorbis setup
- vorbis_info_clear(&_vorbisInfo);
- vorbis_comment_clear(&_vorbisComment);
- _endOfAudio = true;
- }
-
- _surface.create(_theoraInfo.frame_width, _theoraInfo.frame_height, g_system->getScreenFormat());
-
- // Set up a display surface
- _displaySurface.pixels = _surface.getBasePtr(_theoraInfo.pic_x, _theoraInfo.pic_y);
- _displaySurface.w = _theoraInfo.pic_width;
- _displaySurface.h = _theoraInfo.pic_height;
- _displaySurface.format = _surface.format;
- _displaySurface.pitch = _surface.pitch;
-
- // Set the frame rate
- _frameRate = Common::Rational(_theoraInfo.fps_numerator, _theoraInfo.fps_denominator);
-
- return true;
-}
-
-void TheoraDecoder::close() {
- if (_vorbisPacket) {
- ogg_stream_clear(&_vorbisOut);
- vorbis_block_clear(&_vorbisBlock);
- vorbis_dsp_clear(&_vorbisDSP);
- vorbis_comment_clear(&_vorbisComment);
- vorbis_info_clear(&_vorbisInfo);
-
- g_system->getMixer()->stopHandle(*_audHandle);
-
- _audStream = 0;
- _vorbisPacket = false;
- }
- if (_theoraPacket) {
- ogg_stream_clear(&_theoraOut);
- th_decode_free(_theoraDecode);
- th_comment_clear(&_theoraComment);
- th_info_clear(&_theoraInfo);
- _theoraDecode = 0;
- _theoraPacket = false;
- }
-
- if (!_fileStream)
- return;
-
- ogg_sync_clear(&_oggSync);
-
- delete _fileStream;
- _fileStream = 0;
-
- _surface.free();
- _displaySurface.pixels = 0;
- _displaySurface.free();
-
- reset();
-}
-
-const Graphics::Surface *TheoraDecoder::decodeNextFrame() {
- // First, let's get our frame
- while (_theoraPacket) {
- // theora is one in, one out...
- if (ogg_stream_packetout(&_theoraOut, &_oggPacket) > 0) {
-
- if (_ppInc) {
- _ppLevel += _ppInc;
- th_decode_ctl(_theoraDecode, TH_DECCTL_SET_PPLEVEL, &_ppLevel, sizeof(_ppLevel));
- _ppInc = 0;
- }
-
- if (th_decode_packetin(_theoraDecode, &_oggPacket, NULL) == 0) {
- _curFrame++;
-
- // Convert YUV data to RGB data
- th_ycbcr_buffer yuv;
- th_decode_ycbcr_out(_theoraDecode, yuv);
- translateYUVtoRGBA(yuv);
-
- if (_curFrame == 0)
- _startTime = g_system->getMillis();
-
- double time = th_granule_time(_theoraDecode, _oggPacket.granulepos);
-
- // We need to calculate when the next frame should be shown
- // This is all in floating point because that's what the Ogg code gives us
- // Ogg is a lossy container format, so it doesn't always list the time to the
- // next frame. In such cases, we need to calculate it ourselves.
- if (time == -1.0)
- _nextFrameStartTime += _frameRate.getInverse().toDouble();
- else
- _nextFrameStartTime = time;
-
- // break out
- break;
- }
- } else {
- // If we can't get any more frames, we're done.
- if (_theoraOut.e_o_s || _fileStream->eos()) {
- _endOfVideo = true;
- break;
- }
-
- // Queue more data
- bufferData();
- while (ogg_sync_pageout(&_oggSync, &_oggPage) > 0)
- queuePage(&_oggPage);
- }
-
- // Update audio if we can
- queueAudio();
- }
-
- // Force at least some audio to be buffered
- // TODO: 5 is very arbitrary. We probably should do something like QuickTime does.
- while (!_endOfAudio && _audStream->numQueuedStreams() < 5) {
- bufferData();
- while (ogg_sync_pageout(&_oggSync, &_oggPage) > 0)
- queuePage(&_oggPage);
-
- bool queuedAudio = queueAudio();
- if ((_vorbisOut.e_o_s || _fileStream->eos()) && !queuedAudio) {
- _endOfAudio = true;
- break;
- }
- }
-
- return &_displaySurface;
-}
-
-bool TheoraDecoder::queueAudio() {
- if (!_audStream)
- return false;
-
- // An audio buffer should have been allocated (either in the constructor or after queuing the current buffer)
- if (!_audiobuf) {
- warning("[TheoraDecoder::queueAudio] Invalid audio buffer");
- return false;
- }
-
- bool queuedAudio = false;
-
- for (;;) {
- float **pcm;
-
- // if there's pending, decoded audio, grab it
- int ret = vorbis_synthesis_pcmout(&_vorbisDSP, &pcm);
- if (ret > 0) {
- int count = _audiobufFill / 2;
- int maxsamples = ((AUDIOFD_FRAGSIZE - _audiobufFill) / _vorbisInfo.channels) >> 1;
- int i;
- for (i = 0; i < ret && i < maxsamples; i++)
- for (int j = 0; j < _vorbisInfo.channels; j++) {
- int val = CLIP((int)rint(pcm[j][i] * 32767.f), -32768, 32767);
- _audiobuf[count++] = val;
- }
-
- vorbis_synthesis_read(&_vorbisDSP, i);
- _audiobufFill += (i * _vorbisInfo.channels) << 1;
-
- if (_audiobufFill == AUDIOFD_FRAGSIZE) {
- byte flags = Audio::FLAG_16BITS | Audio::FLAG_STEREO;
-#ifdef SCUMM_LITTLE_ENDIAN
- flags |= Audio::FLAG_LITTLE_ENDIAN;
-#endif
- _audStream->queueBuffer((byte *)_audiobuf, AUDIOFD_FRAGSIZE, DisposeAfterUse::NO, flags);
-
- // The audio mixer is now responsible for the old audio buffer.
- // We need to create a new one.
- _audiobuf = (ogg_int16_t *)malloc(AUDIOFD_FRAGSIZE * sizeof(ogg_int16_t));
- if (!_audiobuf) {
- warning("[TheoraDecoder::queueAudio] Cannot allocate memory for audio buffer");
- return false;
- }
-
- _audiobufFill = 0;
- queuedAudio = true;
- }
- } else {
- // no pending audio; is there a pending packet to decode?
- if (ogg_stream_packetout(&_vorbisOut, &_oggPacket) > 0) {
- if (vorbis_synthesis(&_vorbisBlock, &_oggPacket) == 0) // test for success!
- vorbis_synthesis_blockin(&_vorbisDSP, &_vorbisBlock);
- } else // we've buffered all we have, break out for now
- return queuedAudio;
- }
- }
-
- // Unreachable
- return false;
-}
-
-void TheoraDecoder::reset() {
- VideoDecoder::reset();
-
- // FIXME: This does a rewind() instead of a reset()!
-
- if (_fileStream)
- _fileStream->seek(0);
-
- _audiobufFill = 0;
- _audiobufReady = false;
-
- _curFrame = -1;
-
- _theoraPacket = 0;
- _vorbisPacket = 0;
-}
-
-bool TheoraDecoder::endOfVideo() const {
- return !isVideoLoaded() || (_endOfVideo && (!_audStream || (_audStream->endOfData() && _endOfAudio)));
-}
-
-uint32 TheoraDecoder::getTimeToNextFrame() const {
- if (endOfVideo() || _curFrame < 0)
- return 0;
-
- uint32 elapsedTime = getTime();
- uint32 nextFrameStartTime = (uint32)(_nextFrameStartTime * 1000);
-
- if (nextFrameStartTime <= elapsedTime)
- return 0;
-
- return nextFrameStartTime - elapsedTime;
-}
-
-uint32 TheoraDecoder::getTime() const {
- if (_audStream)
- return g_system->getMixer()->getSoundElapsedTime(*_audHandle);
-
- return VideoDecoder::getTime();
-}
-
-void TheoraDecoder::pauseVideoIntern(bool pause) {
- if (_audStream)
- g_system->getMixer()->pauseHandle(*_audHandle, pause);
-}
-
-enum TheoraYUVBuffers {
- kBufferY = 0,
- kBufferU = 1,
- kBufferV = 2
-};
-
-void TheoraDecoder::translateYUVtoRGBA(th_ycbcr_buffer &YUVBuffer) {
- // Width and height of all buffers have to be divisible by 2.
- assert((YUVBuffer[kBufferY].width & 1) == 0);
- assert((YUVBuffer[kBufferY].height & 1) == 0);
- assert((YUVBuffer[kBufferU].width & 1) == 0);
- assert((YUVBuffer[kBufferV].width & 1) == 0);
-
- // UV images have to have a quarter of the Y image resolution
- assert(YUVBuffer[kBufferU].width == YUVBuffer[kBufferY].width >> 1);
- assert(YUVBuffer[kBufferV].width == YUVBuffer[kBufferY].width >> 1);
- assert(YUVBuffer[kBufferU].height == YUVBuffer[kBufferY].height >> 1);
- assert(YUVBuffer[kBufferV].height == YUVBuffer[kBufferY].height >> 1);
-
- Graphics::convertYUV420ToRGB(&_surface, YUVBuffer[kBufferY].data, YUVBuffer[kBufferU].data, YUVBuffer[kBufferV].data, YUVBuffer[kBufferY].width, YUVBuffer[kBufferY].height, YUVBuffer[kBufferY].stride, YUVBuffer[kBufferU].stride);
-}
-
-void TheoraDecoder::updateVolume() {
- if (g_system->getMixer()->isSoundHandleActive(*_audHandle))
- g_system->getMixer()->setChannelVolume(*_audHandle, getVolume());
-}
-
-void TheoraDecoder::updateBalance() {
- if (g_system->getMixer()->isSoundHandleActive(*_audHandle))
- g_system->getMixer()->setChannelBalance(*_audHandle, getBalance());
-}
-
-} // End of namespace Sword25
-
-#endif
diff --git a/engines/sword25/fmv/theora_decoder.h b/engines/sword25/fmv/theora_decoder.h
deleted file mode 100644
index 739040024f..0000000000
--- a/engines/sword25/fmv/theora_decoder.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/* 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.
- *
- */
-
-#ifndef SWORD25_THEORADECODER_H
-#define SWORD25_THEORADECODER_H
-
-#include "common/scummsys.h" // for USE_THEORADEC
-
-#ifdef USE_THEORADEC
-
-#include "common/rational.h"
-#include "video/video_decoder.h"
-#include "audio/audiostream.h"
-#include "audio/mixer.h"
-#include "graphics/pixelformat.h"
-#include "graphics/surface.h"
-
-#include <theora/theoradec.h>
-#include <vorbis/codec.h>
-
-namespace Common {
-class SeekableReadStream;
-}
-
-namespace Sword25 {
-
-/**
- *
- * Decoder for Theora videos.
- * Video decoder used in engines:
- * - sword25
- */
-class TheoraDecoder : public Video::VideoDecoder {
-public:
- TheoraDecoder(Audio::Mixer::SoundType soundType = Audio::Mixer::kMusicSoundType);
- virtual ~TheoraDecoder();
-
- /**
- * Load a video file
- * @param stream the stream to load
- */
- bool loadStream(Common::SeekableReadStream *stream);
- void close();
- void reset();
-
- /**
- * Decode the next frame and return the frame's surface
- * @note the return surface should *not* be freed
- * @note this may return 0, in which case the last frame should be kept on screen
- */
- const Graphics::Surface *decodeNextFrame();
-
- bool isVideoLoaded() const { return _fileStream != 0; }
- uint16 getWidth() const { return _displaySurface.w; }
- uint16 getHeight() const { return _displaySurface.h; }
-
- uint32 getFrameCount() const {
- // It is not possible to get frame count easily
- // I.e. seeking is required
- assert(0);
- return 0;
- }
-
- Graphics::PixelFormat getPixelFormat() const { return _displaySurface.format; }
- uint32 getTime() const;
- uint32 getTimeToNextFrame() const;
-
- bool endOfVideo() const;
-
-protected:
- // VideoDecoder API
- void updateVolume();
- void updateBalance();
- void pauseVideoIntern(bool pause);
-
-private:
- void queuePage(ogg_page *page);
- bool queueAudio();
- int bufferData();
- void translateYUVtoRGBA(th_ycbcr_buffer &YUVBuffer);
-
- Common::SeekableReadStream *_fileStream;
- Graphics::Surface _surface;
- Graphics::Surface _displaySurface;
- Common::Rational _frameRate;
- double _nextFrameStartTime;
- bool _endOfVideo;
- bool _endOfAudio;
-
- Audio::Mixer::SoundType _soundType;
- Audio::SoundHandle *_audHandle;
- Audio::QueuingAudioStream *_audStream;
-
- ogg_sync_state _oggSync;
- ogg_page _oggPage;
- ogg_packet _oggPacket;
- ogg_stream_state _vorbisOut;
- ogg_stream_state _theoraOut;
- th_info _theoraInfo;
- th_comment _theoraComment;
- th_dec_ctx *_theoraDecode;
- th_setup_info *_theoraSetup;
- vorbis_info _vorbisInfo;
- vorbis_dsp_state _vorbisDSP;
- vorbis_block _vorbisBlock;
- vorbis_comment _vorbisComment;
-
- int _theoraPacket;
- int _vorbisPacket;
-
- int _ppLevelMax;
- int _ppLevel;
- int _ppInc;
-
- // single audio fragment audio buffering
- int _audiobufFill;
- bool _audiobufReady;
- ogg_int16_t *_audiobuf;
-};
-
-} // End of namespace Sword25
-
-#endif
-
-#endif
diff --git a/engines/sword25/module.mk b/engines/sword25/module.mk
index 302120c500..e24a221244 100644
--- a/engines/sword25/module.mk
+++ b/engines/sword25/module.mk
@@ -85,11 +85,6 @@ MODULE_OBJS := \
util/pluto/pluto.o \
util/pluto/plzio.o
-ifdef USE_THEORADEC
-MODULE_OBJS += \
- fmv/theora_decoder.o
-endif
-
# This module can be built as a plugin
ifeq ($(ENABLE_SWORD25), DYNAMIC_PLUGIN)
PLUGIN := 1
diff --git a/engines/sword25/sfx/soundengine.cpp b/engines/sword25/sfx/soundengine.cpp
index 78b2db19eb..69fae3dc4e 100644
--- a/engines/sword25/sfx/soundengine.cpp
+++ b/engines/sword25/sfx/soundengine.cpp
@@ -239,16 +239,20 @@ void SoundEngine::setSoundVolume(uint handle, float volume) {
debugC(1, kDebugSound, "SoundEngine::setSoundVolume(%d, %f)", handle, volume);
SndHandle* sndHandle = findHandle(handle);
- if (sndHandle != NULL)
+ if (sndHandle != NULL) {
+ sndHandle->volume = volume;
_mixer->setChannelVolume(sndHandle->handle, (byte)(volume * 255));
+ }
}
void SoundEngine::setSoundPanning(uint handle, float pan) {
debugC(1, kDebugSound, "SoundEngine::setSoundPanning(%d, %f)", handle, pan);
SndHandle* sndHandle = findHandle(handle);
- if (sndHandle != NULL)
+ if (sndHandle != NULL) {
+ sndHandle->pan = pan;
_mixer->setChannelBalance(sndHandle->handle, (int8)(pan * 127));
+ }
}
void SoundEngine::pauseSound(uint handle) {
@@ -324,13 +328,16 @@ bool SoundEngine::canLoadResource(const Common::String &fileName) {
return fname.hasSuffix(".ogg");
}
-
- bool SoundEngine::persist(OutputPersistenceBlock &writer) {
+bool SoundEngine::persist(OutputPersistenceBlock &writer) {
writer.write(_maxHandleId);
for (uint i = 0; i < SOUND_HANDLES; i++) {
writer.write(_handles[i].id);
+ // Don't restart sounds which already finished playing.
+ if (_handles[i].type != kFreeHandle && !_mixer->isSoundHandleActive(_handles[i].handle))
+ _handles[i].type = kFreeHandle;
+
writer.writeString(_handles[i].fileName);
writer.write((int)_handles[i].sndType);
writer.write(_handles[i].volume);
@@ -374,7 +381,8 @@ bool SoundEngine::unpersist(InputPersistenceBlock &reader) {
reader.read(layer);
if (reader.isGood()) {
- playSoundEx(fileName, (SOUND_TYPES)sndType, volume, pan, loop, loopStart, loopEnd, layer, i);
+ if (sndType != kFreeHandle)
+ playSoundEx(fileName, (SOUND_TYPES)sndType, volume, pan, loop, loopStart, loopEnd, layer, i);
} else
return false;
}
diff --git a/engines/sword25/util/pluto/pluto.cpp b/engines/sword25/util/pluto/pluto.cpp
index d645e5ed2a..b7f5e30340 100644
--- a/engines/sword25/util/pluto/pluto.cpp
+++ b/engines/sword25/util/pluto/pluto.cpp
@@ -895,10 +895,10 @@ static void unpersistnumber(UnpersistInfo *upi)
static void unpersiststring(UnpersistInfo *upi)
{
/* perms reftbl sptbl ref */
- int length;
+ size_t length;
char* string;
lua_checkstack(upi->L, 1);
- verify(LIF(Z,read)(&upi->zio, &length, sizeof(int)) == 0);
+ verify(LIF(Z,read)(&upi->zio, &length, sizeof(size_t)) == 0);
string = pdep_newvector(upi->L, length, char);
verify(LIF(Z,read)(&upi->zio, string, length) == 0);
lua_pushlstring(upi->L, string, length);
diff --git a/engines/toon/movie.cpp b/engines/toon/movie.cpp
index 93e41adf57..8c85e20f7c 100644
--- a/engines/toon/movie.cpp
+++ b/engines/toon/movie.cpp
@@ -25,6 +25,7 @@
#include "common/keyboard.h"
#include "common/stream.h"
#include "common/system.h"
+#include "graphics/palette.h"
#include "graphics/surface.h"
#include "toon/audio.h"
@@ -33,6 +34,10 @@
namespace Toon {
+ToonstruckSmackerDecoder::ToonstruckSmackerDecoder() : Video::SmackerDecoder() {
+ _lowRes = false;
+}
+
void ToonstruckSmackerDecoder::handleAudioTrack(byte track, uint32 chunkSize, uint32 unpackedSize) {
debugC(6, kDebugMovie, "handleAudioTrack(%d, %d, %d)", track, chunkSize, unpackedSize);
@@ -40,33 +45,21 @@ void ToonstruckSmackerDecoder::handleAudioTrack(byte track, uint32 chunkSize, ui
/* uint16 width = */ _fileStream->readUint16LE();
uint16 height = _fileStream->readUint16LE();
_lowRes = (height == getHeight() / 2);
- } else
+ } else {
Video::SmackerDecoder::handleAudioTrack(track, chunkSize, unpackedSize);
+ }
}
-bool ToonstruckSmackerDecoder::loadFile(const Common::String &filename) {
- debugC(1, kDebugMovie, "loadFile(%s)", filename.c_str());
+bool ToonstruckSmackerDecoder::loadStream(Common::SeekableReadStream *stream) {
+ if (!Video::SmackerDecoder::loadStream(stream))
+ return false;
_lowRes = false;
-
- if (Video::SmackerDecoder::loadFile(filename)) {
- if (_surface->h == 200) {
- if (_surface) {
- _surface->free();
- delete _surface;
- }
- _surface = new Graphics::Surface();
- _surface->create(640, 400, Graphics::PixelFormat::createFormatCLUT8());
- _header.flags = 4;
- }
-
- return true;
- }
- return false;
+ return true;
}
-ToonstruckSmackerDecoder::ToonstruckSmackerDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType) : Video::SmackerDecoder(mixer, soundType) {
- _lowRes = false;
+Video::SmackerDecoder::SmackerVideoTrack *ToonstruckSmackerDecoder::createVideoTrack(uint32 width, uint32 height, uint32 frameCount, const Common::Rational &frameRate, uint32 flags, uint32 signature) const {
+ return Video::SmackerDecoder::createVideoTrack(width, height, frameCount, frameRate, (height == 200) ? 4 : flags, signature);
}
// decoder is deallocated with Movie destruction i.e. new ToonstruckSmackerDecoder is needed
@@ -103,6 +96,9 @@ void Movie::play(const Common::String &video, int32 flags) {
bool Movie::playVideo(bool isFirstIntroVideo) {
debugC(1, kDebugMovie, "playVideo(isFirstIntroVideo: %d)", isFirstIntroVideo);
+
+ _decoder->start();
+
while (!_vm->shouldQuit() && !_decoder->endOfVideo()) {
if (_decoder->needsUpdate()) {
const Graphics::Surface *frame = _decoder->decodeNextFrame();
@@ -131,7 +127,7 @@ bool Movie::playVideo(bool isFirstIntroVideo) {
}
}
}
- _decoder->setSystemPalette();
+ _vm->_system->getPaletteManager()->setPalette(_decoder->getPalette(), 0, 256);
_vm->_system->updateScreen();
}
diff --git a/engines/toon/movie.h b/engines/toon/movie.h
index 2cd33302f2..e795182cba 100644
--- a/engines/toon/movie.h
+++ b/engines/toon/movie.h
@@ -30,13 +30,17 @@ namespace Toon {
class ToonstruckSmackerDecoder : public Video::SmackerDecoder {
public:
- ToonstruckSmackerDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType);
- virtual ~ToonstruckSmackerDecoder() {}
- void handleAudioTrack(byte track, uint32 chunkSize, uint32 unpackedSize);
- bool loadFile(const Common::String &filename);
+ ToonstruckSmackerDecoder();
+
+ bool loadStream(Common::SeekableReadStream *stream);
bool isLowRes() { return _lowRes; }
+
protected:
- bool _lowRes;
+ void handleAudioTrack(byte track, uint32 chunkSize, uint32 unpackedSize);
+ SmackerVideoTrack *createVideoTrack(uint32 width, uint32 height, uint32 frameCount, const Common::Rational &frameRate, uint32 flags, uint32 signature) const;
+
+private:
+ bool _lowRes;
};
class Movie {
diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp
index ee427652d8..9fd8415676 100644
--- a/engines/toon/toon.cpp
+++ b/engines/toon/toon.cpp
@@ -51,7 +51,7 @@ void ToonEngine::init() {
_currentScriptRegion = 0;
_resources = new Resources(this);
_animationManager = new AnimationManager(this);
- _moviePlayer = new Movie(this, new ToonstruckSmackerDecoder(_mixer));
+ _moviePlayer = new Movie(this, new ToonstruckSmackerDecoder());
_hotspots = new Hotspots(this);
_mainSurface = new Graphics::Surface();
diff --git a/engines/tucker/sequences.cpp b/engines/tucker/sequences.cpp
index 775fd6f1a0..16c4f4f6f0 100644
--- a/engines/tucker/sequences.cpp
+++ b/engines/tucker/sequences.cpp
@@ -28,6 +28,7 @@
#include "audio/decoders/wave.h"
#include "graphics/palette.h"
+#include "graphics/surface.h"
#include "tucker/tucker.h"
#include "tucker/graphics.h"
@@ -749,6 +750,7 @@ void AnimationSequencePlayer::openAnimation(int index, const char *fileName) {
_seqNum = 1;
return;
}
+ _flicPlayer[index].start();
_flicPlayer[index].decodeNextFrame();
if (index == 0) {
getRGBPalette(index);
@@ -801,7 +803,7 @@ void AnimationSequencePlayer::playIntroSeq19_20() {
if (_flicPlayer[0].getCurFrame() >= 115) {
surface = _flicPlayer[1].decodeNextFrame();
if (_flicPlayer[1].endOfVideo())
- _flicPlayer[1].reset();
+ _flicPlayer[1].rewind();
}
bool framesLeft = decodeNextAnimationFrame(0, false);