aboutsummaryrefslogtreecommitdiff
path: root/engines/gob
diff options
context:
space:
mode:
Diffstat (limited to 'engines/gob')
-rw-r--r--engines/gob/coktelvideo.cpp32
-rw-r--r--engines/gob/coktelvideo.h15
-rw-r--r--engines/gob/detection.cpp65
-rw-r--r--engines/gob/draw_v2.cpp28
-rw-r--r--engines/gob/driver_vga.cpp19
-rw-r--r--engines/gob/game_v2.cpp12
-rw-r--r--engines/gob/gob.cpp22
-rw-r--r--engines/gob/gob.h8
-rw-r--r--engines/gob/inter.cpp4
-rw-r--r--engines/gob/inter.h1
-rw-r--r--engines/gob/inter_v2.cpp85
-rw-r--r--engines/gob/inter_v4.cpp103
-rw-r--r--engines/gob/map_v4.cpp2
-rw-r--r--engines/gob/mult_v2.cpp4
-rw-r--r--engines/gob/scenery.cpp159
-rw-r--r--engines/gob/scenery.h21
-rw-r--r--engines/gob/sound/adlib.cpp2
-rw-r--r--engines/gob/sound/cdrom.cpp6
-rw-r--r--engines/gob/sound/sound.cpp60
-rw-r--r--engines/gob/video.cpp23
-rw-r--r--engines/gob/video.h5
-rw-r--r--engines/gob/videoplayer.cpp61
-rw-r--r--engines/gob/videoplayer.h4
23 files changed, 538 insertions, 203 deletions
diff --git a/engines/gob/coktelvideo.cpp b/engines/gob/coktelvideo.cpp
index c3625574d0..415790e67b 100644
--- a/engines/gob/coktelvideo.cpp
+++ b/engines/gob/coktelvideo.cpp
@@ -123,8 +123,9 @@ bool Imd::load(Common::SeekableReadStream &stream) {
return false;
}
- _soundSliceLength = 1000 / (_soundFreq / _soundSliceSize);
- _frameLength = _soundSliceLength;
+ _soundSliceLength = (uint32) (((double) (1000 << 16)) /
+ ((double) _soundFreq / (double) _soundSliceSize));
+ _frameLength = _soundSliceLength >> 16;
_soundStage = 1;
_hasSound = true;
@@ -325,11 +326,11 @@ void Imd::waitEndFrame() {
return;
if (_skipFrames == 0) {
- int32 waitTime = (_curFrame * _soundSliceLength) -
- (g_system->getMillis() - _soundStartTime);
+ int32 waitTime = (int16) (((_curFrame * _soundSliceLength) -
+ ((g_system->getMillis() - _soundStartTime) << 16)) >> 16);
if (waitTime < 0) {
- _skipFrames = -waitTime / _soundSliceLength;
+ _skipFrames = -waitTime / (_soundSliceLength >> 16);
warning("Video A/V sync broken, skipping %d frame(s)", _skipFrames + 1);
} else if (waitTime > 0)
g_system->delayMillis(waitTime);
@@ -340,6 +341,11 @@ void Imd::waitEndFrame() {
g_system->delayMillis(_frameLength);
}
+void Imd::notifyPaused(uint32 duration) {
+ if (_soundStage == 2)
+ _soundStartTime += duration;
+}
+
void Imd::copyCurrentFrame(byte *dest,
uint16 left, uint16 top, uint16 width, uint16 height,
uint16 x, uint16 y, uint16 pitch, int16 transp) {
@@ -938,10 +944,9 @@ bool Vmd::load(Common::SeekableReadStream &stream) {
_soundSliceSize = -_soundSliceSize;
}
- _soundSliceLength = (uint16) (1000.0 /
+ _soundSliceLength = (uint32) (((double) (1000 << 16)) /
((double) _soundFreq / (double) _soundSliceSize));
-
- _frameLength = _soundSliceLength;
+ _frameLength = _soundSliceLength >> 16;
_soundStage = 1;
_audioStream = Audio::makeAppendableAudioStream(_soundFreq,
@@ -1073,8 +1078,8 @@ CoktelVideo::State Vmd::processFrame(uint16 frame) {
state.flags |= kStateNoVideoData;
state.left = 0x7FFF;
- state.right = 0x7FFF;
- state.top = 0;
+ state.top = 0x7FFF;
+ state.right = 0;
state.bottom = 0;
if (!_vidMem)
@@ -1128,6 +1133,8 @@ CoktelVideo::State Vmd::processFrame(uint16 frame) {
} else if (part.type == kPartTypeVideo) {
state.flags &= ~kStateNoVideoData;
+ uint32 size = part.size;
+
// New palette
if (part.flags & 2) {
uint8 index = _stream->readByte();
@@ -1137,9 +1144,12 @@ CoktelVideo::State Vmd::processFrame(uint16 frame) {
_stream->skip((255 - count) * 3);
state.flags |= kStatePalette;
+
+ size -= (768 + 2);
}
- _stream->read(_frameData, part.size);
+ _stream->read(_frameData, size);
+
if (renderFrame(part.left, part.top, part.right, part.bottom)) {
// Rendering succeeded, merging areas
state.left = MIN(state.left, part.left);
diff --git a/engines/gob/coktelvideo.h b/engines/gob/coktelvideo.h
index 581ac2ae81..348e5e3ab1 100644
--- a/engines/gob/coktelvideo.h
+++ b/engines/gob/coktelvideo.h
@@ -134,7 +134,7 @@ public:
/** Use an own memory block as video memory. */
virtual void setVideoMemory() = 0;
- /** Play sound (if the IMD has sound). */
+ /** Play sound (if the video has sound). */
virtual void enableSound(Audio::Mixer &mixer) = 0;
/** Don't play sound or stop currently playing sound. */
virtual void disableSound() = 0;
@@ -155,6 +155,9 @@ public:
/** Wait for the frame to end. */
virtual void waitEndFrame() = 0;
+ /** Notifies the video that it was paused for duration ms. */
+ virtual void notifyPaused(uint32 duration) = 0;
+
/** Copy the current frame.
*
* @param dest The memory to which to copy the current frame.
@@ -187,7 +190,11 @@ public:
int16 getHeight() const { return _height; }
uint16 getFramesCount() const { return _framesCount; }
uint16 getCurrentFrame() const { return _curFrame; }
- int16 getFrameRate() const { if (_hasSound) return 1000 / _soundSliceLength; return _frameRate; }
+ int16 getFrameRate() const {
+ if (_hasSound)
+ return 1000 / (_soundSliceLength >> 16);
+ return _frameRate;
+ }
uint32 getSyncLag() const { return _skipFrames; }
const byte *getPalette() const { return _palette; }
@@ -213,6 +220,8 @@ public:
State nextFrame();
void waitEndFrame();
+ void notifyPaused(uint32 duration);
+
void copyCurrentFrame(byte *dest,
uint16 left, uint16 top, uint16 width, uint16 height,
uint16 x, uint16 y, uint16 pitch, int16 transp = -1);
@@ -255,7 +264,7 @@ protected:
int16 _soundFreq;
int16 _soundSliceSize;
int16 _soundSlicesCount;
- uint16 _soundSliceLength;
+ uint32 _soundSliceLength;
Audio::AppendableAudioStream *_audioStream;
Audio::SoundHandle _audioHandle;
diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp
index cbc9272e80..8351f2ecfb 100644
--- a/engines/gob/detection.cpp
+++ b/engines/gob/detection.cpp
@@ -1684,6 +1684,71 @@ static const GOBGameDescription gameDescriptions[] = {
kFeatures640,
"intro"
},
+ { // Supplied by DjDiabolik in bug report #1971294
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
+ EN_GRB,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by DjDiabolik in bug report #1971294
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
+ DE_DEU,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by DjDiabolik in bug report #1971294
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
+ FR_FRA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by DjDiabolik in bug report #1971294
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
+ IT_ITA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by DjDiabolik in bug report #1971294
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
+ ES_ESP,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
{
{
"dynasty",
diff --git a/engines/gob/draw_v2.cpp b/engines/gob/draw_v2.cpp
index 1195e35e93..8c12079b83 100644
--- a/engines/gob/draw_v2.cpp
+++ b/engines/gob/draw_v2.cpp
@@ -247,10 +247,7 @@ void Draw_v2::printTotText(int16 id) {
if (_renderFlags & RENDERFLAG_FROMSPLIT) {
int16 start;
- if (_vm->_video->_splitHeight1 < _vm->_height)
- start = _vm->_video->_splitHeight1;
- else
- start = _vm->_video->_splitStart;
+ start = _vm->_video->_splitStart;
destY = start;
spriteBottom = READ_LE_UINT16(ptr + 6) - READ_LE_UINT16(ptr + 2);
@@ -654,22 +651,23 @@ void Draw_v2::spriteOperation(int16 operation) {
int16 destSurface = _destSurface;
int16 sourceSurface = _sourceSurface;
- if ((_destSpriteY >= _vm->_video->_splitHeight1) &&
- ((_destSurface == 20) || (_destSurface == 21))) {
-
- if (_vm->_video->_splitHeight1 < _vm->_height) {
- _destSpriteY = (_destSpriteY - _vm->_video->_splitHeight1) + _vm->_video->_splitStart;
+ if (_vm->_video->_splitSurf && ((_destSurface == 20) || (_destSurface == 21))) {
+ if ((_destSpriteY >= _vm->_video->_splitStart)) {
+ _destSpriteY -= _vm->_video->_splitStart;
if ((operation == DRAW_DRAWLINE) ||
((operation >= DRAW_DRAWBAR) && (operation <= DRAW_FILLRECTABS)))
- _spriteBottom = (_spriteBottom - _vm->_video->_splitHeight1) + _vm->_video->_splitStart;
+ _spriteBottom -= _vm->_video->_splitStart;
+
+ _destSurface += 4;
}
- }
+ if ((_spriteTop >= _vm->_video->_splitStart) && (operation == DRAW_BLITSURF)) {
+ _spriteTop -= _vm->_video->_splitStart;
+ if (_destSurface < 24)
+ _destSurface += 4;
+ }
- if ((_spriteTop >= _vm->_video->_splitHeight1) && (operation == DRAW_BLITSURF) &&
- ((_destSurface == 20) || (_destSurface == 21)))
- if (_vm->_video->_splitHeight1 < _vm->_height)
- _spriteTop = (_spriteTop - _vm->_video->_splitHeight1) + _vm->_video->_splitStart;
+ }
adjustCoords(0, &_destSpriteX, &_destSpriteY);
if ((operation != DRAW_LOADSPRITE) && (_needAdjust != 2)) {
diff --git a/engines/gob/driver_vga.cpp b/engines/gob/driver_vga.cpp
index c4861ca146..f68ce47783 100644
--- a/engines/gob/driver_vga.cpp
+++ b/engines/gob/driver_vga.cpp
@@ -109,10 +109,16 @@ void VGAVideoDriver::drawSprite(SurfaceDesc *source, SurfaceDesc *dest,
int16 width = MIN((right - left) + 1, (int) dest->getWidth());
int16 height = MIN((bottom - top) + 1, (int) dest->getHeight());
+ if ((width < 1) || (height < 1))
+ return;
+
byte *srcPos = source->getVidMem() + (top * source->getWidth()) + left;
byte *destPos = dest->getVidMem() + (y * dest->getWidth()) + x;
+ uint32 size = width * height;
+
if (transp) {
+
while (height--) {
for (int16 i = 0; i < width; ++i) {
if (srcPos[i])
@@ -122,13 +128,26 @@ void VGAVideoDriver::drawSprite(SurfaceDesc *source, SurfaceDesc *dest,
srcPos += source->getWidth();
destPos += dest->getWidth();
}
+
+ } else if (((srcPos >= destPos) && (srcPos <= (destPos + size))) ||
+ ((destPos >= srcPos) && (destPos <= (srcPos + size)))) {
+
+ while (height--) {
+ memmove(destPos, srcPos, width);
+
+ srcPos += source->getWidth();
+ destPos += dest->getWidth();
+ }
+
} else {
+
while (height--) {
memcpy(destPos, srcPos, width);
srcPos += source->getWidth();
destPos += dest->getWidth();
}
+
}
}
diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp
index ff444f4a69..e783f5bfb5 100644
--- a/engines/gob/game_v2.cpp
+++ b/engines/gob/game_v2.cpp
@@ -632,13 +632,15 @@ void Game_v2::collisionsBlock(void) {
Collision *collArea;
int16 timeKey;
byte *savedIP;
+ byte collAreaStart;
if (_shouldPushColls)
pushCollisions(0);
- collArea = _collisionAreas;
- while (collArea->left != 0xFFFF)
- collArea++;
+ collAreaStart = 0;
+ while (_collisionAreas[collAreaStart].left != 0xFFFF)
+ collAreaStart++;
+ collArea = &_collisionAreas[collAreaStart];
_shouldPushColls = 0;
collResId = -1;
@@ -964,7 +966,7 @@ void Game_v2::collisionsBlock(void) {
continue;
_activeCollResId = collPtr->id;
- _activeCollIndex = i;
+ _activeCollIndex = i + collAreaStart;
_vm->_inter->storeMouse();
if (VAR(16) != 0)
break;
@@ -1006,7 +1008,7 @@ void Game_v2::collisionsBlock(void) {
if ((collPtr->id & 0xF000) == 0x8000)
if (++counter == descIndex) {
_activeCollResId = collPtr->id;
- _activeCollIndex = i;
+ _activeCollIndex = i + collAreaStart;
break;
}
}
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp
index 5871151d6e..a3fe0ebbe2 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -75,6 +75,8 @@ GobEngine::GobEngine(OSystem *syst) : Engine(syst) {
_scenery = 0; _draw = 0; _util = 0;
_video = 0; _saveLoad = 0;
+ _pauseStart = 0;
+
// Setup mixer
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
@@ -85,12 +87,13 @@ GobEngine::GobEngine(OSystem *syst) : Engine(syst) {
Common::addSpecialDebugLevel(kDebugFuncOp, "FuncOpcodes", "Script FuncOpcodes debug level");
Common::addSpecialDebugLevel(kDebugDrawOp, "DrawOpcodes", "Script DrawOpcodes debug level");
Common::addSpecialDebugLevel(kDebugGobOp, "GoblinOpcodes", "Script GoblinOpcodes debug level");
- Common::addSpecialDebugLevel(kDebugMusic, "Music", "CD, Adlib and Infogrames music debug level");
+ Common::addSpecialDebugLevel(kDebugSound, "Sound", "Sound output debug level");
Common::addSpecialDebugLevel(kDebugParser, "Parser", "Parser debug level");
Common::addSpecialDebugLevel(kDebugGameFlow, "Gameflow", "Gameflow debug level");
Common::addSpecialDebugLevel(kDebugFileIO, "FileIO", "File Input/Output debug level");
Common::addSpecialDebugLevel(kDebugSaveLoad, "SaveLoad", "Saving/Loading debug level");
Common::addSpecialDebugLevel(kDebugGraphics, "Graphics", "Graphics debug level");
+ Common::addSpecialDebugLevel(kDebugVideo, "Video", "IMD/VMD video debug level");
Common::addSpecialDebugLevel(kDebugCollisions, "Collisions", "Collisions debug level");
syst->getEventManager()->registerRandomSource(_rnd, "gob");
@@ -247,6 +250,23 @@ int GobEngine::init() {
return 0;
}
+void GobEngine::pauseEngineIntern(bool pause) {
+ if (pause) {
+ _pauseStart = _system->getMillis();
+ } else {
+ uint32 duration = _system->getMillis() - _pauseStart;
+
+ _vm->_vidPlayer->notifyPaused(duration);
+
+ _vm->_game->_startTimeKey += duration;
+ _vm->_draw->_cursorTimeKey += duration;
+ if (_vm->_inter->_soundEndTimeKey != 0)
+ _vm->_inter->_soundEndTimeKey += duration;
+ }
+
+ _mixer->pauseAll(pause);
+}
+
bool GobEngine::initGameParts() {
_noMusic = MidiDriver::parseMusicDriver(ConfMan.get("music_driver")) == MD_NULL;
diff --git a/engines/gob/gob.h b/engines/gob/gob.h
index 0a82bceed5..efc9718098 100644
--- a/engines/gob/gob.h
+++ b/engines/gob/gob.h
@@ -100,13 +100,14 @@ enum {
kDebugFuncOp = 1 << 0,
kDebugDrawOp = 1 << 1,
kDebugGobOp = 1 << 2,
- kDebugMusic = 1 << 3, // CD, Adlib and Infogrames music
+ kDebugSound = 1 << 3,
kDebugParser = 1 << 4,
kDebugGameFlow = 1 << 5,
kDebugFileIO = 1 << 6,
kDebugSaveLoad = 1 << 7,
kDebugGraphics = 1 << 8,
- kDebugCollisions = 1 << 9
+ kDebugVideo = 1 << 9,
+ kDebugCollisions = 1 << 10
};
inline char *strncpy0(char *dest, const char *src, size_t n) {
@@ -177,9 +178,12 @@ private:
int32 _features;
Common::Platform _platform;
+ uint32 _pauseStart;
+
int go();
int init();
+ void pauseEngineIntern(bool pause);
bool initGameParts();
void deinitGameParts();
diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp
index dd3fdf3684..9e5005f443 100644
--- a/engines/gob/inter.cpp
+++ b/engines/gob/inter.cpp
@@ -23,6 +23,8 @@
*
*/
+#include <time.h> // FIXME: for Inter::renewTimeInVars()
+
#include "common/endian.h"
#include "gob/gob.h"
@@ -35,8 +37,6 @@
#include "gob/scenery.h"
#include "gob/sound/sound.h"
-#include <time.h> // FIXME: for Inter::renewTimeInVars()
-
namespace Gob {
Inter::Inter(GobEngine *vm) : _vm(vm) {
diff --git a/engines/gob/inter.h b/engines/gob/inter.h
index 582e57a2d4..e43cb4e891 100644
--- a/engines/gob/inter.h
+++ b/engines/gob/inter.h
@@ -519,6 +519,7 @@ protected:
virtual const char *getOpcodeFuncDesc(byte i, byte j);
virtual const char *getOpcodeGoblinDesc(int i);
+ void o4_initScreen();
void o4_playVmdOrMusic();
};
diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp
index 493efa8438..e442ec4eca 100644
--- a/engines/gob/inter_v2.cpp
+++ b/engines/gob/inter_v2.cpp
@@ -1087,6 +1087,8 @@ void Inter_v2::o2_playCDTrack() {
}
void Inter_v2::o2_waitCDTrackEnd() {
+ debugC(1, kDebugSound, "CDROM: Waiting for playback to end");
+
while (_vm->_sound->cdGetTrackPos() >= 0)
_vm->_util->longDelay(1);
}
@@ -1431,49 +1433,17 @@ void Inter_v2::o2_initScreen() {
if (height > 0)
_vm->_video->_surfHeight = height;
- if (videoMode == 0x18) {
-
- if (_vm->_video->_surfWidth < _vm->_width)
- _vm->_video->_screenDeltaX = (_vm->_width - _vm->_video->_surfWidth) / 2;
- else
- _vm->_video->_screenDeltaX = 0;
-
- _vm->_global->_mouseMinX = _vm->_video->_screenDeltaX;
- _vm->_global->_mouseMaxX = _vm->_video->_screenDeltaX + _vm->_video->_surfWidth - 1;
-
-
- int16 screenHeight = _vm->_video->_surfHeight;
-
- if (screenHeight < _vm->_height) {
- _vm->_video->_surfHeight += offY;
- _vm->_video->_splitStart = screenHeight;
- } else
- _vm->_video->_splitStart = screenHeight - offY;
-
- _vm->_video->_splitHeight1 = MIN<int16>(_vm->_height, screenHeight - offY);
- _vm->_video->_splitHeight2 = offY;
-
- if ((_vm->_video->_surfHeight + offY) < _vm->_height)
- _vm->_video->_screenDeltaY = (_vm->_height - (screenHeight + offY)) / 2;
- else
- _vm->_video->_screenDeltaY = 0;
-
- _vm->_global->_mouseMaxY = (screenHeight + _vm->_video->_screenDeltaY) - offY - 1;
- _vm->_global->_mouseMinY = _vm->_video->_screenDeltaY;
+ _vm->_video->_splitHeight1 = MIN<int16>(_vm->_height, _vm->_video->_surfHeight - offY);
+ _vm->_video->_splitHeight2 = offY;
+ _vm->_video->_splitStart = _vm->_video->_surfHeight - offY;
- } else {
- _vm->_video->_splitHeight1 = MIN<int16>(_vm->_height, _vm->_video->_surfHeight - offY);
- _vm->_video->_splitHeight2 = offY;
- _vm->_video->_splitStart = _vm->_video->_surfHeight - offY;
+ _vm->_video->_screenDeltaX = 0;
+ _vm->_video->_screenDeltaY = 0;
- _vm->_video->_screenDeltaX = 0;
- _vm->_video->_screenDeltaY = 0;
-
- _vm->_global->_mouseMinX = 0;
- _vm->_global->_mouseMinY = 0;
- _vm->_global->_mouseMaxX = _vm->_width;
- _vm->_global->_mouseMaxY = _vm->_height - _vm->_video->_splitHeight2 - 1;
- }
+ _vm->_global->_mouseMinX = 0;
+ _vm->_global->_mouseMinY = 0;
+ _vm->_global->_mouseMaxX = _vm->_width;
+ _vm->_global->_mouseMaxY = _vm->_height - _vm->_video->_splitHeight2 - 1;
_vm->_draw->closeScreen();
_vm->_util->clearPalette();
@@ -1532,18 +1502,27 @@ void Inter_v2::o2_scroll() {
}
void Inter_v2::o2_setScrollOffset() {
- int16 offset;
+ int16 offsetX, offsetY;
- offset = _vm->_parse->parseValExpr();
+ offsetX = _vm->_parse->parseValExpr();
+ offsetY = _vm->_parse->parseValExpr();
- if (offset == -1) {
- _vm->_parse->parseValExpr();
+ if (offsetX == -1) {
WRITE_VAR(2, _vm->_draw->_scrollOffsetX);
WRITE_VAR(3, _vm->_draw->_scrollOffsetY);
} else {
- _vm->_draw->_scrollOffsetX = offset;
- _vm->_draw->_scrollOffsetY = _vm->_parse->parseValExpr();
+ int16 screenW = _vm->_video->_surfWidth;
+ int16 screenH = _vm->_video->_surfHeight;
+
+ if (screenW > _vm->_width)
+ screenW -= _vm->_width;
+ if (screenH > _vm->_height)
+ screenH -= _vm->_height;
+
+ _vm->_draw->_scrollOffsetX = CLIP<int16>(offsetX, 0, screenW);
+ _vm->_draw->_scrollOffsetY = CLIP<int16>(offsetY, 0, screenH);
}
+
_vm->_util->setScrollOffset();
_noBusyWait = true;
}
@@ -1574,6 +1553,10 @@ void Inter_v2::o2_playImd() {
palEnd = _vm->_parse->parseValExpr();
palCmd = 1 << (flags & 0x3F);
+ debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, "
+ "paletteCmd %d (%d - %d), flags %X", _vm->_global->_inter_resStr, x, y,
+ startFrame, lastFrame, palCmd, palStart, palEnd, flags);
+
if ((imd[0] != 0) && !_vm->_vidPlayer->primaryOpen(imd, x, y, flags)) {
WRITE_VAR(11, -1);
return;
@@ -1607,6 +1590,12 @@ void Inter_v2::o2_getImdInfo() {
varWidth = _vm->_parse->parseVarIndex();
varHeight = _vm->_parse->parseVarIndex();
+ // WORKAROUND: The nut rolling animation in the administration center
+ // in Woodruff is called "noixroul", but the scripts think it's "noixroule".
+ if ((_vm->getGameType() == kGameTypeWoodruff) &&
+ (!scumm_stricmp(_vm->_global->_inter_resStr, "noixroule")))
+ strcpy(_vm->_global->_inter_resStr, "noixroul");
+
_vm->_vidPlayer->writeVideoInfo(_vm->_global->_inter_resStr, varX, varY,
varFrames, varWidth, varHeight);
}
@@ -2056,7 +2045,6 @@ void Inter_v2::o2_loadInfogramesIns(OpGobParams &params) {
strncpy0(fileName, GET_VAR_STR(varName), 15);
strcat(fileName, ".INS");
- debugC(1, kDebugMusic, "Loading Infogrames instrument file \"%s\"", fileName);
_vm->_sound->infogramesLoadInstruments(fileName);
}
@@ -2069,7 +2057,6 @@ void Inter_v2::o2_playInfogrames(OpGobParams &params) {
strncpy0(fileName, GET_VAR_STR(varName), 15);
strcat(fileName, ".DUM");
- debugC(1, kDebugMusic, "Playing Infogrames music file \"%s\"", fileName);
_vm->_sound->infogramesLoadSong(fileName);
_vm->_sound->infogramesPlay();
diff --git a/engines/gob/inter_v4.cpp b/engines/gob/inter_v4.cpp
index 76b11752e0..fd90b731a2 100644
--- a/engines/gob/inter_v4.cpp
+++ b/engines/gob/inter_v4.cpp
@@ -29,6 +29,7 @@
#include "gob/gob.h"
#include "gob/inter.h"
#include "gob/global.h"
+#include "gob/draw.h"
#include "gob/game.h"
#include "gob/parse.h"
#include "gob/videoplayer.h"
@@ -279,7 +280,7 @@ void Inter_v4::setupOpcodes() {
{NULL, ""},
{NULL, ""},
/* 80 */
- OPCODE(o2_initScreen),
+ OPCODE(o4_initScreen),
OPCODE(o2_scroll),
OPCODE(o2_setScrollOffset),
OPCODE(o4_playVmdOrMusic),
@@ -504,7 +505,7 @@ void Inter_v4::setupOpcodes() {
/* 30 */
OPCODE(o1_returnTo),
OPCODE(o1_loadSpriteContent),
- OPCODE(o3_copySprite),
+ OPCODE(o1_copySprite),
OPCODE(o1_fillRect),
/* 34 */
OPCODE(o1_drawLine),
@@ -687,6 +688,8 @@ void Inter_v4::executeGoblinOpcode(int i, OpGobParams &params) {
}
if (op == NULL) {
+ warning("unimplemented opcodeGoblin: %d", i);
+
int16 val;
_vm->_global->_inter_execPtr -= 2;
@@ -714,6 +717,86 @@ const char *Inter_v4::getOpcodeGoblinDesc(int i) {
return "";
}
+void Inter_v4::o4_initScreen() {
+ int16 offY;
+ int16 videoMode;
+ int16 width, height;
+
+ offY = load16();
+
+ videoMode = offY & 0xFF;
+ offY = (offY >> 8) & 0xFF;
+
+ width = _vm->_parse->parseValExpr();
+ height = _vm->_parse->parseValExpr();
+
+ _vm->_video->clearScreen();
+
+ _vm->_global->_fakeVideoMode = videoMode;
+
+ // Some versions require this
+ if (videoMode == 0xD)
+ videoMode = _vm->_mode;
+
+ if ((videoMode == _vm->_global->_videoMode) && (width == -1))
+ return;
+
+ if (width > 0)
+ _vm->_video->_surfWidth = width;
+ if (height > 0)
+ _vm->_video->_surfHeight = height;
+
+ _vm->_video->_screenDeltaX = 0;
+ if (_vm->_video->_surfWidth < _vm->_width)
+ _vm->_video->_screenDeltaX = (_vm->_width - _vm->_video->_surfWidth) / 2;
+
+ _vm->_global->_mouseMinX = _vm->_video->_screenDeltaX;
+ _vm->_global->_mouseMaxX = _vm->_video->_screenDeltaX + _vm->_video->_surfWidth - 1;
+
+ _vm->_video->_splitStart = _vm->_video->_surfHeight - offY;
+
+ _vm->_video->_splitHeight1 = MIN<int16>(_vm->_height, _vm->_video->_surfHeight);
+ _vm->_video->_splitHeight2 = offY;
+
+ if ((_vm->_video->_surfHeight + offY) < _vm->_height)
+ _vm->_video->_screenDeltaY = (_vm->_height - (_vm->_video->_surfHeight + offY)) / 2;
+ else
+ _vm->_video->_screenDeltaY = 0;
+
+ _vm->_global->_mouseMaxY = (_vm->_video->_surfHeight + _vm->_video->_screenDeltaY) - offY - 1;
+ _vm->_global->_mouseMinY = _vm->_video->_screenDeltaY;
+
+ _vm->_draw->closeScreen();
+ _vm->_util->clearPalette();
+ memset(_vm->_global->_redPalette, 0, 256);
+ memset(_vm->_global->_greenPalette, 0, 256);
+ memset(_vm->_global->_bluePalette, 0, 256);
+
+ _vm->_video->_splitSurf = 0;
+ _vm->_draw->_spritesArray[24] = 0;
+ _vm->_draw->_spritesArray[25] = 0;
+
+ _vm->_global->_videoMode = videoMode;
+ _vm->_video->initPrimary(videoMode);
+ WRITE_VAR(15, _vm->_global->_fakeVideoMode);
+
+ _vm->_global->_setAllPalette = true;
+
+ _vm->_util->setMousePos(_vm->_global->_inter_mouseX,
+ _vm->_global->_inter_mouseY);
+ _vm->_util->clearPalette();
+
+ _vm->_draw->initScreen();
+
+ _vm->_util->setScrollOffset();
+
+ if (offY > 0) {
+ _vm->_draw->_spritesArray[24] = new SurfaceDesc(videoMode, _vm->_width, offY);
+ _vm->_draw->_spritesArray[25] = new SurfaceDesc(videoMode, _vm->_width, offY);
+ _vm->_video->_splitSurf = _vm->_draw->_spritesArray[25];
+ }
+}
+
void Inter_v4::o4_playVmdOrMusic() {
char fileName[128];
int16 x, y;
@@ -729,6 +812,12 @@ void Inter_v4::o4_playVmdOrMusic() {
evalExpr(0);
strncpy0(fileName, _vm->_global->_inter_resStr, 127);
+ // WORKAROUND: The nut rolling animation in the administration center
+ // in Woodruff is called "noixroul", but the scripts think it's "noixroule".
+ if ((_vm->getGameType() == kGameTypeWoodruff) &&
+ (!scumm_stricmp(fileName, "noixroule")))
+ strcpy(fileName, "noixroul");
+
x = _vm->_parse->parseValExpr();
y = _vm->_parse->parseValExpr();
startFrame = _vm->_parse->parseValExpr();
@@ -739,11 +828,14 @@ void Inter_v4::o4_playVmdOrMusic() {
palEnd = _vm->_parse->parseValExpr();
palCmd = 1 << (flags & 0x3F);
+ debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, "
+ "paletteCmd %d (%d - %d), flags %X", fileName, x, y, startFrame, lastFrame,
+ palCmd, palStart, palEnd, flags);
+
close = false;
if (lastFrame == -1) {
close = true;
} else if (lastFrame == -3) {
-// warning("Woodruff Stub: Video/Music command -3: Play background video %s, %d, %d, %d, %d", fileName, startFrame, x, y, VAR_OFFSET(7872));
_vm->_mult->_objects[startFrame].pAnimData->animation = -startFrame - 1;
@@ -767,17 +859,16 @@ void Inter_v4::o4_playVmdOrMusic() {
warning("Woodruff Stub: Video/Music command -4: Play background video %s", fileName);
return;
} else if (lastFrame == -5) {
-// warning("Woodruff Stub: Video/Music command -5: Stop background music");
_vm->_sound->bgStop();
return;
} else if (lastFrame == -6) {
-// warning("Woodruff Stub: Video/Music command -6: Load background video %s", fileName);
+ return;
+ } else if (lastFrame == -7) {
return;
} else if (lastFrame == -8) {
warning("Woodruff Stub: Video/Music command -8: Play background video %s", fileName);
return;
} else if (lastFrame == -9) {
-// warning("Woodruff Stub: Video/Music command -9: Play background music %s (%d-%d)", fileName, palEnd, palStart);
_vm->_sound->bgStop();
_vm->_sound->bgSetPlayMode(BackgroundAtmosphere::kPlayModeRandom);
_vm->_sound->bgPlay(fileName, palStart);
diff --git a/engines/gob/map_v4.cpp b/engines/gob/map_v4.cpp
index 721f040341..a3c3222213 100644
--- a/engines/gob/map_v4.cpp
+++ b/engines/gob/map_v4.cpp
@@ -113,7 +113,7 @@ void Map_v4::loadMapObjects(const char *avjFile) {
}
if (_widthByte == 4)
- _mapWidth = (int16) READ_VARO_UINT16(68);
+ _mapWidth = VAR(17);
_passWidth = _mapWidth;
diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp
index 8a299649c7..3a83ac1867 100644
--- a/engines/gob/mult_v2.cpp
+++ b/engines/gob/mult_v2.cpp
@@ -755,7 +755,7 @@ void Mult_v2::newCycleAnim(Mult_Object &animObj) {
animData.frame = 0;
if ((animData.animation < 0) && (animObj.videoSlot > 0)) {
_vm->_vidPlayer->slotClose(animObj.videoSlot - 1);
- animObj.videoSlot = 0;
+ animObj.videoSlot = 0;
}
break;
@@ -764,12 +764,14 @@ void Mult_v2::newCycleAnim(Mult_Object &animObj) {
case 7:
animData.frame--;
animData.isPaused = 1;
+/*
if ((animData.animation < 0) && (animObj.videoSlot > 0)) {
if (_vm->_vidPlayer->getFlags(animObj.videoSlot - 1) & 0x1000) {
_vm->_vidPlayer->slotClose(animObj.videoSlot - 1);
animObj.videoSlot = 0;
}
}
+*/
break;
case 10:
diff --git a/engines/gob/scenery.cpp b/engines/gob/scenery.cpp
index 25df5b7e71..6b52cdbbd6 100644
--- a/engines/gob/scenery.cpp
+++ b/engines/gob/scenery.cpp
@@ -100,7 +100,6 @@ int16 Scenery::loadStatic(char search) {
byte *extData = 0;
byte *dataPtr;
Static *ptr;
- int16 pictDescId;
int16 width;
int16 height;
int16 sprResId;
@@ -143,8 +142,6 @@ int16 Scenery::loadStatic(char search) {
dataPtr += 2;
ptr->layers = new StaticLayer[ptr->layersCount];
- ptr->pieces = new PieceDesc*[picsCount];
- ptr->piecesFromExt = new bool[picsCount];
for (int i = 0; i < ptr->layersCount; i++) {
int16 offset = READ_LE_UINT16(dataPtr + i * 2);
@@ -166,18 +163,13 @@ int16 Scenery::loadStatic(char search) {
backsPtr++;
}
+ ptr->pieces = new PieceDesc*[picsCount];
+ ptr->piecesCount = new uint32[picsCount];
+
for (int i = 0; i < picsCount; i++) {
- pictDescId = _vm->_inter->load16();
+ int16 pictDescId = _vm->_inter->load16();
- if (pictDescId >= 30000) {
- ptr->pieces[i] =
- (PieceDesc *) _vm->_game->loadExtData(pictDescId, 0, 0);
- ptr->piecesFromExt[i] = true;
- } else {
- ptr->pieces[i] =
- (PieceDesc *) _vm->_game->loadTotResource(pictDescId);
- ptr->piecesFromExt[i] = false;
- }
+ loadPieces(pictDescId, ptr->pieces[i], ptr->piecesCount[i]);
width = _vm->_inter->load16();
height = _vm->_inter->load16();
@@ -224,8 +216,7 @@ void Scenery::freeStatic(int16 index) {
return;
for (int i = 0; i < _staticPictCount[index]; i++) {
- if (_statics[index].piecesFromExt[i])
- delete[] _statics[index].pieces[i];
+ delete[] _statics[index].pieces[i];
spr = _staticPictToSprite[index * 7 + i];
_spriteRefs[spr]--;
@@ -239,7 +230,7 @@ void Scenery::freeStatic(int16 index) {
delete[] _statics[index].layers[i].planes;
delete[] _statics[index].layers;
delete[] _statics[index].pieces;
- delete[] _statics[index].piecesFromExt;
+ delete[] _statics[index].piecesCount;
_statics[index].layersCount = 0;
_staticPictCount[index] = -1;
@@ -253,8 +244,8 @@ void Scenery::renderStatic(int16 scenery, int16 layer) {
int16 order;
int16 plane;
- int16 pieceIndex;
- int16 pictIndex;
+ uint16 pieceIndex;
+ uint16 pictIndex;
int16 left;
int16 right;
@@ -286,12 +277,21 @@ void Scenery::renderStatic(int16 scenery, int16 layer) {
pieceIndex = planePtr->pieceIndex;
pictIndex = planePtr->pictIndex - 1;
+ if (pictIndex >= _staticPictCount[scenery])
+ continue;
+
+ if (!ptr->pieces || !ptr->pieces[pictIndex])
+ continue;
+
+ if (pieceIndex >= ptr->piecesCount[pictIndex])
+ continue;
+
_vm->_draw->_destSpriteX = planePtr->destX;
_vm->_draw->_destSpriteY = planePtr->destY;
- left = FROM_LE_16(ptr->pieces[pictIndex][pieceIndex].left);
- right = FROM_LE_16(ptr->pieces[pictIndex][pieceIndex].right);
- top = FROM_LE_16(ptr->pieces[pictIndex][pieceIndex].top);
- bottom = FROM_LE_16(ptr->pieces[pictIndex][pieceIndex].bottom);
+ left = ptr->pieces[pictIndex][pieceIndex].left;
+ right = ptr->pieces[pictIndex][pieceIndex].right;
+ top = ptr->pieces[pictIndex][pieceIndex].top;
+ bottom = ptr->pieces[pictIndex][pieceIndex].bottom;
_vm->_draw->_sourceSurface =
_staticPictToSprite[scenery * 7 + pictIndex];
@@ -313,8 +313,8 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) {
int16 planeCount;
int16 order;
int16 plane;
- int16 pieceIndex;
- int16 pictIndex;
+ uint16 pieceIndex;
+ uint16 pictIndex;
int16 left;
int16 right;
@@ -338,16 +338,22 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) {
pieceIndex = planePtr->pieceIndex;
pictIndex = planePtr->pictIndex - 1;
- if ((pictIndex >= _staticPictCount[index]) || (!pictPtr[pictIndex]))
+ if (pictIndex >= _staticPictCount[index])
+ continue;
+
+ if (!pictPtr || !pictPtr[pictIndex])
+ continue;
+
+ if (pieceIndex >= _statics[index].piecesCount[pictIndex])
continue;
_vm->_draw->_destSpriteX = planePtr->destX;
_vm->_draw->_destSpriteY = planePtr->destY;
- left = FROM_LE_16(pictPtr[pictIndex][pieceIndex].left);
- right = FROM_LE_16(pictPtr[pictIndex][pieceIndex].right);
- top = FROM_LE_16(pictPtr[pictIndex][pieceIndex].top);
- bottom = FROM_LE_16(pictPtr[pictIndex][pieceIndex].bottom);
+ left = pictPtr[pictIndex][pieceIndex].left;
+ right = pictPtr[pictIndex][pieceIndex].right;
+ top = pictPtr[pictIndex][pieceIndex].top;
+ bottom = pictPtr[pictIndex][pieceIndex].bottom;
if (_vm->_draw->_destSpriteX > _toRedrawRight)
continue;
@@ -418,7 +424,6 @@ int16 Scenery::loadAnim(char search) {
byte *extData;
byte *dataPtr;
Animation *ptr;
- int16 pictDescId;
int16 width;
int16 height;
int16 sprResId;
@@ -457,9 +462,6 @@ int16 Scenery::loadAnim(char search) {
dataPtr += 2;
ptr->layers = new AnimLayer[ptr->layersCount];
- ptr->pieces = new PieceDesc*[picsCount];
- ptr->piecesFromExt = new bool[picsCount];
- ptr->sizes = new uint16[picsCount];
for (i = 0; i < ptr->layersCount; i++) {
int16 offset = READ_LE_UINT16(dataPtr + i * 2);
@@ -495,23 +497,13 @@ int16 Scenery::loadAnim(char search) {
}
}
+ ptr->pieces = new PieceDesc*[picsCount];
+ ptr->piecesCount = new uint32[picsCount];
+
for (i = 0; i < picsCount; i++) {
- pictDescId = _vm->_inter->load16();
- if (pictDescId >= 30000) {
- uint32 size;
-
- ptr->pieces[i] =
- (PieceDesc *) _vm->_game->loadExtData(pictDescId, 0, 0, &size);
- ptr->piecesFromExt[i] = true;
- ptr->sizes[i] = size / 8;
- } else {
- int16 size;
+ int16 pictDescId = _vm->_inter->load16();
- ptr->pieces[i] =
- (PieceDesc *) _vm->_game->loadTotResource(pictDescId, &size);
- ptr->piecesFromExt[i] = false;
- ptr->sizes[i] = size / 8;
- }
+ loadPieces(pictDescId, ptr->pieces[i], ptr->piecesCount[i]);
width = _vm->_inter->load16();
height = _vm->_inter->load16();
@@ -557,8 +549,7 @@ void Scenery::freeAnim(int16 index) {
return;
for (int i = 0; i < _animPictCount[index]; i++) {
- if (_animations[index].piecesFromExt[i])
- delete[] _animations[index].pieces[i];
+ delete[] _animations[index].pieces[i];
spr = _animPictToSprite[index * 7 + i];
_spriteRefs[spr]--;
@@ -572,8 +563,7 @@ void Scenery::freeAnim(int16 index) {
delete[] _animations[index].layers[i].frames;
delete[] _animations[index].layers;
delete[] _animations[index].pieces;
- delete[] _animations[index].piecesFromExt;
- delete[] _animations[index].sizes;
+ delete[] _animations[index].piecesCount;
_animPictCount[index] = 0;
}
@@ -623,8 +613,8 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
Mult::Mult_Object &obj = _vm->_mult->_objects[-animation - 1];
- if (!_vm->_vidPlayer->slotIsOpen(obj.videoSlot - 1)) {
- _toRedrawLeft = -1234;
+ if ((obj.videoSlot == 0) || !_vm->_vidPlayer->slotIsOpen(obj.videoSlot - 1)) {
+ _toRedrawLeft = -12345;
return;
}
@@ -736,7 +726,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
}
- if (flags & 4) {
+ if (!(flags & 4)) {
_animLeft = _toRedrawLeft = left;
_animTop = _toRedrawTop = top;
_animRight = _toRedrawRight = right;
@@ -824,20 +814,19 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
pictIndex = (pictIndex & 15) - 1;
- if ((pictIndex == 0xFFFF) || (_animPictCount[animation] <= pictIndex)) {
- warning("Scenery::updateAnim: pictIndex out of range");
- return;
- }
+ if (pictIndex >= _animPictCount[animation])
+ continue;
- if (_animations[animation].sizes[pictIndex] <= pieceIndex) {
- warning("Scenery::updateAnim: pieceIndex out of range");
+ if (!pictPtr[pictIndex])
+ continue;
+
+ if (pieceIndex >= _animations[animation].piecesCount[pictIndex])
continue;
- }
- left = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].left);
- right = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].right);
- top = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].top);
- bottom = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].bottom);
+ left = pictPtr[pictIndex][pieceIndex].left;
+ right = pictPtr[pictIndex][pieceIndex].right;
+ top = pictPtr[pictIndex][pieceIndex].top;
+ bottom = pictPtr[pictIndex][pieceIndex].bottom;
if (flags & 2) {
if (destX < _vm->_mult->_animLeft) {
@@ -958,4 +947,42 @@ Scenery::AnimLayer *Scenery::getAnimLayer(uint16 index, uint16 layer) {
return &_animations[index].layers[layer];
}
+void Scenery::loadPieces(int16 pictDescId, PieceDesc *&pieceDesc, uint32 &piecesCount) {
+ byte *data;
+ uint32 size;
+ bool fromExt = false;
+
+ if (pictDescId >= 30000) {
+ fromExt = true;
+
+ uint32 eSize;
+
+ data = _vm->_game->loadExtData(pictDescId, 0, 0, &eSize);
+ size = eSize;
+ } else {
+ int16 tSize;
+
+ data = _vm->_game->loadTotResource(pictDescId, &tSize);
+ size = tSize;
+ }
+
+ if (!data)
+ error("Scenery::loadPieces(): Can't load pictDescId %d", pictDescId);
+
+ piecesCount = size / 8;
+ pieceDesc = new PieceDesc[piecesCount];
+
+ Common::MemoryReadStream pieceData(data, size);
+
+ for (uint32 i = 0; i < piecesCount; i++) {
+ pieceDesc[i].left = (int16) pieceData.readUint16LE();
+ pieceDesc[i].right = (int16) pieceData.readUint16LE();
+ pieceDesc[i].top = (int16) pieceData.readUint16LE();
+ pieceDesc[i].bottom = (int16) pieceData.readUint16LE();
+ }
+
+ if (fromExt)
+ delete[] data;
+}
+
} // End of namespace Gob
diff --git a/engines/gob/scenery.h b/engines/gob/scenery.h
index 03ef84e16d..21bf29deda 100644
--- a/engines/gob/scenery.h
+++ b/engines/gob/scenery.h
@@ -34,10 +34,10 @@ public:
#include "common/pack-start.h" // START STRUCT PACKING
struct PieceDesc {
- int16 left; //NOTE:
- int16 right; //These are stored in Little Endian format
- int16 top; //And should be converted by client code when accessed
- int16 bottom; //i.e. use FROM_LE_16()
+ int16 left;
+ int16 right;
+ int16 top;
+ int16 bottom;
} PACKED_STRUCT;
struct StaticPlane {
@@ -82,19 +82,16 @@ public:
int16 layersCount;
StaticLayer *layers;
PieceDesc **pieces;
- bool *piecesFromExt;
- Static() : layersCount(0), layers(0), pieces(0),
- piecesFromExt(0) {}
+ uint32 *piecesCount;
+ Static() : layersCount(0), layers(0), pieces(0), piecesCount(0) {}
};
struct Animation {
int16 layersCount;
AnimLayer *layers;
PieceDesc **pieces;
- bool *piecesFromExt;
- uint16 *sizes;
- Animation() : layersCount(0), layers(0), pieces(0),
- piecesFromExt(0) {}
+ uint32 *piecesCount;
+ Animation() : layersCount(0), layers(0), pieces(0), piecesCount(0) {}
};
int16 _curStatic;
@@ -151,6 +148,8 @@ protected:
GobEngine *_vm;
+ void loadPieces(int16 pictDescId, PieceDesc *&pieceDesc, uint32 &piecesCount);
+
void updateStatic(int16 orderFrom, byte index, byte layer);
};
diff --git a/engines/gob/sound/adlib.cpp b/engines/gob/sound/adlib.cpp
index fb0d9d58c1..b3d392ad1e 100644
--- a/engines/gob/sound/adlib.cpp
+++ b/engines/gob/sound/adlib.cpp
@@ -125,7 +125,7 @@ int AdLib::readBuffer(int16 *buffer, const int numSamples) {
}
void AdLib::writeOPL(byte reg, byte val) {
- debugC(6, kDebugMusic, "writeOPL(%02X, %02X)", reg, val);
+ debugC(6, kDebugSound, "writeOPL(%02X, %02X)", reg, val);
OPLWriteReg(_opl, reg, val);
}
diff --git a/engines/gob/sound/cdrom.cpp b/engines/gob/sound/cdrom.cpp
index f3bc70807e..eef8025cc2 100644
--- a/engines/gob/sound/cdrom.cpp
+++ b/engines/gob/sound/cdrom.cpp
@@ -83,8 +83,6 @@ void CDROM::startTrack(const char *trackName) {
if (!_LICbuffer)
return;
- debugC(1, kDebugMusic, "CDROM::startTrack(%s)", trackName);
-
byte *matchPtr = getTrackBuffer(trackName);
if (!matchPtr) {
warning("Track \"%s\" not found", trackName);
@@ -114,8 +112,6 @@ void CDROM::play(uint32 from, uint32 to) {
// HSG encodes frame information into a double word:
// minute multiplied by 4500, plus second multiplied by 75,
// plus frame, minus 150
- debugC(1, kDebugMusic, "CDROM::play(%d, %d)", from, to);
-
AudioCD.play(1, 1, from, to - from + 1);
_cdPlaying = true;
}
@@ -159,8 +155,6 @@ void CDROM::stopPlaying() {
}
void CDROM::stop() {
- debugC(1, kDebugMusic, "CDROM::stop()");
-
_curTrackBuffer = 0;
AudioCD.stop();
_cdPlaying = false;
diff --git a/engines/gob/sound/sound.cpp b/engines/gob/sound/sound.cpp
index 63b74ca36f..a90afe0e27 100644
--- a/engines/gob/sound/sound.cpp
+++ b/engines/gob/sound/sound.cpp
@@ -56,6 +56,8 @@ Sound::~Sound() {
delete _blaster;
delete _adlib;
delete _infogrames;
+ delete _cdrom;
+ delete _bgatmos;
for (int i = 0; i < kSoundsCount; i++)
_sounds[i].free();
@@ -92,6 +94,8 @@ bool Sound::sampleLoad(SoundDesc *sndDesc, const char *fileName, bool tryExist)
if (!sndDesc)
return false;
+ debugC(2, kDebugSound, "Loading sample \"%s\"", fileName);
+
int16 handle = _vm->_dataIO->openData(fileName);
if (handle < 0) {
warning("Can't open sample file \"%s\"", fileName);
@@ -137,6 +141,8 @@ void Sound::speakerOn(int16 frequency, int32 length) {
if (!_pcspeaker)
return;
+ debugC(1, kDebugSound, "PCSpeaker: Playing tone (%d, %d)", frequency, length);
+
_pcspeaker->speakerOn(frequency, length);
}
@@ -144,6 +150,8 @@ void Sound::speakerOff() {
if (!_pcspeaker)
return;
+ debugC(1, kDebugSound, "PCSpeaker: Stopping tone");
+
_pcspeaker->speakerOff();
}
@@ -158,6 +166,8 @@ bool Sound::infogramesLoadInstruments(const char *fileName) {
if (!_infogrames)
return false;
+ debugC(1, kDebugSound, "Infogrames: Loading instruments \"%s\"", fileName);
+
return _infogrames->loadInstruments(fileName);
}
@@ -165,6 +175,8 @@ bool Sound::infogramesLoadSong(const char *fileName) {
if (!_infogrames)
return false;
+ debugC(1, kDebugSound, "Infogrames: Loading song \"%s\"", fileName);
+
return _infogrames->loadSong(fileName);
}
@@ -172,6 +184,8 @@ void Sound::infogramesPlay() {
if (!_infogrames)
return;
+ debugC(1, kDebugSound, "Infogrames: Starting playback");
+
_infogrames->play();
}
@@ -179,6 +193,8 @@ void Sound::infogramesStop() {
if (!_infogrames)
return;
+ debugC(1, kDebugSound, "Infogrames: Stopping playback");
+
_infogrames->stop();
}
@@ -186,6 +202,8 @@ bool Sound::adlibLoad(const char *fileName) {
if (!_adlib)
return false;
+ debugC(1, kDebugSound, "Adlib: Loading data (\"%s\")", fileName);
+
return _adlib->load(fileName);
}
@@ -193,6 +211,8 @@ bool Sound::adlibLoad(byte *data, uint32 size, int index) {
if (!_adlib)
return false;
+ debugC(1, kDebugSound, "Adlib: Loading data (%d)", index);
+
return _adlib->load(data, size, index);
}
@@ -200,6 +220,8 @@ void Sound::adlibUnload() {
if (!_adlib)
return;
+ debugC(1, kDebugSound, "Adlib: Unloading data");
+
_adlib->unload();
}
@@ -207,7 +229,7 @@ void Sound::adlibPlayTrack(const char *trackname) {
if (!_adlib || _adlib->isPlaying())
return;
- debugC(1, kDebugMusic, "Adlib::playTrack(%s)", trackname);
+ debugC(1, kDebugSound, "Adlib: Playing track \"%s\"", trackname);
_adlib->unload();
_adlib->load(trackname);
@@ -235,6 +257,8 @@ void Sound::adlibPlay() {
if (!_adlib)
return;
+ debugC(1, kDebugSound, "Adlib: Starting playback");
+
_adlib->startPlay();
}
@@ -242,6 +266,8 @@ void Sound::adlibStop() {
if (!_adlib)
return;
+ debugC(1, kDebugSound, "Adlib: Stopping playback");
+
_adlib->stopPlay();
}
@@ -278,6 +304,9 @@ void Sound::blasterPlay(SoundDesc *sndDesc, int16 repCount,
if (!_blaster || !sndDesc)
return;
+ debugC(1, kDebugSound, "SoundBlaster: Playing sample (%d, %d, %d)",
+ repCount, frequency, fadeLength);
+
_blaster->playSample(*sndDesc, repCount, frequency, fadeLength);
}
@@ -285,6 +314,8 @@ void Sound::blasterStop(int16 fadeLength, SoundDesc *sndDesc) {
if (!_blaster)
return;
+ debugC(1, kDebugSound, "SoundBlaster: Stopping playback");
+
_blaster->stopSound(fadeLength, sndDesc);
}
@@ -293,6 +324,9 @@ void Sound::blasterPlayComposition(int16 *composition, int16 freqVal,
if (!_blaster)
return;
+ debugC(1, kDebugSound, "SoundBlaster: Playing composition (%d, %d)",
+ freqVal, sndCount);
+
blasterWaitEndPlay();
_blaster->stopComposition();
@@ -306,6 +340,8 @@ void Sound::blasterStopComposition() {
if (!_blaster)
return;
+ debugC(1, kDebugSound, "SoundBlaster: Stopping composition");
+
_blaster->stopComposition();
}
@@ -327,6 +363,8 @@ void Sound::blasterWaitEndPlay(bool interruptible, bool stopComp) {
if (!_blaster)
return;
+ debugC(1, kDebugSound, "SoundBlaster: Waiting for playback to end");
+
if (stopComp)
_blaster->endComposition();
@@ -345,6 +383,8 @@ void Sound::cdLoadLIC(const char *fname) {
if (!_cdrom)
return;
+ debugC(1, kDebugSound, "CDROM: Loading LIC \"%s\"", fname);
+
int handle = _vm->_dataIO->openData(fname);
if (handle == -1)
@@ -366,6 +406,8 @@ void Sound::cdUnloadLIC() {
if (!_cdrom)
return;
+ debugC(1, kDebugSound, "CDROM: Unloading LIC");
+
_cdrom->freeLICBuffer();
}
@@ -400,6 +442,9 @@ void Sound::cdPlayBgMusic() {
for (int i = 0; i < ARRAYSIZE(tracks); i++)
if (!scumm_stricmp(_vm->_game->_curTotFile, tracks[i][0])) {
+ debugC(1, kDebugSound, "CDROM: Playing background music \"%s\" (\"%s\")",
+ tracks[i][1], _vm->_game->_curTotFile);
+
_cdrom->startTrack(tracks[i][1]);
break;
}
@@ -422,6 +467,9 @@ void Sound::cdPlayMultMusic() {
int language = _vm->_global->_language <= 4 ? _vm->_global->_language : 2;
for (int i = 0; i < ARRAYSIZE(tracks); i++)
if (!scumm_stricmp(_vm->_game->_curTotFile, tracks[i][0])) {
+ debugC(1, kDebugSound, "CDROM: Playing mult music \"%s\" (\"%s\")",
+ tracks[i][language + 1], _vm->_game->_curTotFile);
+
_cdrom->startTrack(tracks[i][language + 1]);
break;
}
@@ -431,6 +479,7 @@ void Sound::cdPlay(const char *trackName) {
if (!_cdrom)
return;
+ debugC(1, kDebugSound, "CDROM: Playing track \"%s\"", trackName);
_cdrom->startTrack(trackName);
}
@@ -438,6 +487,7 @@ void Sound::cdStop() {
if (!_cdrom)
return;
+ debugC(1, kDebugSound, "CDROM: Stopping playback");
_cdrom->stopPlaying();
}
@@ -473,6 +523,8 @@ void Sound::bgPlay(const char *base, int count) {
if (!_bgatmos)
return;
+ debugC(1, kDebugSound, "BackgroundAtmosphere: Playing \"%s\" (%d)", base, count);
+
_bgatmos->stop();
_bgatmos->queueClear();
@@ -495,6 +547,8 @@ void Sound::bgStop() {
if (!_bgatmos)
return;
+ debugC(1, kDebugSound, "BackgroundAtmosphere: Stopping playback");
+
_bgatmos->stop();
_bgatmos->queueClear();
}
@@ -510,6 +564,8 @@ void Sound::bgShade() {
if (!_bgatmos)
return;
+ debugC(1, kDebugSound, "BackgroundAtmosphere: Shading playback");
+
_bgatmos->shade();
}
@@ -517,6 +573,8 @@ void Sound::bgUnshade() {
if (!_bgatmos)
return;
+ debugC(1, kDebugSound, "BackgroundAtmosphere: Unshading playback");
+
_bgatmos->unshade();
}
diff --git a/engines/gob/video.cpp b/engines/gob/video.cpp
index 3034a38079..453613d1ae 100644
--- a/engines/gob/video.cpp
+++ b/engines/gob/video.cpp
@@ -86,10 +86,14 @@ void SurfaceDesc::swap(SurfaceDesc &surf) {
Video::Video(GobEngine *vm) : _vm(vm) {
_doRangeClamp = false;
_videoDriver = 0;
+
_surfWidth = 320;
_surfHeight = 200;
+
_scrollOffsetX = 0;
_scrollOffsetY = 0;
+
+ _splitSurf = 0;
_splitHeight1 = 200;
_splitHeight2 = 0;
_splitStart = 0;
@@ -178,13 +182,25 @@ void Video::retrace(bool mouse) {
int screenOffset = _scrollOffsetY * _surfWidth + _scrollOffsetX;
int screenX = _screenDeltaX;
int screenY = _screenDeltaY;
- int screenWidth = MIN<int>(_surfWidth, _vm->_width);
- int screenHeight = MIN<int>(_splitHeight1, _vm->_height - _splitHeight2 - _screenDeltaY);
+ int screenWidth = MIN<int>(_surfWidth - _scrollOffsetX, _vm->_width);
+ int screenHeight = MIN<int>(_surfHeight - _splitHeight2 - _scrollOffsetY, _vm->_height);
g_system->copyRectToScreen(_vm->_global->_primarySurfDesc->getVidMem() + screenOffset,
_surfWidth, screenX, screenY, screenWidth, screenHeight);
- if (_splitHeight2 > 0) {
+ if (_splitSurf) {
+
+ screenOffset = 0;
+ screenX = 0;
+ screenY = _vm->_height - _splitSurf->getHeight();
+ screenWidth = MIN<int>(_vm->_width, _splitSurf->getWidth());
+ screenHeight = _splitSurf->getHeight();
+
+ g_system->copyRectToScreen(_splitSurf->getVidMem() + screenOffset,
+ _splitSurf->getWidth(), screenX, screenY, screenWidth, screenHeight);
+
+ } else if (_splitHeight2 > 0) {
+
screenOffset = _splitStart * _surfWidth;
screenX = 0;
screenY = _vm->_height - _splitHeight2;
@@ -193,6 +209,7 @@ void Video::retrace(bool mouse) {
g_system->copyRectToScreen(_vm->_global->_primarySurfDesc->getVidMem() + screenOffset,
_surfWidth, screenX, screenY, screenWidth, screenHeight);
+
}
g_system->updateScreen();
diff --git a/engines/gob/video.h b/engines/gob/video.h
index 1ab513205b..1338885588 100644
--- a/engines/gob/video.h
+++ b/engines/gob/video.h
@@ -98,13 +98,18 @@ public:
};
bool _doRangeClamp;
+
int16 _surfWidth;
int16 _surfHeight;
+
int16 _scrollOffsetX;
int16 _scrollOffsetY;
+
+ SurfaceDesc::Ptr _splitSurf;
int16 _splitHeight1;
int16 _splitHeight2;
int16 _splitStart;
+
int16 _screenDeltaX;
int16 _screenDeltaY;
diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp
index c435136b75..4a337d48b4 100644
--- a/engines/gob/videoplayer.cpp
+++ b/engines/gob/videoplayer.cpp
@@ -348,15 +348,30 @@ int VideoPlayer::slotOpen(const char *videoFile, Type which) {
video->getVideo()->setVideoMemory();
video->getVideo()->enableSound(*_vm->_mixer);
- _videoSlots.push_back(video);
+ int slot = getNextFreeSlot();
+
+ _videoSlots[slot] = video;
WRITE_VAR(7, video->getVideo()->getFramesCount());
- return _videoSlots.size() - 1;
+ return slot;
+}
+
+int VideoPlayer::getNextFreeSlot() {
+ uint slot;
+
+ for (slot = 0; slot < _videoSlots.size(); slot++)
+ if (!_videoSlots[slot])
+ break;
+
+ if (slot == _videoSlots.size())
+ _videoSlots.push_back(0);
+
+ return slot;
}
void VideoPlayer::slotPlay(int slot, int16 frame) {
- if ((slot < 0) || (((uint) slot) >= _videoSlots.size()))
+ if ((slot < 0) || (((uint) slot) >= _videoSlots.size()) || !_videoSlots[slot])
return;
CoktelVideo &video = *(_videoSlots[slot]->getVideo());
@@ -377,18 +392,18 @@ void VideoPlayer::slotPlay(int slot, int16 frame) {
}
void VideoPlayer::slotClose(int slot) {
- if ((slot < 0) || (((uint) slot) >= _videoSlots.size()))
+ if ((slot < 0) || (((uint) slot) >= _videoSlots.size()) || !_videoSlots[slot])
return;
delete _videoSlots[slot];
- _videoSlots.remove_at(slot);
+ _videoSlots[slot] = 0;
}
void VideoPlayer::slotCopyFrame(int slot, byte *dest,
uint16 left, uint16 top, uint16 width, uint16 height,
uint16 x, uint16 y, uint16 pitch, int16 transp) {
- if ((slot < 0) || (((uint) slot) >= _videoSlots.size()))
+ if ((slot < 0) || (((uint) slot) >= _videoSlots.size()) || !_videoSlots[slot])
return;
_videoSlots[slot]->getVideo()->copyCurrentFrame(dest,
@@ -396,14 +411,14 @@ void VideoPlayer::slotCopyFrame(int slot, byte *dest,
}
void VideoPlayer::slotCopyPalette(int slot, int16 palStart, int16 palEnd) {
- if ((slot < 0) || (((uint) slot) >= _videoSlots.size()))
+ if ((slot < 0) || (((uint) slot) >= _videoSlots.size()) || !_videoSlots[slot])
return;
copyPalette(*(_videoSlots[slot]->getVideo()), palStart, palEnd);
}
void VideoPlayer::slotWaitEndFrame(int slot, bool onlySound) {
- if ((slot < 0) || (((uint) slot) >= _videoSlots.size()))
+ if ((slot < 0) || (((uint) slot) >= _videoSlots.size()) || !_videoSlots[slot])
return;
CoktelVideo &video = *(_videoSlots[slot]->getVideo());
@@ -413,7 +428,7 @@ void VideoPlayer::slotWaitEndFrame(int slot, bool onlySound) {
}
bool VideoPlayer::slotIsOpen(int slot) const {
- if ((slot >= 0) && (((uint) slot) < _videoSlots.size()))
+ if ((slot >= 0) && (((uint) slot) < _videoSlots.size()) && _videoSlots[slot])
return true;
return false;
@@ -423,7 +438,7 @@ const VideoPlayer::Video *VideoPlayer::getVideoBySlot(int slot) const {
if (slot < 0) {
if (_primaryVideo->isOpen())
return _primaryVideo;
- } else if (((uint) slot) < _videoSlots.size())
+ } else if (((uint) slot) < _videoSlots.size() && _videoSlots[slot])
return _videoSlots[slot];
return 0;
@@ -527,7 +542,7 @@ bool VideoPlayer::doPlay(int16 frame, int16 breakKey,
_vm->_draw->_noInvalidated = true;
}
- if (state.flags & CoktelVideo::kStatePalette) {
+ if ((state.flags & CoktelVideo::kStatePalette) && (palCmd > 1)) {
copyPalette(*(_primaryVideo->getVideo()), palStart, palEnd);
if (!_backSurf)
@@ -587,20 +602,19 @@ void VideoPlayer::writeVideoInfo(const char *videoFile, int16 varX, int16 varY,
if (primaryOpen(videoFile)) {
int16 x, y, width, height;
- if ((VAR_OFFSET(varX) != 0xFFFFFFFF) ||
- !_primaryVideo->getVideo()->getAnchor(1, 2, x, y, width, height)) {
+ x = _primaryVideo->getVideo()->getX();
+ y = _primaryVideo->getVideo()->getY();
+ width = _primaryVideo->getVideo()->getWidth();
+ height = _primaryVideo->getVideo()->getHeight();
- x = _primaryVideo->getVideo()->getX();
- y = _primaryVideo->getVideo()->getY();
- width = _primaryVideo->getVideo()->getWidth();
- height = _primaryVideo->getVideo()->getHeight();
- }
+ if (VAR_OFFSET(varX) == 0xFFFFFFFF)
+ _primaryVideo->getVideo()->getAnchor(1, 2, x, y, width, height);
WRITE_VAR_OFFSET(varX, x);
WRITE_VAR_OFFSET(varY, y);
WRITE_VAR_OFFSET(varFrames, _primaryVideo->getVideo()->getFramesCount());
WRITE_VAR_OFFSET(varWidth, width);
- WRITE_VAR_OFFSET(varHeight, height);
+ WRITE_VARO_UINT16(varHeight & 0xFFFFFFFC, height);
primaryClose();
} else {
@@ -619,4 +633,13 @@ void VideoPlayer::evalBgShading(CoktelVideo &video) {
_vm->_sound->bgUnshade();
}
+void VideoPlayer::notifyPaused(uint32 duration) {
+ if (_primaryVideo->isOpen())
+ _primaryVideo->getVideo()->notifyPaused(duration);
+
+ for (uint i = 0; i < _videoSlots.size(); i++)
+ if (_videoSlots[i] && _videoSlots[i]->isOpen())
+ _videoSlots[i]->getVideo()->notifyPaused(duration);
+}
+
} // End of namespace Gob
diff --git a/engines/gob/videoplayer.h b/engines/gob/videoplayer.h
index 29531f7ce2..b7aa7313b0 100644
--- a/engines/gob/videoplayer.h
+++ b/engines/gob/videoplayer.h
@@ -83,6 +83,8 @@ public:
void writeVideoInfo(const char *videoFile, int16 varX, int16 varY,
int16 varFrames, int16 varWidth, int16 varHeight);
+ void notifyPaused(uint32 duration);
+
private:
class Video {
public:
@@ -128,6 +130,8 @@ private:
const Video *getVideoBySlot(int slot = -1) const;
+ int getNextFreeSlot();
+
void copyPalette(CoktelVideo &video, int16 palStart = -1, int16 palEnd = -1);
bool doPlay(int16 frame, int16 breakKey,
uint16 palCmd, int16 palStart, int16 palEnd,