From 89087b18c79885680ad1f0d17d36975ea7b06f13 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 22 Jan 2011 13:01:10 +0000 Subject: SCI21: Allow the game scripts to sync robot videos, like in SSCI. Also, references of the SciEngine class to itself via g_sci have been removed svn-id: r55422 --- engines/sci/engine/kgraphics.cpp | 15 +++---- engines/sci/graphics/frameout.cpp | 4 ++ engines/sci/graphics/paint32.cpp | 8 +++- engines/sci/graphics/robot.cpp | 92 ++++++++++++++++++++++----------------- engines/sci/graphics/robot.h | 13 +++++- engines/sci/sci.cpp | 32 ++++++++------ engines/sci/sci.h | 2 + 7 files changed, 99 insertions(+), 67 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 855c6a25c0..0065c7ae74 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1398,6 +1398,7 @@ reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) { reg_t kRobot(EngineState *s, int argc, reg_t *argv) { int16 subop = argv[0].toUint16(); + GfxRobot *robot = g_sci->_gfxRobot; switch (subop) { case 0: { // init @@ -1407,10 +1408,7 @@ reg_t kRobot(EngineState *s, int argc, reg_t *argv) { int16 x = argv[4].toUint16(); int16 y = argv[5].toUint16(); warning("kRobot(init), id %d, obj %04x:%04x, flag %d, x=%d, y=%d", id, PRINT_REG(obj), flag, x, y); - GfxRobot *test = new GfxRobot(g_sci->getResMan(), g_sci->_gfxScreen, g_sci->_gfxPalette, id); - test->draw(x,y); - delete test; - + robot->init(id, x, y); } break; case 1: // LSL6 hires (startup) @@ -1422,11 +1420,10 @@ reg_t kRobot(EngineState *s, int argc, reg_t *argv) { } break; case 8: // sync - //warning("kRobot(sync), obj %04x:%04x", PRINT_REG(argv[1])); - // HACK: Make robots return immediately for now, - // otherwise they just hang for a while. - // TODO: Replace with proper robot functionality. - writeSelector(s->_segMan, argv[1], SELECTOR(signal), SIGNAL_REG); + robot->drawNextFrame(); + // Sync + if (robot->getCurFrame() == robot->getFrameCount()) + writeSelector(s->_segMan, argv[1], SELECTOR(signal), SIGNAL_REG); break; default: warning("kRobot(%d)", subop); diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 01b17ae4f8..ced9c00683 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -40,6 +40,7 @@ #include "sci/graphics/paint32.h" #include "sci/graphics/palette.h" #include "sci/graphics/picture.h" +#include "sci/graphics/robot.h" #include "sci/graphics/frameout.h" namespace Sci { @@ -338,6 +339,9 @@ static int16 GetLongest(const char *text, int16 maxWidth, GfxFont *font) { } void GfxFrameout::kernelFrameout() { + if (g_sci->_gfxRobot->isPlaying()) + return; + _palette->palVaryUpdate(); for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); it++) { diff --git a/engines/sci/graphics/paint32.cpp b/engines/sci/graphics/paint32.cpp index a2cf1c73ad..0167593084 100644 --- a/engines/sci/graphics/paint32.cpp +++ b/engines/sci/graphics/paint32.cpp @@ -25,6 +25,7 @@ #include "common/util.h" #include "common/stack.h" + #include "graphics/primitives.h" #include "sci/sci.h" @@ -81,8 +82,11 @@ void GfxPaint32::kernelGraphDrawLine(Common::Point startPoint, Common::Point end } void GfxPaint32::debugDrawRobot(GuiResourceId robotId) { - GfxRobot *test = new GfxRobot(g_sci->getResMan(), _screen, _palette, robotId); - test->draw(0,0); + GfxRobot *test = new GfxRobot(g_sci->getResMan(), _screen, _palette); + test->init(robotId, 0, 0); + while (test->getCurFrame() + 1 < test->getFrameCount()) { + test->drawNextFrame(); + } delete test; } diff --git a/engines/sci/graphics/robot.cpp b/engines/sci/graphics/robot.cpp index 768eba2214..853e111daa 100644 --- a/engines/sci/graphics/robot.cpp +++ b/engines/sci/graphics/robot.cpp @@ -57,10 +57,10 @@ namespace Sci { // around the screen and go behind other objects. (...) #ifdef ENABLE_SCI32 -GfxRobot::GfxRobot(ResourceManager *resMan, GfxScreen *screen, GfxPalette *palette, GuiResourceId resourceId) - : _resMan(resMan), _screen(screen), _palette(palette), _resourceId(resourceId) { - assert(resourceId != -1); - initData(resourceId); +GfxRobot::GfxRobot(ResourceManager *resMan, GfxScreen *screen, GfxPalette *palette) + : _resMan(resMan), _screen(screen), _palette(palette) { + _resourceId = -1; + _x = _y = 0; } GfxRobot::~GfxRobot() { @@ -70,11 +70,17 @@ GfxRobot::~GfxRobot() { delete[] _audioLen; } -void GfxRobot::initData(GuiResourceId resourceId) { +void GfxRobot::init(GuiResourceId resourceId, uint16 x, uint16 y) { char fileName[10]; uint32 fileSize; - sprintf(fileName, "%d.rbt", resourceId); + // resourceId = 1305; // debug + + _resourceId = resourceId; + _x = x; + _y = y; + _curFrame = 0; + sprintf(fileName, "%d.rbt", _resourceId); Common::File robotFile; if (robotFile.open(fileName)) { @@ -98,28 +104,22 @@ void GfxRobot::initData(GuiResourceId resourceId) { _hasSound = (_resourceData[25] != 0); _palOffset = 60; - if (_hasSound) + + // Some robot files have sound, which doesn't start from frame 0 + // (e.g. Phantasmagoria, robot 1305) + if (_hasSound && _audioSize > 14) _palOffset += READ_LE_UINT32(_resourceData + 60) + 14; getFrameOffsets(); assert(_imageStart[_frameCount] == fileSize); + setPalette(); + debug("Robot %d, %d frames, sound: %s\n", resourceId, _frameCount, _hasSound ? "yes" : "no"); } -void GfxRobot::draw(int x, int y) { - - return; // TODO: Remove once done - // Play the audio of the robot file (for debugging) -#if 0 - if (_hasSound) { - Audio::SoundHandle _audioHandle; - Audio::AudioStream *audioStream = g_sci->_audio->getRobotAudioStream(_resourceData); - g_system->getMixer()->playStream(Audio::Mixer::kSpeechSoundType, &_audioHandle, audioStream); - } -#endif - - byte *paletteData = _hasSound ? +void GfxRobot::setPalette() { + byte *paletteData = (_hasSound && _audioSize > 14) ? _resourceData + 60 + 14 + _audioSize : _resourceData + 60; uint16 paletteSize = READ_LE_UINT16(_resourceData + 16); @@ -127,7 +127,6 @@ void GfxRobot::draw(int x, int y) { Palette resourcePal; byte robotPal[256 * 4]; - byte savePal[256 * 4]; int startIndex = READ_LE_UINT16(paletteData + 25); int colorCount = READ_LE_UINT16(paletteData + 29); @@ -136,13 +135,13 @@ void GfxRobot::draw(int x, int y) { _palette->createFromData(paletteData, paletteSize, &resourcePal); for (int i = 0; i < 256; ++i) { - savePal[i * 4 + 0] = _palette->_sysPalette.colors[i].r; - savePal[i * 4 + 1] = _palette->_sysPalette.colors[i].g; - savePal[i * 4 + 2] = _palette->_sysPalette.colors[i].b; - savePal[i * 4 + 3] = 0; + _savedPal[i * 4 + 0] = _palette->_sysPalette.colors[i].r; + _savedPal[i * 4 + 1] = _palette->_sysPalette.colors[i].g; + _savedPal[i * 4 + 2] = _palette->_sysPalette.colors[i].b; + _savedPal[i * 4 + 3] = 0; } - memcpy(robotPal, savePal, sizeof(savePal)); + memcpy(robotPal, _savedPal, sizeof(_savedPal)); for (int i = 0; i < colorCount; ++i) { int index = i + startIndex; @@ -153,19 +152,34 @@ void GfxRobot::draw(int x, int y) { } g_system->setPalette(robotPal, 0, 256); +} - for (int i = 0; i < _frameCount; ++i) { - int width, height; - - byte *pixels = assembleVideoFrame(i); - getFrameDimensions(i, width, height); - g_system->copyRectToScreen(pixels, width, x, y, width, height * getFrameScale(i) / 100); - g_system->updateScreen(); - g_system->delayMillis(100); - delete[] pixels; +void GfxRobot::drawNextFrame() { + // Play the audio of the robot file (for debugging) +#if 0 + if (_hasSound) { + Audio::SoundHandle _audioHandle; + Audio::AudioStream *audioStream = g_sci->_audio->getRobotAudioStream(_resourceData); + g_system->getMixer()->playStream(Audio::Mixer::kSpeechSoundType, &_audioHandle, audioStream); } +#endif + + int width, height; + + byte *pixels = assembleVideoFrame(_curFrame); + getFrameDimensions(_curFrame, width, height); + g_system->copyRectToScreen(pixels, width, _x, _y, width, height * getFrameScale(_curFrame) / 100); + g_system->updateScreen(); + g_system->delayMillis(100); + delete[] pixels; - g_system->setPalette(savePal, 0, 256); + _curFrame++; + + if (_curFrame == _frameCount) { + // End of robot video, restore palette + g_system->setPalette(_savedPal, 0, 256); + _resourceId = -1; + } } void GfxRobot::getFrameOffsets() { @@ -183,7 +197,7 @@ void GfxRobot::getFrameOffsets() { if (frameDataOffset & 0x7ff) frameDataOffset = (frameDataOffset & ~0x7ff)+0x800; - _imageStart = new uint32[_frameCount+1]; + _imageStart = new uint32[_frameCount + 1]; _audioStart = new uint32[_frameCount]; _audioLen = new uint32[_frameCount]; @@ -276,9 +290,7 @@ void GfxRobot::getFrameRect(int frame, Common::Rect &rect) { int GfxRobot::getFrameScale(int frame) { byte *videoData = _resourceData + _imageStart[frame]; - byte percentage = videoData[3]; - - return percentage; + return videoData[3]; } #endif diff --git a/engines/sci/graphics/robot.h b/engines/sci/graphics/robot.h index fc5f498862..d794c4ba60 100644 --- a/engines/sci/graphics/robot.h +++ b/engines/sci/graphics/robot.h @@ -33,10 +33,14 @@ namespace Sci { #ifdef ENABLE_SCI32 class GfxRobot { public: - GfxRobot(ResourceManager *resMan, GfxScreen *screen, GfxPalette *palette, GuiResourceId resourceId); + GfxRobot(ResourceManager *resMan, GfxScreen *screen, GfxPalette *palette); ~GfxRobot(); - void draw(int x, int y); + void init(GuiResourceId resourceId, uint16 x, uint16 y); + void drawNextFrame(); + uint16 getCurFrame() { return _curFrame; } + uint16 getFrameCount() { return _frameCount; } + bool isPlaying() { return _resourceId != -1; } private: void initData(GuiResourceId resourceId); @@ -45,6 +49,7 @@ private: void getFrameDimensions(int frame, int &width, int &height); void getFrameRect(int frame, Common::Rect &rect); // Not sure what to use this for yet int getFrameScale(int frame); // Scale factor (multiplied by 100). More like custom height, but why use a percentage for it? + void setPalette(); ResourceManager *_resMan; GfxScreen *_screen; @@ -52,7 +57,10 @@ private: GuiResourceId _resourceId; byte *_resourceData; + byte _savedPal[256 * 4]; + uint16 _x; + uint16 _y; //uint16 _width; //uint16 _height; uint16 _frameCount; @@ -63,6 +71,7 @@ private: uint32 *_imageStart; uint32 *_audioStart; uint32 *_audioLen; + uint16 _curFrame; }; #endif diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 3fc982c28a..92b4fc4e68 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -66,6 +66,7 @@ #include "sci/graphics/transitions.h" #ifdef ENABLE_SCI32 +#include "sci/graphics/robot.h" #include "sci/graphics/frameout.h" #endif @@ -145,6 +146,7 @@ SciEngine::~SciEngine() { DebugMan.clearAllDebugChannels(); #ifdef ENABLE_SCI32 + delete _gfxRobot; delete _gfxFrameout; #endif delete _gfxMenu; @@ -585,6 +587,7 @@ void SciEngine::initGraphics() { _gfxText16 = 0; _gfxTransitions = 0; #ifdef ENABLE_SCI32 + _gfxRobot = 0; _gfxFrameout = 0; _gfxPaint32 = 0; #endif @@ -610,24 +613,25 @@ void SciEngine::initGraphics() { // SCI32 graphic objects creation _gfxCoordAdjuster = new GfxCoordAdjuster32(_gamestate->_segMan); _gfxCursor->init(_gfxCoordAdjuster, _eventMan); - _gfxCompare = new GfxCompare(_gamestate->_segMan, g_sci->getKernel(), _gfxCache, _gfxScreen, _gfxCoordAdjuster); - _gfxPaint32 = new GfxPaint32(g_sci->getResMan(), _gamestate->_segMan, g_sci->getKernel(), _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette); + _gfxCompare = new GfxCompare(_gamestate->_segMan, _kernel, _gfxCache, _gfxScreen, _gfxCoordAdjuster); + _gfxPaint32 = new GfxPaint32(_resMan, _gamestate->_segMan, _kernel, _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette); _gfxPaint = _gfxPaint32; - _gfxFrameout = new GfxFrameout(_gamestate->_segMan, g_sci->getResMan(), _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette, _gfxPaint32); + _gfxRobot = new GfxRobot(_resMan, _gfxScreen, _gfxPalette); + _gfxFrameout = new GfxFrameout(_gamestate->_segMan, _resMan, _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette, _gfxPaint32); } else { #endif // SCI0-SCI1.1 graphic objects creation _gfxPorts = new GfxPorts(_gamestate->_segMan, _gfxScreen); _gfxCoordAdjuster = new GfxCoordAdjuster16(_gfxPorts); - _gfxCursor->init(_gfxCoordAdjuster, g_sci->getEventManager()); - _gfxCompare = new GfxCompare(_gamestate->_segMan, g_sci->getKernel(), _gfxCache, _gfxScreen, _gfxCoordAdjuster); - _gfxTransitions = new GfxTransitions(_gfxScreen, _gfxPalette, g_sci->getResMan()->isVGA()); - _gfxPaint16 = new GfxPaint16(g_sci->getResMan(), _gamestate->_segMan, g_sci->getKernel(), _gfxCache, _gfxPorts, _gfxCoordAdjuster, _gfxScreen, _gfxPalette, _gfxTransitions, _audio); + _gfxCursor->init(_gfxCoordAdjuster, _eventMan); + _gfxCompare = new GfxCompare(_gamestate->_segMan, _kernel, _gfxCache, _gfxScreen, _gfxCoordAdjuster); + _gfxTransitions = new GfxTransitions(_gfxScreen, _gfxPalette, _resMan->isVGA()); + _gfxPaint16 = new GfxPaint16(_resMan, _gamestate->_segMan, _kernel, _gfxCache, _gfxPorts, _gfxCoordAdjuster, _gfxScreen, _gfxPalette, _gfxTransitions, _audio); _gfxPaint = _gfxPaint16; _gfxAnimate = new GfxAnimate(_gamestate, _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen, _gfxPalette, _gfxCursor, _gfxTransitions); - _gfxText16 = new GfxText16(g_sci->getResMan(), _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen); + _gfxText16 = new GfxText16(_resMan, _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen); _gfxControls = new GfxControls(_gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen); - _gfxMenu = new GfxMenu(g_sci->getEventManager(), _gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen, _gfxCursor); + _gfxMenu = new GfxMenu(_eventMan, _gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen, _gfxCursor); _gfxMenu->reset(); #ifdef ENABLE_SCI32 @@ -663,14 +667,14 @@ void SciEngine::runGame() { if (DebugMan.isDebugChannelEnabled(kDebugLevelOnStartup)) _console->attach(); - g_sci->getEngineState()->_syncedAudioOptions = false; + _gamestate->_syncedAudioOptions = false; do { _gamestate->_executionStackPosChanged = false; run_vm(_gamestate); exitGame(); - g_sci->getEngineState()->_syncedAudioOptions = true; + _gamestate->_syncedAudioOptions = true; if (_gamestate->abortScriptProcessing == kAbortRestartGame) { _gamestate->_segMan->resetSegMan(); @@ -701,7 +705,7 @@ void SciEngine::exitGame() { if (_gamestate->abortScriptProcessing != kAbortLoadGame) { _gamestate->_executionStack.clear(); _audio->stopAllAudio(); - g_sci->_soundCmd->clearPlayList(); + _soundCmd->clearPlayList(); } // TODO Free parser segment here @@ -809,9 +813,9 @@ void SciEngine::syncSoundSettings() { int soundVolumeMusic = (mute ? 0 : ConfMan.getInt("music_volume")); - if (_gamestate && g_sci->_soundCmd) { + if (_gamestate && _soundCmd) { int vol = (soundVolumeMusic + 1) * MUSIC_MASTERVOLUME_MAX / Audio::Mixer::kMaxMixerVolume; - g_sci->_soundCmd->setMasterVolume(vol); + _soundCmd->setMasterVolume(vol); } } diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 91ab491945..1120154e8c 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -77,6 +77,7 @@ class GfxTransitions; #ifdef ENABLE_SCI32 class SciGui32; +class GfxRobot; class GfxFrameout; #endif @@ -312,6 +313,7 @@ public: GfxMacIconBar *_gfxMacIconBar; // Mac Icon Bar manager #ifdef ENABLE_SCI32 + GfxRobot *_gfxRobot; GfxFrameout *_gfxFrameout; // kFrameout and the like for 32-bit gfx #endif -- cgit v1.2.3