diff options
Diffstat (limited to 'engines/director')
-rw-r--r-- | engines/director/cast.h | 21 | ||||
-rw-r--r-- | engines/director/director.cpp | 27 | ||||
-rw-r--r-- | engines/director/director.h | 13 | ||||
-rw-r--r-- | engines/director/events.cpp | 71 | ||||
-rw-r--r-- | engines/director/frame.cpp | 150 | ||||
-rw-r--r-- | engines/director/frame.h | 3 | ||||
-rw-r--r-- | engines/director/graphics.cpp | 233 | ||||
-rw-r--r-- | engines/director/lingo/lingo-builtins.cpp | 34 | ||||
-rw-r--r-- | engines/director/lingo/lingo-code.cpp | 12 | ||||
-rw-r--r-- | engines/director/lingo/lingo-the.cpp | 50 | ||||
-rw-r--r-- | engines/director/lingo/lingo.cpp | 15 | ||||
-rw-r--r-- | engines/director/resource.cpp | 42 | ||||
-rw-r--r-- | engines/director/score.cpp | 258 | ||||
-rw-r--r-- | engines/director/score.h | 25 | ||||
-rw-r--r-- | engines/director/sprite.cpp | 21 | ||||
-rw-r--r-- | engines/director/sprite.h | 9 | ||||
-rw-r--r-- | engines/director/util.cpp | 2 |
17 files changed, 636 insertions, 350 deletions
diff --git a/engines/director/cast.h b/engines/director/cast.h index 953c94c4c6..f304456e12 100644 --- a/engines/director/cast.h +++ b/engines/director/cast.h @@ -26,6 +26,7 @@ #include "common/rect.h" #include "common/substream.h" #include "director/archive.h" +#include "graphics/surface.h" namespace Director { @@ -44,16 +45,20 @@ enum CastType { kCastLingoScript = 11 }; -struct Cast { +class Cast { +public: CastType type; Common::Rect initialRect; Common::Rect boundingRect; Common::Array<Resource> children; + const Graphics::Surface *surface; + byte modified; }; -struct BitmapCast : Cast { +class BitmapCast : public Cast { +public: BitmapCast(Common::ReadStreamEndian &stream, uint16 version = 2); uint16 regX; @@ -72,7 +77,8 @@ enum ShapeType { kShapeLine }; -struct ShapeCast : Cast { +class ShapeCast : public Cast { +public: ShapeCast(Common::ReadStreamEndian &stream, uint16 version = 2); ShapeType shapeType; @@ -111,7 +117,8 @@ enum SizeType { kSizeLargest }; -struct TextCast : Cast { +class TextCast : public Cast { +public: TextCast(Common::ReadStreamEndian &stream, uint16 version = 2); SizeType borderSize; @@ -135,13 +142,15 @@ enum ButtonType { kTypeRadio }; -struct ButtonCast : TextCast { +class ButtonCast : public TextCast { +public: ButtonCast(Common::ReadStreamEndian &stream, uint16 version = 2); ButtonType buttonType; }; -struct ScriptCast : Cast { +class ScriptCast : public Cast { +public: ScriptCast(Common::ReadStreamEndian &stream, uint16 version = 2); uint32 id; diff --git a/engines/director/director.cpp b/engines/director/director.cpp index edea7ea591..70d5cf3c62 100644 --- a/engines/director/director.cpp +++ b/engines/director/director.cpp @@ -92,7 +92,10 @@ DirectorEngine::DirectorEngine(OSystem *syst, const DirectorGameDescription *gam _keyCode = 0; _machineType = 9; // Macintosh IIci _playbackPaused = false; - g_director->_skipFrameAdvance = false; + _skipFrameAdvance = false; + + _draggingSprite = false; + _draggingSpriteId = 0; } DirectorEngine::~DirectorEngine() { @@ -141,6 +144,8 @@ Common::Error DirectorEngine::run() { //_mainArchive = new RIFFArchive(); //_mainArchive->openFile("bookshelf_example.mmm"); + _currentScore = new Score(this); + if (getVersion() < 4) { if (getPlatform() == Common::kPlatformWindows) { _sharedCastFile = "SHARDCST.MMM"; @@ -155,7 +160,7 @@ Common::Error DirectorEngine::run() { loadInitialMovie(getEXEName()); - _currentScore = new Score(this, _mainArchive); + _currentScore->setArchive(_mainArchive); debug(0, "Score name %s", _currentScore->getMacName().c_str()); bool loop = true; @@ -176,8 +181,12 @@ Common::Error DirectorEngine::run() { _nextMovie.frameI = -1; } + debugC(1, kDebugEvents, "Starting playback of score '%s'", _currentScore->getMacName().c_str()); + _currentScore->startLoop(); + debugC(1, kDebugEvents, "Finished playback of score '%s'", _currentScore->getMacName().c_str()); + // If a loop was requested, do it if (!_nextMovie.movie.empty()) { _lingo->restartLingo(); @@ -192,8 +201,9 @@ Common::Error DirectorEngine::run() { return Common::kNoError; } - _currentScore = new Score(this, mov); - debug(0, "Score name %s", _currentScore->getMacName().c_str()); + _currentScore = new Score(this); + _currentScore->setArchive(mov); + debug(0, "Switching to score '%s'", _currentScore->getMacName().c_str()); _nextMovie.movie.clear(); loop = true; @@ -233,7 +243,8 @@ Common::HashMap<Common::String, Score *> *DirectorEngine::scanMovies(const Commo warning("name: %s", i->getName().c_str()); arc->openFile(i->getName()); - Score *sc = new Score(this, arc); + Score *sc = new Score(this); + sc->setArchive(arc); nameMap->setVal(sc->getMacName(), sc); debugC(2, kDebugLoading, "Movie name: \"%s\"", sc->getMacName().c_str()); @@ -243,11 +254,11 @@ Common::HashMap<Common::String, Score *> *DirectorEngine::scanMovies(const Commo return nameMap; } -Common::HashMap<int, Cast *> *DirectorEngine::getSharedCasts() { +Common::HashMap<int, CastType> *DirectorEngine::getSharedCastTypes() { if (_sharedScore) - return &_sharedScore->_casts; + return &_sharedScore->_castTypes; - return &_dummyCast; + return &_dummyCastType; } } // End of namespace Director diff --git a/engines/director/director.h b/engines/director/director.h index 2f0b65288f..3c3e2e947a 100644 --- a/engines/director/director.h +++ b/engines/director/director.h @@ -28,6 +28,7 @@ #include "common/hashmap.h" #include "engines/engine.h" +#include "director/cast.h" namespace Common { class MacResManager; @@ -50,7 +51,7 @@ struct DirectorGameDescription; class DirectorSound; class Lingo; class Score; -struct Cast; +class Cast; enum { kDebugLingoExec = 1 << 0, @@ -89,6 +90,7 @@ public: Archive *getMainArchive() const { return _mainArchive; } Lingo *getLingo() const { return _lingo; } Score *getCurrentScore() const { return _currentScore; } + Score *getSharedScore() const { return _sharedScore; } void setPalette(byte *palette, uint16 count); bool hasFeature(EngineFeature f) const; const byte *getPalette() const { return _currentPalette; } @@ -103,11 +105,12 @@ public: void cleanupMainArchive(); void processEvents(); // evetns.cpp + void setDraggedSprite(uint16 id); // events.cpp Common::HashMap<int, Common::SeekableSubReadStreamEndian *> *getSharedDIB() const { return _sharedDIB; } Common::HashMap<int, Common::SeekableSubReadStreamEndian *> *getSharedBMP() const { return _sharedBMP; } Common::HashMap<int, Common::SeekableSubReadStreamEndian *> *getSharedSTXT() const { return _sharedSTXT; } - Common::HashMap<int, Cast *> *getSharedCasts(); + Common::HashMap<int, CastType> *getSharedCastTypes(); Common::HashMap<Common::String, Score *> *_movies; @@ -159,7 +162,11 @@ private: Graphics::MacPatterns _director3QuickDrawPatterns; Common::String _sharedCastFile; - Common::HashMap<int, Cast *> _dummyCast; + Common::HashMap<int, CastType> _dummyCastType; + + bool _draggingSprite; + uint16 _draggingSpriteId; + Common::Point _draggingSpritePos; private: void testFontScaling(); diff --git a/engines/director/events.cpp b/engines/director/events.cpp index 613e83c352..e60af2244b 100644 --- a/engines/director/events.cpp +++ b/engines/director/events.cpp @@ -46,51 +46,62 @@ void DirectorEngine::processEvents() { uint endTime = g_system->getMillis() + 200; Score *sc = getCurrentScore(); - int currentFrame = sc->getCurrentFrame(); + Frame *currentFrame = sc->_frames[sc->getCurrentFrame()]; uint16 spriteId = 0; - // TODO: re-instate when we know which script to run. - //if (currentFrame > 0) - // _lingo->processEvent(kEventIdle, currentFrame - 1); + Common::Point pos; while (g_system->getMillis() < endTime) { while (g_system->getEventManager()->pollEvent(event)) { - if (event.type == Common::EVENT_QUIT) + switch (event.type) { + case Common::EVENT_QUIT: sc->_stopPlay = true; + break; - if (event.type == Common::EVENT_LBUTTONDOWN) { - Common::Point pos = g_system->getEventManager()->getMousePos(); + case Common::EVENT_LBUTTONDOWN: + pos = g_system->getEventManager()->getMousePos(); // D3 doesn't have both mouse up and down. // But we still want to know if the mouse is down for press effects. - spriteId = sc->_frames[currentFrame]->getSpriteIDFromPos(pos); + spriteId = currentFrame->getSpriteIDFromPos(pos); sc->_currentMouseDownSpriteId = spriteId; + debugC(3, kDebugEvents, "event: Button Down @(%d, %d), sprite id: %d", pos.x, pos.y, spriteId); + if (getVersion() > 3) { // TODO: check that this is the order of script execution! - _lingo->processEvent(kEventMouseDown, kCastScript, sc->_frames[currentFrame]->_sprites[spriteId]->_castId); - _lingo->processEvent(kEventMouseDown, kSpriteScript, sc->_frames[currentFrame]->_sprites[spriteId]->_scriptId); + _lingo->processEvent(kEventMouseDown, kCastScript, currentFrame->_sprites[spriteId]->_castId); + _lingo->processEvent(kEventMouseDown, kSpriteScript, currentFrame->_sprites[spriteId]->_scriptId); } - } - if (event.type == Common::EVENT_LBUTTONUP) { - Common::Point pos = g_system->getEventManager()->getMousePos(); + if (currentFrame->_sprites[spriteId]->_moveable) { + warning("Moveable"); + } + break; + + case Common::EVENT_LBUTTONUP: + pos = g_system->getEventManager()->getMousePos(); + + spriteId = currentFrame->getSpriteIDFromPos(pos); + + debugC(3, kDebugEvents, "event: Button Up @(%d, %d), sprite id: %d", pos.x, pos.y, spriteId); - spriteId = sc->_frames[currentFrame]->getSpriteIDFromPos(pos); if (getVersion() > 3) { // TODO: check that this is the order of script execution! - _lingo->processEvent(kEventMouseUp, kCastScript, sc->_frames[currentFrame]->_sprites[spriteId]->_castId); - _lingo->processEvent(kEventMouseUp, kSpriteScript, sc->_frames[currentFrame]->_sprites[spriteId]->_scriptId); + _lingo->processEvent(kEventMouseUp, kCastScript, currentFrame->_sprites[spriteId]->_castId); + _lingo->processEvent(kEventMouseUp, kSpriteScript, currentFrame->_sprites[spriteId]->_scriptId); } else { // Frame script overrides sprite script - if (!sc->_frames[currentFrame]->_sprites[spriteId]->_scriptId) - _lingo->processEvent(kEventMouseUp, kSpriteScript, sc->_frames[currentFrame]->_sprites[spriteId]->_castId + 1024); + if (!currentFrame->_sprites[spriteId]->_scriptId) + _lingo->processEvent(kEventMouseUp, kSpriteScript, currentFrame->_sprites[spriteId]->_castId + 1024); else - _lingo->processEvent(kEventMouseUp, kFrameScript, sc->_frames[currentFrame]->_sprites[spriteId]->_scriptId); + _lingo->processEvent(kEventMouseUp, kFrameScript, currentFrame->_sprites[spriteId]->_scriptId); } - } - if (event.type == Common::EVENT_KEYDOWN) { + sc->_currentMouseDownSpriteId = 0; + break; + + case Common::EVENT_KEYDOWN: _keyCode = event.kbd.keycode; _key = (unsigned char)(event.kbd.ascii & 0xff); @@ -111,14 +122,28 @@ void DirectorEngine::processEvents() { warning("Keycode: %d", _keyCode); } - // TODO: is movie script correct? Can this be elsewhere? - _lingo->processEvent(kEventKeyDown, kMovieScript, 0); + _lingo->processEvent(kEventKeyDown, kGlobalScript, 0); + break; + + default: + break; } } g_system->updateScreen(); g_system->delayMillis(10); + + if (sc->getCurrentFrame() > 0) + _lingo->processEvent(kEventIdle, kFrameScript, sc->getCurrentFrame()); } } +void DirectorEngine::setDraggedSprite(uint16 id) { + _draggingSprite = true; + _draggingSpriteId = id; + _draggingSpritePos = g_system->getEventManager()->getMousePos(); + + warning("STUB: DirectorEngine::setDraggedSprite(%d)", id); +} + } // End of namespace Director diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp index 7690a47893..92aa851d06 100644 --- a/engines/director/frame.cpp +++ b/engines/director/frame.cpp @@ -36,6 +36,7 @@ #include "director/score.h" #include "director/sprite.h" #include "director/util.h" +#include "director/lingo/lingo.h" namespace Director { @@ -221,10 +222,14 @@ void Frame::readChannels(Common::ReadStreamEndian *stream) { sprite._unk3 = stream->readUint32(); } - debugC(kDebugLoading, 8, "%03d(%d)[%x,%x,%04x,%d/%d/%d/%d/%d] script:%d", - sprite._castId, sprite._enabled, sprite._x1, sprite._x2, sprite._flags, - sprite._startPoint.x, sprite._startPoint.y, sprite._width, sprite._height, - sprite._lineSize, sprite._scriptId); + if (sprite._castId) { + debugC(kDebugLoading, 4, "CH: %-3d castId: %03d(%s) (e:%d) [%x,%x, flags:%04x, %dx%d@%d,%d linesize: %d] script: %d", + i + 1, sprite._castId, numToCastNum(sprite._castId), sprite._enabled, sprite._x1, sprite._x2, sprite._flags, + sprite._width, sprite._height, sprite._startPoint.x, sprite._startPoint.y, + sprite._lineSize, sprite._scriptId); + } else { + debugC(kDebugLoading, 4, "CH: %-3d castId: 000", i + 1); + } } } @@ -539,6 +544,14 @@ void Frame::playTransition(Score *score) { } } +void Frame::executeImmediateScripts() { + for (uint16 i = 0; i < CHANNEL_COUNT; i++) { + if (_vm->getCurrentScore()->_immediateActions.contains(_sprites[i]->_scriptId)) { + g_lingo->processEvent(kEventMouseUp, kFrameScript, _sprites[i]->_scriptId); + } + } +} + void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) { for (uint16 i = 0; i < CHANNEL_COUNT; i++) { if (_sprites[i]->_enabled) { @@ -563,18 +576,17 @@ void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) { break; } } else { - if (!_vm->getCurrentScore()->_casts.contains(_sprites[i]->_castId)) { - if (!_vm->getSharedCasts()->contains(_sprites[i]->_castId)) { + if (!_vm->getCurrentScore()->_castTypes.contains(_sprites[i]->_castId)) { + if (!_vm->getSharedCastTypes()->contains(_sprites[i]->_castId)) { warning("Cast id %d not found", _sprites[i]->_castId); continue; } else { warning("Getting cast id %d from shared cast", _sprites[i]->_castId); - cast = _vm->getSharedCasts()->getVal(_sprites[i]->_castId); + castType = _vm->getSharedCastTypes()->getVal(_sprites[i]->_castId); } } else { - cast = _vm->getCurrentScore()->_casts[_sprites[i]->_castId]; + castType = _vm->getCurrentScore()->_castTypes[_sprites[i]->_castId]; } - castType = cast->type; } // this needs precedence to be hit first... D3 does something really tricky with cast IDs for shapes. @@ -586,34 +598,15 @@ void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) { } else if (castType == kCastButton) { renderButton(surface, i, _vm->getVersion() < 4 ? _sprites[i]->_castId + 1024 : cast->children[0].index); } else { - Image::ImageDecoder *img = getImageFrom(_sprites[i]->_castId); - - if (!img) { - warning("Image with id %d (%s) not found", _sprites[i]->_castId, numToCastNum(_sprites[i]->_castId)); - continue; - } - - if (!img->getSurface()) { - warning("Frame::renderSprites: Could not load image %d (%s)", _sprites[i]->_castId, numToCastNum(_sprites[i]->_castId)); - continue; - } - - if (!_sprites[i]->_cast) { + if (!_sprites[i]->_bitmapCast) { warning("No cast ID for sprite %d", i); continue; } - BitmapCast *bitmapCast = static_cast<BitmapCast *>(_sprites[i]->_cast); - // TODO: might want a quicker way to determine if cast is from Shared Cast. - if (_vm->getSharedBMP() != NULL && _vm->getSharedBMP()->contains(_sprites[i]->_castId + 1024)) { - debugC(2, kDebugImages, "Shared cast sprite BMP: id: %d", _sprites[i]->_castId + 1024); - bitmapCast = static_cast<BitmapCast *>(_vm->getSharedCasts()->getVal(_sprites[i]->_castId)); - } - - uint32 regX = bitmapCast->regX; - uint32 regY = bitmapCast->regY; - uint32 rectLeft = bitmapCast->initialRect.left; - uint32 rectTop = bitmapCast->initialRect.top; + uint32 regX = _sprites[i]->_bitmapCast->regX; + uint32 regY = _sprites[i]->_bitmapCast->regY; + uint32 rectLeft = _sprites[i]->_bitmapCast->initialRect.left; + uint32 rectTop = _sprites[i]->_bitmapCast->initialRect.top; int x = _sprites[i]->_startPoint.x - regX + rectLeft; int y = _sprites[i]->_startPoint.y - regY + rectTop; @@ -621,9 +614,8 @@ void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) { int width = _sprites[i]->_width; Common::Rect drawRect(x, y, x + width, y + height); - addDrawRect(i, drawRect); - inkBasedBlit(surface, *img->getSurface(), i, drawRect); + inkBasedBlit(surface, *(_sprites[i]->_bitmapCast->surface), i, drawRect); } } } @@ -667,15 +659,15 @@ void Frame::renderShape(Graphics::ManagedSurface &surface, uint16 spriteId) { void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId, uint16 textId) { uint16 castId = _sprites[spriteId]->_castId; - ButtonCast *button = static_cast<ButtonCast *>(_vm->getCurrentScore()->_casts[castId]); + ButtonCast *button = _vm->getCurrentScore()->_loadedButtons->getVal(castId); uint32 rectLeft = button->initialRect.left; uint32 rectTop = button->initialRect.top; int x = _sprites[spriteId]->_startPoint.x + rectLeft; int y = _sprites[spriteId]->_startPoint.y + rectTop; - int height = button->initialRect.height(); // _sprites[spriteId]->_height; - int width = button->initialRect.width() + 3; // _sprites[spriteId]->_width; + int height = button->initialRect.height(); + int width = button->initialRect.width() + 3; Common::Rect textRect(0, 0, width, height); // pass the rect of the button into the label. @@ -706,73 +698,6 @@ void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId, uin } } -Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId) { - uint16 imgId = spriteId + 1024; - - if (_vm->getVersion() >= 4 && _vm->getCurrentScore()->_casts[spriteId]->children.size() > 0) - imgId = _vm->getCurrentScore()->_casts[spriteId]->children[0].index; - - Image::ImageDecoder *img = NULL; - - if (_vm->getCurrentScore()->getArchive()->hasResource(MKTAG('D', 'I', 'B', ' '), imgId)) { - img = new DIBDecoder(); - img->loadStream(*_vm->getCurrentScore()->getArchive()->getResource(MKTAG('D', 'I', 'B', ' '), imgId)); - return img; - } - - if (_vm->getSharedDIB() != NULL && _vm->getSharedDIB()->contains(imgId)) { - img = new DIBDecoder(); - img->loadStream(*_vm->getSharedDIB()->getVal(imgId)); - return img; - } - - Common::SeekableReadStream *pic = NULL; - BitmapCast *bc = NULL; - - if (_vm->getSharedBMP() != NULL && _vm->getSharedBMP()->contains(imgId)) { - debugC(4, kDebugImages, "Shared cast BMP: id: %d", imgId); - pic = _vm->getSharedBMP()->getVal(imgId); - pic->seek(0); // TODO: this actually gets re-read every loop... we need to rewind it! - bc = static_cast<BitmapCast *>(_vm->getSharedCasts()->getVal(spriteId)); - } else if (_vm->getCurrentScore()->getArchive()->hasResource(MKTAG('B', 'I', 'T', 'D'), imgId)) { - pic = _vm->getCurrentScore()->getArchive()->getResource(MKTAG('B', 'I', 'T', 'D'), imgId); - bc = static_cast<BitmapCast *>(_vm->getCurrentScore()->_casts[spriteId]); - } - - if (pic != NULL && bc != NULL) { - if (_vm->getVersion() < 4) { - int w = bc->initialRect.width(), h = bc->initialRect.height(); - - debugC(4, kDebugImages, "id: %d, w: %d, h: %d, flags: %x, some: %x, unk1: %d, unk2: %d", - imgId, w, h, bc->flags, bc->someFlaggyThing, bc->unk1, bc->unk2); - img = new BITDDecoder(w, h); - } else if (_vm->getVersion() < 6) { - bc = static_cast<BitmapCast *>(_vm->getCurrentScore()->_casts[spriteId]); - int w = bc->initialRect.width(), h = bc->initialRect.height(); - - debugC(4, kDebugImages, "id: %d, w: %d, h: %d, flags: %x, some: %x, unk1: %d, unk2: %d", - imgId, w, h, bc->flags, bc->someFlaggyThing, bc->unk1, bc->unk2); - img = new BITDDecoderV4(w, h, bc->bitsPerPixel); - } else { - img = new Image::BitmapDecoder(); - } - - if (debugChannelSet(8, kDebugLoading)) { - Common::SeekableReadStream *s = pic; - byte buf[1024]; - int n = s->read(buf, 1024); - Common::hexdump(buf, n); - s->seek(0); - } - - img->loadStream(*pic); - return img; - } - - warning("Image %d not found", spriteId); - return img; -} - void Frame::inkBasedBlit(Graphics::ManagedSurface &targetSurface, const Graphics::Surface &spriteSurface, uint16 spriteId, Common::Rect drawRect) { switch (_sprites[spriteId]->_ink) { case kInkTypeCopy: @@ -818,7 +743,7 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo return; uint16 castId = _sprites[spriteId]->_castId; - TextCast *textCast = static_cast<TextCast *>(_vm->getCurrentScore()->_casts[castId]); + TextCast *textCast = _vm->getCurrentScore()->_loadedText->getVal(castId); uint32 unk1 = textStream->readUint32(); uint32 strLen = textStream->readUint32(); @@ -906,8 +831,8 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo int x = _sprites[spriteId]->_startPoint.x; // +rectLeft; int y = _sprites[spriteId]->_startPoint.y; // +rectTop; - int height = _sprites[spriteId]->_cast->initialRect.height(); //_sprites[spriteId]->_height; - int width = _sprites[spriteId]->_cast->initialRect.width(); //_sprites[spriteId]->_width; + int height = textCast->initialRect.height(); //_sprites[spriteId]->_height; + int width = textCast->initialRect.width(); //_sprites[spriteId]->_width; if (_vm->getVersion() >= 4 && textSize != NULL) width = textCast->initialRect.right; @@ -1143,4 +1068,13 @@ uint16 Frame::getSpriteIDFromPos(Common::Point pos) { return 0; } +bool Frame::checkSpriteIntersection(uint16 spriteId, Common::Point pos) { + // Find first from front to back + for (int dr = _drawRects.size() - 1; dr >= 0; dr--) + if (_drawRects[dr]->spriteId == spriteId && _drawRects[dr]->rect.contains(pos)) + return true; + + return false; +} + } // End of namespace Director diff --git a/engines/director/frame.h b/engines/director/frame.h index 704319ba0d..e2a4a1f37b 100644 --- a/engines/director/frame.h +++ b/engines/director/frame.h @@ -119,6 +119,9 @@ public: void readChannel(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size); void prepareFrame(Score *score); uint16 getSpriteIDFromPos(Common::Point pos); + bool checkSpriteIntersection(uint16 spriteId, Common::Point pos); + + void executeImmediateScripts(); private: void playTransition(Score *score); diff --git a/engines/director/graphics.cpp b/engines/director/graphics.cpp index 5322abcedf..46dab0f763 100644 --- a/engines/director/graphics.cpp +++ b/engines/director/graphics.cpp @@ -82,123 +82,126 @@ byte defaultPalette[768] = { 102, 255, 102, 153, 255, 102, 204, 255, 102, 255, 255, 153, 0, 255, 153, 51, 255, 153, 102, 255, 153, 153, 255, 153, 204, 255, 153, 255, 255, 204, 0, 255, 204, 51, 255, 204, 102, 255, 204, 153, 255, 204, 204, 255, 204, 255, 255, 255, - 0, 255, 255, 51, 255, 255, 102, 255, 255, 153, 255, 255, 204, 255, 255, 255 }; - - -static byte director3Patterns[][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0x77, 0xFF, 0xFF, 0xFF, 0x77, 0xFF }, - { 0x77, 0xFF, 0xDD, 0xFF, 0x77, 0xFF, 0xDD, 0xFF }, - { 0xFF, 0xDD, 0xFF, 0x55, 0xFF, 0xDD, 0xFF, 0x55 }, - { 0xFF, 0xD5, 0xFF, 0x55, 0xFF, 0x5D, 0xFF, 0x55 }, - { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA }, - { 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA }, - { 0xAA, 0x44, 0xAA, 0x11, 0xAA, 0x44, 0xAA, 0x11 }, - { 0xAA, 0x44, 0xAA, 0x00, 0xAA, 0x44, 0xAA, 0x00 }, - { 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00 }, - { 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00, 0x88 }, - { 0x88, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00 }, - { 0x80, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, - { 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }, - { 0x21, 0x42, 0x84, 0x09, 0x12, 0x24, 0x48, 0x90 }, - { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 }, - { 0xEE, 0xDD, 0xBB, 0x77, 0xEE, 0xDD, 0xBB, 0x77 }, - { 0xF6, 0xED, 0xDB, 0xB7, 0x6F, 0xDE, 0xBD, 0x7B }, - { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF }, - { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF }, - { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF }, - { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00 }, - { 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00 }, - { 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00 }, - { 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, - { 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82 }, - { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 }, - { 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94 }, - { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA }, - { 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD }, - { 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB }, - { 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7 }, - { 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF }, - { 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x00 }, - { 0x7F, 0x7F, 0x7F, 0x00, 0x7F, 0x7F, 0x7F, 0x00 }, - { 0x77, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x00 }, - { 0x88, 0x88, 0x88, 0xFF, 0x88, 0x88, 0x88, 0xFF }, - { 0x80, 0x80, 0x80, 0xFF, 0x80, 0x80, 0x80, 0xFF }, - { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFF }, - { 0x01, 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82 }, - { 0x11, 0x82, 0x45, 0xAB, 0xD7, 0xAB, 0x45, 0x82 }, - { 0xF7, 0x7F, 0xBE, 0x5D, 0x2A, 0x5D, 0xBE, 0x7F }, - { 0xFE, 0x7D, 0xBB, 0xD7, 0xEF, 0xD7, 0xBB, 0x7D }, - { 0xFE, 0x7F, 0xBF, 0xDF, 0xEF, 0xDF, 0xBF, 0x7F }, - { 0xEE, 0x77, 0xBB, 0xDD, 0xEE, 0xDD, 0xBB, 0x77 }, - { 0x11, 0x88, 0x44, 0x22, 0x11, 0x22, 0x44, 0x88 }, - { 0x01, 0x80, 0x40, 0x20, 0x10, 0x20, 0x40, 0x80 }, - { 0x22, 0x00, 0x01, 0x22, 0x54, 0x88, 0x01, 0x00 }, - { 0xBF, 0xAF, 0xAB, 0xAA, 0xEA, 0xFA, 0xFE, 0xFF }, - { 0xFF, 0xFF, 0xBE, 0x9C, 0xAA, 0xB6, 0xBE, 0xFF } + 0, 255, 255, 51, 255, 255, 102, 255, 255, 153, 255, 255, 204, 255, 255, 255 }; -static byte director3QuickDrawPatterns[][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xDD, 0xFF, 0x77, 0xFF, 0xDD, 0xFF, 0x77, 0xFF }, - { 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77 }, - { 0xEE, 0xDD, 0xBB, 0x77, 0xEE, 0xDD, 0xBB, 0x77 }, - { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA }, - { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 }, - { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }, - { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 }, - { 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00 }, - { 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22 }, - { 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00, 0x88 }, - { 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08 }, - { 0x80, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, - { 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 }, - { 0x58, 0xDF, 0x00, 0xDF, 0xDF, 0x58, 0x58, 0x58 }, - { 0xB1, 0x36, 0x06, 0x60, 0x63, 0x1B, 0x18, 0x81 }, - { 0x08, 0xFF, 0x01, 0x01, 0x01, 0xFF, 0x08, 0x08 }, - { 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00 }, - { 0x80, 0x80, 0x80, 0xFF, 0x80, 0x80, 0x80, 0x80 }, - { 0x80, 0x10, 0x02, 0x40, 0x04, 0x20, 0x09, 0x00 }, - { 0x80, 0x01, 0x82, 0x44, 0x38, 0x10, 0x20, 0x40 }, - { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00 }, - { 0x22, 0xFF, 0x22, 0x22, 0x22, 0xFF, 0x22, 0x22 }, - { 0x00, 0x08, 0x14, 0x2A, 0x55, 0x2A, 0x14, 0x08 }, - { 0x81, 0xAA, 0x14, 0x08, 0x08, 0xAA, 0x41, 0x80 }, - { 0x3E, 0x1D, 0x88, 0xD1, 0xE3, 0xC5, 0x88, 0x5C }, - { 0xAA, 0x00, 0x80, 0x00, 0x88, 0x00, 0x80, 0x00 }, - { 0x00, 0x11, 0x82, 0x44, 0x28, 0x11, 0x00, 0x55 }, - { 0x7C, 0x10, 0x10, 0x28, 0xC7, 0x01, 0x01, 0x82 }, - { 0xEE, 0x31, 0xF1, 0xF1, 0xEE, 0x13, 0x1F, 0x1F }, - { 0x00, 0x40, 0x20, 0x10, 0x00, 0x01, 0x02, 0x04 }, - { 0x00, 0x00, 0x40, 0xA0, 0x00, 0x04, 0x0A, 0x00 }, - { 0x20, 0x60, 0x90, 0x09, 0x06, 0x81, 0x40, 0x20 }, - { 0x00, 0x7F, 0x43, 0x5F, 0x5F, 0x5F, 0x7F, 0x7F }, - { 0x01, 0x02, 0x45, 0xAA, 0xFF, 0x20, 0x40, 0x80 }, - { 0x00, 0x44, 0x0A, 0x11, 0x11, 0x11, 0x51, 0x24 }, - { 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0 }, - { 0xF8, 0xFC, 0xFA, 0xFC, 0xFA, 0x54, 0x2A, 0x00 }, - { 0x42, 0xC3, 0x3C, 0x3C, 0x3C, 0x3C, 0xC3, 0x42 }, - { 0x10, 0x38, 0x7C, 0xFE, 0x7D, 0x3A, 0x14, 0x08 }, - { 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF }, - { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC }, - { 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00 }, - { 0xBB, 0xDD, 0xAE, 0x77, 0xEE, 0xDD, 0xAB, 0x77 }, - { 0x80, 0x40, 0x40, 0x20, 0x20, 0x18, 0x06, 0x01 }, - { 0x01, 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82 }, - { 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF }, - { 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xFF, 0xFF, 0xFF }, - { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00 }, - { 0xC3, 0x87, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xE1 }, - { 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0 }, - { 0xFF, 0xFF, 0xE7, 0xC3, 0x81, 0x18, 0x3C, 0x7E }, - { 0x1F, 0x8F, 0xC7, 0xE3, 0xC7, 0x8F, 0x1F, 0x3E }, - { 0xFF, 0x2A, 0xFF, 0xC8, 0xFF, 0x65, 0xFF, 0x9D } + +static byte director3Patterns[][8] = { + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0x77, 0xFF, 0xFF, 0xFF, 0x77, 0xFF }, + { 0x77, 0xFF, 0xDD, 0xFF, 0x77, 0xFF, 0xDD, 0xFF }, + { 0xFF, 0xDD, 0xFF, 0x55, 0xFF, 0xDD, 0xFF, 0x55 }, + { 0xFF, 0xD5, 0xFF, 0x55, 0xFF, 0x5D, 0xFF, 0x55 }, + { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA }, + { 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA }, + { 0xAA, 0x44, 0xAA, 0x11, 0xAA, 0x44, 0xAA, 0x11 }, + { 0xAA, 0x44, 0xAA, 0x00, 0xAA, 0x44, 0xAA, 0x00 }, + { 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00 }, + { 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00, 0x88 }, + { 0x88, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00 }, + { 0x80, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, + { 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }, + { 0x21, 0x42, 0x84, 0x09, 0x12, 0x24, 0x48, 0x90 }, + { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 }, + { 0xEE, 0xDD, 0xBB, 0x77, 0xEE, 0xDD, 0xBB, 0x77 }, + { 0xF6, 0xED, 0xDB, 0xB7, 0x6F, 0xDE, 0xBD, 0x7B }, + { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF }, + { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF }, + { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF }, + { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00 }, + { 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00 }, + { 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00 }, + { 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, + { 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82 }, + { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 }, + { 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94 }, + { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA }, + { 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD }, + { 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB }, + { 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7 }, + { 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF }, + { 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x00 }, + { 0x7F, 0x7F, 0x7F, 0x00, 0x7F, 0x7F, 0x7F, 0x00 }, + { 0x77, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x00 }, + { 0x88, 0x88, 0x88, 0xFF, 0x88, 0x88, 0x88, 0xFF }, + { 0x80, 0x80, 0x80, 0xFF, 0x80, 0x80, 0x80, 0xFF }, + { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFF }, + { 0x01, 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82 }, + { 0x11, 0x82, 0x45, 0xAB, 0xD7, 0xAB, 0x45, 0x82 }, + { 0xF7, 0x7F, 0xBE, 0x5D, 0x2A, 0x5D, 0xBE, 0x7F }, + { 0xFE, 0x7D, 0xBB, 0xD7, 0xEF, 0xD7, 0xBB, 0x7D }, + { 0xFE, 0x7F, 0xBF, 0xDF, 0xEF, 0xDF, 0xBF, 0x7F }, + { 0xEE, 0x77, 0xBB, 0xDD, 0xEE, 0xDD, 0xBB, 0x77 }, + { 0x11, 0x88, 0x44, 0x22, 0x11, 0x22, 0x44, 0x88 }, + { 0x01, 0x80, 0x40, 0x20, 0x10, 0x20, 0x40, 0x80 }, + { 0x22, 0x00, 0x01, 0x22, 0x54, 0x88, 0x01, 0x00 }, + { 0xBF, 0xAF, 0xAB, 0xAA, 0xEA, 0xFA, 0xFE, 0xFF }, + { 0xFF, 0xFF, 0xBE, 0x9C, 0xAA, 0xB6, 0xBE, 0xFF } +}; + +static byte director3QuickDrawPatterns[][8] = { + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xDD, 0xFF, 0x77, 0xFF, 0xDD, 0xFF, 0x77, 0xFF }, + { 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77 }, + { 0xEE, 0xDD, 0xBB, 0x77, 0xEE, 0xDD, 0xBB, 0x77 }, + { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA }, + { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 }, + { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }, + { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 }, + { 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00 }, + { 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22 }, + { 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00, 0x88 }, + { 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08 }, + { 0x80, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, + { 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 }, + { 0x58, 0xDF, 0x00, 0xDF, 0xDF, 0x58, 0x58, 0x58 }, + { 0xB1, 0x36, 0x06, 0x60, 0x63, 0x1B, 0x18, 0x81 }, + { 0x08, 0xFF, 0x01, 0x01, 0x01, 0xFF, 0x08, 0x08 }, + { 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00 }, + { 0x80, 0x80, 0x80, 0xFF, 0x80, 0x80, 0x80, 0x80 }, + { 0x80, 0x10, 0x02, 0x40, 0x04, 0x20, 0x09, 0x00 }, + { 0x80, 0x01, 0x82, 0x44, 0x38, 0x10, 0x20, 0x40 }, + { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00 }, + { 0x22, 0xFF, 0x22, 0x22, 0x22, 0xFF, 0x22, 0x22 }, + { 0x00, 0x08, 0x14, 0x2A, 0x55, 0x2A, 0x14, 0x08 }, + { 0x81, 0xAA, 0x14, 0x08, 0x08, 0xAA, 0x41, 0x80 }, + { 0x3E, 0x1D, 0x88, 0xD1, 0xE3, 0xC5, 0x88, 0x5C }, + { 0xAA, 0x00, 0x80, 0x00, 0x88, 0x00, 0x80, 0x00 }, + { 0x00, 0x11, 0x82, 0x44, 0x28, 0x11, 0x00, 0x55 }, + { 0x7C, 0x10, 0x10, 0x28, 0xC7, 0x01, 0x01, 0x82 }, + { 0xEE, 0x31, 0xF1, 0xF1, 0xEE, 0x13, 0x1F, 0x1F }, + { 0x00, 0x40, 0x20, 0x10, 0x00, 0x01, 0x02, 0x04 }, + { 0x00, 0x00, 0x40, 0xA0, 0x00, 0x04, 0x0A, 0x00 }, + { 0x20, 0x60, 0x90, 0x09, 0x06, 0x81, 0x40, 0x20 }, + { 0x00, 0x7F, 0x43, 0x5F, 0x5F, 0x5F, 0x7F, 0x7F }, + { 0x01, 0x02, 0x45, 0xAA, 0xFF, 0x20, 0x40, 0x80 }, + { 0x00, 0x44, 0x0A, 0x11, 0x11, 0x11, 0x51, 0x24 }, + { 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0 }, + { 0xF8, 0xFC, 0xFA, 0xFC, 0xFA, 0x54, 0x2A, 0x00 }, + { 0x42, 0xC3, 0x3C, 0x3C, 0x3C, 0x3C, 0xC3, 0x42 }, + { 0x10, 0x38, 0x7C, 0xFE, 0x7D, 0x3A, 0x14, 0x08 }, + { 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF }, + { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC }, + { 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00 }, + { 0xBB, 0xDD, 0xAE, 0x77, 0xEE, 0xDD, 0xAB, 0x77 }, + { 0x80, 0x40, 0x40, 0x20, 0x20, 0x18, 0x06, 0x01 }, + { 0x01, 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82 }, + { 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF }, + { 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xFF, 0xFF, 0xFF }, + { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00 }, + { 0xC3, 0x87, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xE1 }, + { 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0 }, + { 0xFF, 0xFF, 0xE7, 0xC3, 0x81, 0x18, 0x3C, 0x7E }, + { 0x1F, 0x8F, 0xC7, 0xE3, 0xC7, 0x8F, 0x1F, 0x3E }, + { 0xFF, 0x2A, 0xFF, 0xC8, 0xFF, 0x65, 0xFF, 0x9D } }; void DirectorEngine::loadPatterns() { diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp index f554f43cd8..cb6a7d67ec 100644 --- a/engines/director/lingo/lingo-builtins.cpp +++ b/engines/director/lingo/lingo-builtins.cpp @@ -21,7 +21,11 @@ */ #include "common/system.h" +#include "common/events.h" + #include "director/lingo/lingo.h" +#include "director/frame.h" +#include "director/sprite.h" namespace Director { @@ -379,7 +383,7 @@ void Lingo::printSTUBWithArglist(const char *funcname, int nargs, const char *pr s += ")"; - warning("%s: %s", prefix, s.c_str()); + warning("%s %s", prefix, s.c_str()); } void Lingo::convertVOIDtoString(int arg, int nargs) { @@ -1163,9 +1167,12 @@ void Lingo::b_move(int nargs) { } void Lingo::b_moveableSprite(int nargs) { - g_lingo->printSTUBWithArglist("b_moveableSprite", nargs); + Frame *frame = g_director->getCurrentScore()->_frames[g_director->getCurrentScore()->getCurrentFrame()]; - g_lingo->dropStack(nargs); + // Will have no effect + frame->_sprites[g_lingo->_currentEntityId]->_moveable = true; + + g_director->setDraggedSprite(frame->_sprites[g_lingo->_currentEntityId]->_castId); } void Lingo::b_pasteClipBoardInto(int nargs) { @@ -1216,9 +1223,26 @@ void Lingo::b_ramNeeded(int nargs) { void Lingo::b_rollOver(int nargs) { Datum d = g_lingo->pop(); - warning("STUB: b_rollOver(%d)", d.u.i); - g_lingo->push(Datum(0)); + d.toInt(); + + int arg = d.u.i; + + d.u.i = 0; // FALSE + + Frame *frame = g_director->getCurrentScore()->_frames[g_director->getCurrentScore()->getCurrentFrame()]; + + if (arg >= frame->_sprites.size()) { + g_lingo->push(d); + return; + } + + Common::Point pos = g_system->getEventManager()->getMousePos(); + + if (frame->checkSpriteIntersection(arg, pos)) + d.u.i = 1; // TRUE + + g_lingo->push(d); } void Lingo::b_spriteBox(int nargs) { diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp index 7bc82eddcf..d0d29dd04c 100644 --- a/engines/director/lingo/lingo-code.cpp +++ b/engines/director/lingo/lingo-code.cpp @@ -307,10 +307,14 @@ void Lingo::c_assign() { } if (d1.type == REFERENCE) { - if (!g_director->getCurrentScore()->_castsInfo.contains(d1.u.i)) { - warning("c_assign: Unknown REFERENCE %d", d1.u.i); - g_lingo->pushVoid(); - return; + if (!g_director->getCurrentScore()->_loadedText->contains(d1.u.i)) { + if (!g_director->getCurrentScore()->_loadedText->contains(d1.u.i - 1024)) { + warning("c_assign: Unknown REFERENCE %d", d1.u.i); + g_lingo->pushVoid(); + return; + } else { + d1.u.i -= 1024; + } } warning("STUB: c_assing REFERENCE"); diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp index 8f874435f7..68999f66ef 100644 --- a/engines/director/lingo/lingo-the.cpp +++ b/engines/director/lingo/lingo-the.cpp @@ -332,8 +332,8 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) { switch (field) { case kTheCastNum: - if (_vm->getCurrentScore()->_casts.contains(d.u.i)) { - sprite->_cast = _vm->getCurrentScore()->_casts[d.u.i]; + if (_vm->getCurrentScore()->_castTypes.contains(d.u.i)) { + _vm->getCurrentScore()->loadCastInto(sprite, d.u.i); sprite->_castId = d.u.i; } break; @@ -638,9 +638,9 @@ Datum Lingo::getTheCast(Datum &id1, int field) { return d; } - Cast *cast; + CastType castType; CastInfo *castInfo; - if (!_vm->getCurrentScore()->_casts.contains(id)) { + if (!_vm->getCurrentScore()->_castTypes.contains(id)) { if (field == kTheLoaded) { d.type = INT; d.u.i = 0; @@ -651,14 +651,14 @@ Datum Lingo::getTheCast(Datum &id1, int field) { warning("The cast %d found", id); } - cast = _vm->getCurrentScore()->_casts[id]; + castType = _vm->getCurrentScore()->_castTypes[id]; castInfo = _vm->getCurrentScore()->_castsInfo[id]; d.type = INT; switch (field) { case kTheCastType: - d.u.i = cast->type; + d.u.i = castType; break; case kTheFileName: d.toString(); @@ -673,32 +673,32 @@ Datum Lingo::getTheCast(Datum &id1, int field) { d.u.s = &castInfo->script; break; case kTheWidth: - d.u.i = cast->initialRect.width(); + d.u.i = _vm->getCurrentScore()->getCastMemberInitialRect(id).width(); break; case kTheHeight: - d.u.i = cast->initialRect.height(); + d.u.i = _vm->getCurrentScore()->getCastMemberInitialRect(id).height(); break; case kTheBackColor: { - if (cast->type != kCastShape) { + if (castType != kCastShape) { warning("Field %d of cast %d not found", field, id); d.type = VOID; return d; } - ShapeCast *shape = static_cast<ShapeCast *>(_vm->getCurrentScore()->_casts[id]); + ShapeCast *shape = _vm->getCurrentScore()->_loadedShapes->getVal(id); d.u.i = shape->bgCol; } break; case kTheForeColor: { - if (cast->type != kCastShape) { + if (castType != kCastShape) { warning("Field %d of cast %d not found", field, id); d.type = VOID; return d; } - ShapeCast *shape = static_cast<ShapeCast *>(_vm->getCurrentScore()->_casts[id]); + ShapeCast *shape = _vm->getCurrentScore()->_loadedShapes->getVal(id); d.u.i = shape->fgCol; } break; @@ -729,18 +729,20 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) { return; } - Cast *cast = _vm->getCurrentScore()->_casts[id]; + CastType castType = _vm->getCurrentScore()->_castTypes[id]; CastInfo *castInfo = _vm->getCurrentScore()->_castsInfo[id]; - if (!cast) { + if (!castInfo) { warning("The cast %d found", id); return; } switch (field) { case kTheCastType: - cast->type = static_cast<CastType>(d.u.i); - cast->modified = 1; + // TODO: You can actually switch the cast type!? + warning("Tried to switch cast type of %d", id); + //cast->type = static_cast<CastType>(d.u.i); + //cast->modified = 1; break; case kTheFileName: castInfo->fileName = *d.u.s; @@ -752,30 +754,30 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) { castInfo->script = *d.u.s; break; case kTheWidth: - cast->initialRect.setWidth(d.u.i); - cast->modified = 1; + _vm->getCurrentScore()->getCastMemberInitialRect(id).setWidth(d.u.i); + _vm->getCurrentScore()->setCastMemberModified(id); break; case kTheHeight: - cast->initialRect.setHeight(d.u.i); - cast->modified = 1; + _vm->getCurrentScore()->getCastMemberInitialRect(id).setHeight(d.u.i); + _vm->getCurrentScore()->setCastMemberModified(id); break; case kTheBackColor: { - if (cast->type != kCastShape) { + if (castType != kCastShape) { warning("Field %d of cast %d not found", field, id); } - ShapeCast *shape = static_cast<ShapeCast *>(_vm->getCurrentScore()->_casts[id]); + ShapeCast *shape = _vm->getCurrentScore()->_loadedShapes->getVal(id); shape->bgCol = d.u.i; shape->modified = 1; } break; case kTheForeColor: { - if (cast->type != kCastShape) { + if (castType != kCastShape) { warning("Field %d of cast %d not found", field, id); return; } - ShapeCast *shape = static_cast<ShapeCast *>(_vm->getCurrentScore()->_casts[id]); + ShapeCast *shape = _vm->getCurrentScore()->_loadedShapes->getVal(id); shape->fgCol = d.u.i; shape->modified = 1; } diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp index 706f76777d..a51ff222c7 100644 --- a/engines/director/lingo/lingo.cpp +++ b/engines/director/lingo/lingo.cpp @@ -299,7 +299,7 @@ void Lingo::processEvent(LEvent event, ScriptType st, int entityId) { if (entityId < 0) return; - debugC(1, kDebugEvents, "Lingo::processEvent(%s, %s, %d)", _eventHandlerTypes[event], scriptType2str(st), entityId); + debugC(9, kDebugEvents, "Lingo::processEvent(%s, %s, %d)", _eventHandlerTypes[event], scriptType2str(st), entityId); _currentEntityId = entityId; @@ -307,8 +307,11 @@ void Lingo::processEvent(LEvent event, ScriptType st, int entityId) { error("processEvent: Unknown event %d for entity %d", event, entityId); if (_handlers.contains(ENTITY_INDEX(event, entityId))) { + debugC(1, kDebugEvents, "Lingo::processEvent(%s, %s, %d), _eventHandler", _eventHandlerTypes[event], scriptType2str(st), entityId); call(_eventHandlerTypes[event], 0); // D4+ Events } else if (_scripts[st].contains(entityId)) { + debugC(1, kDebugEvents, "Lingo::processEvent(%s, %s, %d), script", _eventHandlerTypes[event], scriptType2str(st), entityId); + executeScript(st, entityId); // D3 list of scripts. } else { debugC(3, kDebugLingoExec, "STUB: processEvent(%s) for %d", _eventHandlerTypes[event], entityId); @@ -318,6 +321,13 @@ void Lingo::processEvent(LEvent event, ScriptType st, int entityId) { void Lingo::restartLingo() { warning("STUB: restartLingo()"); + for (int i = 0; i <= kMaxScriptType; i++) { + for (ScriptHash::iterator it = _scripts[i].begin(); it != _scripts[i].end(); ++it) + delete it->_value; + + _scripts[i].clear(); + } + // TODO // // reset the following: @@ -403,6 +413,9 @@ Common::String *Datum::toString() { case VAR: *s = Common::String::format("var: #%s", u.sym->name.c_str()); break; + case REFERENCE: + *s = Common::String::format("field#%d", u.i); + break; default: warning("Incorrect operation toString() for type: %s", type2str()); } diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp index 6dace8bcb2..7dbd5a78a6 100644 --- a/engines/director/resource.cpp +++ b/engines/director/resource.cpp @@ -76,6 +76,7 @@ void DirectorEngine::loadEXE(const Common::String movie) { exeStream->seek(exeStream->readUint32LE()); switch (getVersion()) { + case 2: case 3: loadEXEv3(exeStream); break; @@ -100,12 +101,23 @@ void DirectorEngine::loadEXEv3(Common::SeekableReadStream *stream) { stream->skip(5); // unknown - stream->readUint32LE(); // Main MMM size + uint32 mmmSize = stream->readUint32LE(); // Main MMM size + Common::String mmmFileName = stream->readPascalString(); Common::String directoryName = stream->readPascalString(); debugC(1, kDebugLoading, "Main MMM: '%s'", mmmFileName.c_str()); debugC(1, kDebugLoading, "Directory Name: '%s'", directoryName.c_str()); + debugC(1, kDebugLoading, "Main mmmSize: %d (0x%x)", mmmSize, mmmSize); + + if (mmmSize) { + uint32 riffOffset = stream->pos(); + + _mainArchive = new RIFFArchive(); + + if (!_mainArchive->openStream(stream, riffOffset)) + error("Failed to load RIFF from EXE"); + } openMainArchive(mmmFileName); @@ -200,19 +212,21 @@ void DirectorEngine::loadMac(const Common::String movie) { void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Archive *shardcst = createArchive(); - debug(0, "Loading Shared cast '%s'", filename.c_str()); + debug(0, "****** Loading Shared cast '%s'", filename.c_str()); + _sharedDIB = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; + _sharedSTXT = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; + _sharedSound = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; + _sharedBMP = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; + + _sharedScore = new Score(this); if (!shardcst->openFile(filename)) { warning("No shared cast %s", filename.c_str()); return; } - _sharedDIB = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; - _sharedSTXT = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; - _sharedSound = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; - _sharedBMP = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; - _sharedScore = new Score(this, shardcst); + _sharedScore->setArchive(shardcst); if (shardcst->hasResource(MKTAG('F', 'O', 'N', 'D'), -1)) { debug("Shared cast has fonts. Loading...."); @@ -227,12 +241,16 @@ void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Common::Array<uint16> cast = shardcst->getResourceIDList(MKTAG('C','A','S','t')); if (cast.size() > 0) { + debug(0, "****** Loading %d CASt resources", cast.size()); + for (Common::Array<uint16>::iterator iterator = cast.begin(); iterator != cast.end(); ++iterator) _sharedScore->loadCastData(*shardcst->getResource(MKTAG('C','A','S','t'), *iterator), *iterator, NULL); } Common::Array<uint16> vwci = shardcst->getResourceIDList(MKTAG('V', 'W', 'C', 'I')); if (vwci.size() > 0) { + debug(0, "****** Loading %d CastInfo resources", vwci.size()); + for (Common::Array<uint16>::iterator iterator = vwci.begin(); iterator != vwci.end(); ++iterator) _sharedScore->loadCastInfo(*shardcst->getResource(MKTAG('V', 'W', 'C', 'I'), *iterator), *iterator); } @@ -241,7 +259,7 @@ void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Common::Array<uint16> dib = shardcst->getResourceIDList(MKTAG('D','I','B',' ')); if (dib.size() != 0) { - debugC(3, kDebugLoading, "Loading %d DIBs", dib.size()); + debugC(3, kDebugLoading, "****** Loading %d DIBs", dib.size()); for (Common::Array<uint16>::iterator iterator = dib.begin(); iterator != dib.end(); ++iterator) { debugC(3, kDebugLoading, "Shared DIB %d", *iterator); @@ -251,7 +269,7 @@ void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Common::Array<uint16> stxt = shardcst->getResourceIDList(MKTAG('S','T','X','T')); if (stxt.size() != 0) { - debugC(3, kDebugLoading, "Loading %d STXTs", stxt.size()); + debugC(3, kDebugLoading, "****** Loading %d STXTs", stxt.size()); for (Common::Array<uint16>::iterator iterator = stxt.begin(); iterator != stxt.end(); ++iterator) { debugC(3, kDebugLoading, "Shared STXT %d", *iterator); @@ -261,7 +279,7 @@ void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Common::Array<uint16> bmp = shardcst->getResourceIDList(MKTAG('B','I','T','D')); if (bmp.size() != 0) { - debugC(3, kDebugLoading, "Loading %d BITDs", bmp.size()); + debugC(3, kDebugLoading, "****** Loading %d BITDs", bmp.size()); for (Common::Array<uint16>::iterator iterator = bmp.begin(); iterator != bmp.end(); ++iterator) { debugC(3, kDebugLoading, "Shared BITD %d (%s)", *iterator, numToCastNum(*iterator - 1024)); _sharedBMP->setVal(*iterator, shardcst->getResource(MKTAG('B','I','T','D'), *iterator)); @@ -270,12 +288,14 @@ void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Common::Array<uint16> sound = shardcst->getResourceIDList(MKTAG('S','N','D',' ')); if (sound.size() != 0) { - debugC(3, kDebugLoading, "Loading %d SNDs", sound.size()); + debugC(3, kDebugLoading, "****** Loading %d SNDs", sound.size()); for (Common::Array<uint16>::iterator iterator = sound.begin(); iterator != sound.end(); ++iterator) { debugC(3, kDebugLoading, "Shared SND %d", *iterator); _sharedSound->setVal(*iterator, shardcst->getResource(MKTAG('S','N','D',' '), *iterator)); } } + + _sharedScore->loadSpriteImages(true); } } // End of namespace Director diff --git a/engines/director/score.cpp b/engines/director/score.cpp index 1ba0ab4683..472bd739c5 100644 --- a/engines/director/score.cpp +++ b/engines/director/score.cpp @@ -30,6 +30,7 @@ #include "graphics/palette.h" #include "graphics/macgui/macfontmanager.h" #include "graphics/macgui/macwindowmanager.h" +#include "image/bmp.h" #include "director/cast.h" #include "director/score.h" @@ -59,11 +60,10 @@ const char *scriptType2str(ScriptType scr) { } -Score::Score(DirectorEngine *vm, Archive *archive) { +Score::Score(DirectorEngine *vm) { _vm = vm; _surface = new Graphics::ManagedSurface; _trailSurface = new Graphics::ManagedSurface; - _movieArchive = archive; _lingo = _vm->getLingo(); _soundManager = _vm->getSoundManager(); _currentMouseDownSpriteId = 0; @@ -87,6 +87,15 @@ Score::Score(DirectorEngine *vm, Archive *archive) { _stopPlay = false; _stageColor = 0; + _loadedBitmaps = new Common::HashMap<int, BitmapCast *>(); + _loadedText = new Common::HashMap<int, TextCast *>(); + _loadedButtons = new Common::HashMap<int, ButtonCast *>(); + _loadedShapes = new Common::HashMap<int, ShapeCast *>(); + _loadedScripts = new Common::HashMap<int, ScriptCast *>(); +} + +void Score::setArchive(Archive *archive) { + _movieArchive = archive; if (archive->hasResource(MKTAG('M', 'C', 'N', 'M'), 0)) { _macName = archive->getName(MKTAG('M', 'C', 'N', 'M'), 0).c_str(); } else { @@ -111,6 +120,7 @@ void Score::loadArchive() { } else { Common::SeekableSubReadStreamEndian *pal = _movieArchive->getResource(MKTAG('C', 'L', 'U', 'T'), clutList[0]); + debugC(2, kDebugLoading, "****** Loading Palette"); loadPalette(*pal); g_system->getPaletteManager()->setPalette(_vm->getPalette(), 0, _vm->getPaletteColorCount()); } @@ -146,12 +156,16 @@ void Score::loadArchive() { Common::Array<uint16> vwci = _movieArchive->getResourceIDList(MKTAG('V', 'W', 'C', 'I')); if (vwci.size() > 0) { + debugC(2, kDebugLoading, "****** Loading %d CastInfos", vwci.size()); + for (Common::Array<uint16>::iterator iterator = vwci.begin(); iterator != vwci.end(); ++iterator) loadCastInfo(*_movieArchive->getResource(MKTAG('V', 'W', 'C', 'I'), *iterator), *iterator); } Common::Array<uint16> cast = _movieArchive->getResourceIDList(MKTAG('C', 'A', 'S', 't')); if (cast.size() > 0) { + debugC(2, kDebugLoading, "****** Loading %d CASt resources", cast.size()); + for (Common::Array<uint16>::iterator iterator = cast.begin(); iterator != cast.end(); ++iterator) { Common::SeekableSubReadStreamEndian *stream = _movieArchive->getResource(MKTAG('C', 'A', 'S', 't'), *iterator); Resource res = _movieArchive->getResourceDetail(MKTAG('C', 'A', 'S', 't'), *iterator); @@ -160,11 +174,14 @@ void Score::loadArchive() { } setSpriteCasts(); + loadSpriteImages(false); // Try to load movie script, it sits in resource A11 if (_vm->getVersion() <= 3) { Common::Array<uint16> stxt = _movieArchive->getResourceIDList(MKTAG('S','T','X','T')); if (stxt.size() > 0) { + debugC(2, kDebugLoading, "****** Loading %d STXT resources", stxt.size()); + for (Common::Array<uint16>::iterator iterator = stxt.begin(); iterator != stxt.end(); ++iterator) { loadScriptText(*_movieArchive->getResource(MKTAG('S','T','X','T'), *iterator)); } @@ -172,6 +189,65 @@ void Score::loadArchive() { } } +void Score::loadSpriteImages(bool isSharedCast) { + debugC(1, kDebugLoading, "****** Preloading sprite images"); + + Common::HashMap<int, BitmapCast *>::iterator bc; + for (bc = _loadedBitmaps->begin(); bc != _loadedBitmaps->end(); ++bc) { + if (bc->_value) { + uint16 imgId = bc->_key + 1024; + BitmapCast *bitmapCast = bc->_value; + + if (_vm->getVersion() >= 4 && bitmapCast->children.size() > 0) + imgId = bitmapCast->children[0].index; + + Image::ImageDecoder *img = NULL; + + if (_movieArchive->hasResource(MKTAG('D', 'I', 'B', ' '), imgId)) { + img = new DIBDecoder(); + img->loadStream(*_movieArchive->getResource(MKTAG('D', 'I', 'B', ' '), imgId)); + bitmapCast->surface = img->getSurface(); + } + + if (isSharedCast && _vm->getSharedDIB() != NULL && _vm->getSharedDIB()->contains(imgId)) { + img = new DIBDecoder(); + img->loadStream(*_vm->getSharedDIB()->getVal(imgId)); + bitmapCast->surface = img->getSurface(); + } + + Common::SeekableReadStream *pic = NULL; + + if (isSharedCast) { + debugC(4, kDebugImages, "Shared cast BMP: id: %d", imgId); + pic = _vm->getSharedBMP()->getVal(imgId); + if (pic != NULL) + pic->seek(0); // TODO: this actually gets re-read every loop... we need to rewind it! + } else if (_movieArchive->hasResource(MKTAG('B', 'I', 'T', 'D'), imgId)) { + pic = _movieArchive->getResource(MKTAG('B', 'I', 'T', 'D'), imgId); + } + + int w = bitmapCast->initialRect.width(), h = bitmapCast->initialRect.height(); + debugC(4, kDebugImages, "id: %d, w: %d, h: %d, flags: %x, some: %x, unk1: %d, unk2: %d", + imgId, w, h, bitmapCast->flags, bitmapCast->someFlaggyThing, bitmapCast->unk1, bitmapCast->unk2); + + if (pic != NULL && bitmapCast != NULL) { + if (_vm->getVersion() < 4) { + img = new BITDDecoder(w, h); + } else if (_vm->getVersion() < 6) { + img = new BITDDecoderV4(w, h, bitmapCast->bitsPerPixel); + } else { + img = new Image::BitmapDecoder(); + } + + img->loadStream(*pic); + bitmapCast->surface = img->getSurface(); + } + + warning("Image %d not found", imgId); + } + } +} + Score::~Score() { if (_surface) _surface->free(); @@ -210,6 +286,8 @@ void Score::loadPalette(Common::SeekableSubReadStreamEndian &stream) { } void Score::loadFrames(Common::SeekableSubReadStreamEndian &stream) { + debugC(1, kDebugLoading, "****** Loading frames"); + uint32 size = stream.readUint32(); size -= 4; @@ -267,7 +345,7 @@ void Score::loadFrames(Common::SeekableSubReadStreamEndian &stream) { //Common::hexdump(channelData, ARRAYSIZE(channelData)); frame->readChannels(str); - debugC(3, kDebugLoading, "Frame %d actionId: %d", _frames.size() + 1, frame->_actionId); + debugC(3, kDebugLoading, "Frame %d actionId: %d", _frames.size(), frame->_actionId); delete str; @@ -276,6 +354,8 @@ void Score::loadFrames(Common::SeekableSubReadStreamEndian &stream) { } void Score::loadConfig(Common::SeekableSubReadStreamEndian &stream) { + debugC(1, kDebugLoading, "****** Loading Config"); + /*uint16 unk1 = */ stream.readUint16(); /*ver1 = */ stream.readUint16(); _movieRect = Score::readRect(stream); @@ -295,7 +375,7 @@ void Score::readVersion(uint32 rid) { } void Score::loadCastDataVWCR(Common::SeekableSubReadStreamEndian &stream) { - debugC(1, kDebugLoading, "Score::loadCastDataVWCR(). start: %d, end: %d", _castArrayStart, _castArrayEnd); + debugC(1, kDebugLoading, "****** Score::loadCastDataVWCR(). start: %d, end: %d", _castArrayStart, _castArrayEnd); for (uint16 id = _castArrayStart; id <= _castArrayEnd; id++) { byte size = stream.readByte(); @@ -309,20 +389,24 @@ void Score::loadCastDataVWCR(Common::SeekableSubReadStreamEndian &stream) { switch (castType) { case kCastBitmap: - _casts[id] = new BitmapCast(stream); - _casts[id]->type = kCastBitmap; + debugC(3, kDebugLoading, "CastTypes id: %d BitmapCast", id); + _loadedBitmaps->setVal(id, new BitmapCast(stream)); + _castTypes[id] = kCastBitmap; break; case kCastText: - _casts[id] = new TextCast(stream); - _casts[id]->type = kCastText; + debugC(3, kDebugLoading, "CastTypes id: %d TextCast", id); + _loadedText->setVal(id, new TextCast(stream)); + _castTypes[id] = kCastText; break; case kCastShape: - _casts[id] = new ShapeCast(stream); - _casts[id]->type = kCastShape; + debugC(3, kDebugLoading, "CastTypes id: %d ShapeCast", id); + _loadedShapes->setVal(id, new ShapeCast(stream)); + _castTypes[id] = kCastShape; break; case kCastButton: - _casts[id] = new ButtonCast(stream); - _casts[id]->type = kCastButton; + debugC(3, kDebugLoading, "CastTypes id: %d ButtonCast", id); + _loadedButtons->setVal(id, new ButtonCast(stream)); + _castTypes[id] = kCastButton; break; default: warning("Score::loadCastDataVWCR(): Unhandled cast type: %d", castType); @@ -336,10 +420,34 @@ void Score::setSpriteCasts() { // Set cast pointers to sprites for (uint16 i = 0; i < _frames.size(); i++) { for (uint16 j = 0; j < _frames[i]->_sprites.size(); j++) { - byte castId = _frames[i]->_sprites[j]->_castId; + uint16 castId = _frames[i]->_sprites[j]->_castId; + + if (_vm->getSharedScore()->_loadedBitmaps->contains(castId)) { + _frames[i]->_sprites[j]->_bitmapCast = _vm->getSharedScore()->_loadedBitmaps->getVal(castId); + } else if (_loadedBitmaps->contains(castId)) { + _frames[i]->_sprites[j]->_bitmapCast = _loadedBitmaps->getVal(castId); + } + + if (_vm->getSharedScore()->_loadedButtons->contains(castId)) { + _frames[i]->_sprites[j]->_buttonCast = _vm->getSharedScore()->_loadedButtons->getVal(castId); + } else if (_loadedButtons->contains(castId)) { + _frames[i]->_sprites[j]->_buttonCast = _loadedButtons->getVal(castId); + } + + //if (_loadedScripts->contains(castId)) + // _frames[i]->_sprites[j]->_bitmapCast = _loadedBitmaps->getVal(castId); + + if (_vm->getSharedScore()->_loadedText->contains(castId)) { + _frames[i]->_sprites[j]->_textCast = _vm->getSharedScore()->_loadedText->getVal(castId); + } else if (_loadedText->contains(castId)) { + _frames[i]->_sprites[j]->_textCast = _loadedText->getVal(castId); + } - if (_casts.contains(castId)) - _frames[i]->_sprites[j]->_cast = _casts.find(castId)->_value; + if (_vm->getSharedScore()->_loadedShapes->contains(castId)) { + _frames[i]->_sprites[j]->_shapeCast = _vm->getSharedScore()->_loadedShapes->getVal(castId); + } else if (_loadedShapes->contains(castId)) { + _frames[i]->_sprites[j]->_shapeCast = _loadedShapes->getVal(castId); + } } } } @@ -398,35 +506,32 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id, switch (castType) { case kCastBitmap: - _casts[id] = new BitmapCast(castStream, _vm->getVersion()); - _casts[id]->type = kCastBitmap; + _loadedBitmaps->setVal(id, new BitmapCast(castStream, _vm->getVersion())); + for (uint child = 0; child < res->children.size(); child++) + _loadedBitmaps->getVal(id)->children.push_back(res->children[child]); + _castTypes[id] = kCastBitmap; break; case kCastText: - _casts[id] = new TextCast(castStream, _vm->getVersion()); - _casts[id]->type = kCastText; + _loadedText->setVal(id, new TextCast(castStream, _vm->getVersion())); + _castTypes[id] = kCastText; break; case kCastShape: - _casts[id] = new ShapeCast(castStream, _vm->getVersion()); - _casts[id]->type = kCastShape; + _loadedShapes->setVal(id, new ShapeCast(castStream, _vm->getVersion())); + _castTypes[id] = kCastShape; break; case kCastButton: - _casts[id] = new ButtonCast(castStream, _vm->getVersion()); - _casts[id]->type = kCastButton; + _loadedButtons->setVal(id, new ButtonCast(castStream, _vm->getVersion())); + _castTypes[id] = kCastButton; break; case kCastLingoScript: - _casts[id] = new ScriptCast(castStream, _vm->getVersion()); - _casts[id]->type = kCastLingoScript; + _loadedScripts->setVal(id, new ScriptCast(castStream, _vm->getVersion())); + _castTypes[id] = kCastLingoScript; break; default: warning("Score::loadCastData(): Unhandled cast type: %d", castType); break; } - if (res != NULL) { - for (uint child = 0; child < res->children.size(); child++) - _casts[id]->children.push_back(res->children[child]); - } - free(data); if (size2) { @@ -467,6 +572,60 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id, warning("size3: %x", size3); } +void Score::loadCastInto(Sprite *sprite, int castId) { + switch (_castTypes[castId]) { + case kCastBitmap: + sprite->_bitmapCast = _loadedBitmaps->getVal(castId); + break; + case kCastShape: + sprite->_shapeCast = _loadedShapes->getVal(castId); + break; + case kCastButton: + sprite->_buttonCast = _loadedButtons->getVal(castId); + break; + case kCastText: + sprite->_textCast = _loadedText->getVal(castId); + break; + default: + warning("Score::loadCastInto(..., %d): Unhandled castType %d", castId, _castTypes[castId]); + } +} + +Common::Rect Score::getCastMemberInitialRect(int castId) { + switch (_castTypes[castId]) { + case kCastBitmap: + return _loadedBitmaps->getVal(castId)->initialRect; + case kCastShape: + return _loadedShapes->getVal(castId)->initialRect; + case kCastButton: + return _loadedButtons->getVal(castId)->initialRect; + case kCastText: + return _loadedText->getVal(castId)->initialRect; + default: + warning("Score::getCastMemberInitialRect(%d): Unhandled castType %d", castId, _castTypes[castId]); + return Common::Rect(0, 0); + } +} + +void Score::setCastMemberModified(int castId) { + switch (_castTypes[castId]) { + case kCastBitmap: + _loadedBitmaps->getVal(castId)->modified = 1; + break; + case kCastShape: + _loadedShapes->getVal(castId)->modified = 1; + break; + case kCastButton: + _loadedButtons->getVal(castId)->modified = 1; + break; + case kCastText: + _loadedText->getVal(castId)->modified = 1; + break; + default: + warning("Score::setCastMemberModified(%d): Unhandled castType %d", castId, _castTypes[castId]); + } +} + void Score::loadLabels(Common::SeekableSubReadStreamEndian &stream) { _labels = new Common::SortedArray<Label *>(compareLabels); uint16 count = stream.readUint16() + 1; @@ -496,6 +655,7 @@ void Score::loadLabels(Common::SeekableSubReadStreamEndian &stream) { Common::SortedArray<Label *>::iterator j; + debugC(2, kDebugLoading, "****** Loading labels"); for (j = _labels->begin(); j != _labels->end(); ++j) { debugC(2, kDebugLoading, "Frame %d, Label %s", (*j)->number, (*j)->name.c_str()); } @@ -506,6 +666,8 @@ int Score::compareLabels(const void *a, const void *b) { } void Score::loadActions(Common::SeekableSubReadStreamEndian &stream) { + debugC(2, kDebugLoading, "****** Loading Actions"); + uint16 count = stream.readUint16() + 1; uint16 offset = count * 4 + 2; @@ -530,7 +692,7 @@ void Score::loadActions(Common::SeekableSubReadStreamEndian &stream) { _actions[i + 1] += ch; } - debugC(3, kDebugLoading, "id: %d nextId: %d subId: %d, code: %s", id, nextId, subId, _actions[id].c_str()); + debugC(3, kDebugLoading, "Action id: %d nextId: %d subId: %d, code: %s", id, nextId, subId, _actions[id].c_str()); stream.seek(streamPos); @@ -551,8 +713,22 @@ void Score::loadActions(Common::SeekableSubReadStreamEndian &stream) { } for (j = _actions.begin(); j != _actions.end(); ++j) - if (!j->_value.empty()) + if (!j->_value.empty()) { _lingo->addCode(j->_value.c_str(), kFrameScript, j->_key); + + processImmediateFrameScript(j->_value, j->_key); + } +} + +bool Score::processImmediateFrameScript(Common::String s, int id) { + s.trim(); + + // In D2/D3 this specifies immediately the sprite/field properties + if (!s.compareToIgnoreCase("moveableSprite") || !s.compareToIgnoreCase("editableText")) { + _immediateActions[id] = true; + } + + return false; } void Score::loadScriptText(Common::SeekableSubReadStreamEndian &stream) { @@ -621,6 +797,9 @@ void Score::dumpScript(const char *script, ScriptType type, uint16 id) { case kCastScript: typeName = "cast"; break; + case kGlobalScript: + typeName = "global"; + break; } sprintf(buf, "./dumps/%s-%s-%d.txt", _macName.c_str(), typeName.c_str(), id); @@ -776,6 +955,8 @@ Common::String Score::getString(Common::String str) { } void Score::loadFileInfo(Common::SeekableSubReadStreamEndian &stream) { + debugC(2, kDebugLoading, "****** Loading FileInfo"); + Common::Array<Common::String> fileInfoStrings = loadStrings(stream, _flags); _script = fileInfoStrings[0]; @@ -805,6 +986,8 @@ Common::Array<Common::String> Score::loadStrings(Common::SeekableSubReadStreamEn uint16 count = stream.readUint16() + 1; + debugC(3, kDebugLoading, "Strings: %d entries", count); + uint32 *entries = (uint32 *)calloc(count, sizeof(uint32)); for (uint i = 0; i < count; i++) @@ -823,6 +1006,8 @@ Common::Array<Common::String> Score::loadStrings(Common::SeekableSubReadStreamEn entryString += data[j]; strings.push_back(entryString); + + debugC(6, kDebugLoading, "String %d:\n%s\n", i, entryString.c_str()); } free(data); @@ -835,6 +1020,8 @@ void Score::loadFontMap(Common::SeekableSubReadStreamEndian &stream) { if (stream.size() == 0) return; + debugC(2, kDebugLoading, "****** Loading FontMap"); + uint16 count = stream.readUint16(); uint32 offset = (count * 2) + 2; uint16 currentRawPosition = offset; @@ -855,7 +1042,7 @@ void Score::loadFontMap(Common::SeekableSubReadStreamEndian &stream) { _fontMap[id] = font; _vm->_wm->_fontMan->registerFontMapping(id, font); - debug(3, "Fontmap. ID %d Font %s", id, font.c_str()); + debugC(3, kDebugLoading, "Fontmap. ID %d Font %s", id, font.c_str()); currentRawPosition = stream.pos(); stream.seek(positionInfo); } @@ -902,9 +1089,10 @@ void Score::update() { _surface->clear(); _surface->copyFrom(*_trailSurface); + _frames[_currentFrame]->executeImmediateScripts(); + // Enter and exit from previous frame (Director 4) _lingo->processEvent(kEventEnterFrame, kFrameScript, _frames[_currentFrame]->_actionId); - _lingo->processEvent(kEventExitFrame, kFrameScript, _frames[_currentFrame]->_actionId); // TODO Director 6 - another order // TODO Director 6 step: send beginSprite event to any sprites whose span begin in the upcoming frame @@ -972,6 +1160,8 @@ void Score::update() { } } + _lingo->processEvent(kEventExitFrame, kFrameScript, _frames[_currentFrame]->_actionId); + _nextFrameTime = g_system->getMillis() + (float)_currentFrameRate / 60 * 1000; } diff --git a/engines/director/score.h b/engines/director/score.h index 3e7aa62c4f..021dcb5577 100644 --- a/engines/director/score.h +++ b/engines/director/score.h @@ -26,6 +26,8 @@ #include "common/substream.h" #include "common/rect.h" #include "director/archive.h" +#include "director/cast.h" +#include "director/images.h" namespace Graphics { class ManagedSurface; @@ -48,15 +50,16 @@ enum ScriptType { kSpriteScript = 1, kFrameScript = 2, kCastScript = 3, + kGlobalScript = 4, kNoneScript = -1, - kMaxScriptType = 3 + kMaxScriptType = 4 }; const char *scriptType2str(ScriptType scr); class Score { public: - Score(DirectorEngine *vm, Archive *); + Score(DirectorEngine *vm); ~Score(); static Common::Rect readRect(Common::ReadStreamEndian &stream); @@ -67,6 +70,7 @@ public: void gotoNext(); void gotoPrevious(); void startLoop(); + void setArchive(Archive *archive); Archive *getArchive() const { return _movieArchive; }; void loadConfig(Common::SeekableSubReadStreamEndian &stream); void loadCastDataVWCR(Common::SeekableSubReadStreamEndian &stream); @@ -77,8 +81,13 @@ public: Common::String getMacName() const { return _macName; } Sprite *getSpriteById(uint16 id); void setSpriteCasts(); + void loadSpriteImages(bool isSharedCast); Graphics::ManagedSurface *getSurface() { return _surface; } + void loadCastInto(Sprite *sprite, int castId); + Common::Rect getCastMemberInitialRect(int castId); + void setCastMemberModified(int castId); + int getPreviousLabelNumber(int referenceFrame); int getCurrentLabelNumber(); int getNextLabelNumber(int referenceFrame); @@ -97,13 +106,16 @@ private: Common::String getString(Common::String str); Common::Array<Common::String> loadStrings(Common::SeekableSubReadStreamEndian &stream, uint32 &entryType, bool hasHeader = true); + bool processImmediateFrameScript(Common::String s, int id); + public: Common::Array<Frame *> _frames; - Common::HashMap<int, Cast *> _casts; + Common::HashMap<int, CastType> _castTypes; Common::HashMap<uint16, CastInfo *> _castsInfo; Common::HashMap<Common::String, int> _castsNames; Common::SortedArray<Label *> *_labels; Common::HashMap<uint16, Common::String> _actions; + Common::HashMap<uint16, bool> _immediateActions; Common::HashMap<uint16, Common::String> _fontMap; Graphics::ManagedSurface *_surface; Graphics::ManagedSurface *_trailSurface; @@ -115,6 +127,13 @@ public: bool _stopPlay; uint32 _nextFrameTime; + Common::HashMap<int, ButtonCast *> *_loadedButtons; + Common::HashMap<int, TextCast *> *_loadedText; + //Common::HashMap<int, SoundCast *> _loadedSound; + Common::HashMap<int, BitmapCast *> *_loadedBitmaps; + Common::HashMap<int, ShapeCast *> *_loadedShapes; + Common::HashMap<int, ScriptCast *> *_loadedScripts; + private: uint16 _versionMinor; uint16 _versionMajor; diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp index 019966762e..9d219d6076 100644 --- a/engines/director/sprite.cpp +++ b/engines/director/sprite.cpp @@ -53,7 +53,11 @@ Sprite::Sprite() { _stretch = 0; _type = kInactiveSprite; - _cast = nullptr; + _bitmapCast = nullptr; + _textCast = nullptr; + _buttonCast = nullptr; + _shapeCast = nullptr; + _blend = 0; _lineSize = 1; @@ -90,7 +94,11 @@ Sprite::Sprite(const Sprite &sprite) { _stretch = sprite._stretch; _type = sprite._type; - _cast = sprite._cast; + _bitmapCast = sprite._bitmapCast; + _shapeCast = sprite._shapeCast; + _textCast = sprite._textCast; + _buttonCast = sprite._buttonCast; + _constraint = sprite._constraint; _moveable = sprite._moveable; _blend = sprite._blend; @@ -107,7 +115,14 @@ Sprite::Sprite(const Sprite &sprite) { } Sprite::~Sprite() { - delete _cast; + if (_bitmapCast) + delete _bitmapCast; + if (_shapeCast) + delete _shapeCast; + if (_textCast) + delete _textCast; + if (_buttonCast) + delete _buttonCast; } } // End of namespace Director diff --git a/engines/director/sprite.h b/engines/director/sprite.h index c43418828c..de1965dc2a 100644 --- a/engines/director/sprite.h +++ b/engines/director/sprite.h @@ -110,7 +110,14 @@ public: byte _spriteType; InkType _ink; uint16 _trails; - Cast *_cast; + + BitmapCast *_bitmapCast; + ShapeCast *_shapeCast; + //SoundCast *_soundCast; + TextCast *_textCast; + ButtonCast *_buttonCast; + //ScriptCast *_scriptCast; + uint16 _flags; Common::Point _startPoint; uint16 _width; diff --git a/engines/director/util.cpp b/engines/director/util.cpp index ccde2b3127..dbd1cd351f 100644 --- a/engines/director/util.cpp +++ b/engines/director/util.cpp @@ -48,7 +48,7 @@ char *numToCastNum(int num) { res[3] = '\0'; num--; - if (num > 0 && num <= 512) { + if (num >= 0 && num < 512) { int c = num / 64; res[0] = 'A' + c; num -= 64 * c; |