diff options
Diffstat (limited to 'engines/gob')
-rw-r--r-- | engines/gob/coktelvideo.cpp | 32 | ||||
-rw-r--r-- | engines/gob/coktelvideo.h | 15 | ||||
-rw-r--r-- | engines/gob/detection.cpp | 65 | ||||
-rw-r--r-- | engines/gob/draw_v2.cpp | 28 | ||||
-rw-r--r-- | engines/gob/driver_vga.cpp | 19 | ||||
-rw-r--r-- | engines/gob/game_v2.cpp | 12 | ||||
-rw-r--r-- | engines/gob/gob.cpp | 22 | ||||
-rw-r--r-- | engines/gob/gob.h | 8 | ||||
-rw-r--r-- | engines/gob/inter.cpp | 4 | ||||
-rw-r--r-- | engines/gob/inter.h | 1 | ||||
-rw-r--r-- | engines/gob/inter_v2.cpp | 85 | ||||
-rw-r--r-- | engines/gob/inter_v4.cpp | 103 | ||||
-rw-r--r-- | engines/gob/map_v4.cpp | 2 | ||||
-rw-r--r-- | engines/gob/mult_v2.cpp | 4 | ||||
-rw-r--r-- | engines/gob/scenery.cpp | 159 | ||||
-rw-r--r-- | engines/gob/scenery.h | 21 | ||||
-rw-r--r-- | engines/gob/sound/adlib.cpp | 2 | ||||
-rw-r--r-- | engines/gob/sound/cdrom.cpp | 6 | ||||
-rw-r--r-- | engines/gob/sound/sound.cpp | 60 | ||||
-rw-r--r-- | engines/gob/video.cpp | 23 | ||||
-rw-r--r-- | engines/gob/video.h | 5 | ||||
-rw-r--r-- | engines/gob/videoplayer.cpp | 61 | ||||
-rw-r--r-- | engines/gob/videoplayer.h | 4 |
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 ¶ms) { 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 ¶ms) { 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 ¶ms) { } 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, |