diff options
-rw-r--r-- | engines/director/archive.cpp | 49 | ||||
-rw-r--r-- | engines/director/archive.h | 16 | ||||
-rw-r--r-- | engines/director/cast.cpp | 20 | ||||
-rw-r--r-- | engines/director/cast.h | 2 | ||||
-rw-r--r-- | engines/director/director.h | 1 | ||||
-rw-r--r-- | engines/director/frame.cpp | 360 | ||||
-rw-r--r-- | engines/director/frame.h | 8 | ||||
-rw-r--r-- | engines/director/images.cpp | 118 | ||||
-rw-r--r-- | engines/director/images.h | 19 | ||||
-rw-r--r-- | engines/director/lingo/lingo-builtins.cpp | 4 | ||||
-rw-r--r-- | engines/director/lingo/lingo-funcs.cpp | 35 | ||||
-rw-r--r-- | engines/director/lingo/lingo.h | 4 | ||||
-rw-r--r-- | engines/director/resource.cpp | 2 | ||||
-rw-r--r-- | engines/director/score.cpp | 53 | ||||
-rw-r--r-- | engines/director/score.h | 3 | ||||
-rw-r--r-- | engines/director/sound.cpp | 10 | ||||
-rw-r--r-- | engines/director/sound.h | 4 | ||||
-rw-r--r-- | engines/director/sprite.h | 3 | ||||
-rw-r--r-- | graphics/macgui/macwindowmanager.cpp | 70 | ||||
-rw-r--r-- | graphics/macgui/macwindowmanager.h | 4 |
20 files changed, 625 insertions, 160 deletions
diff --git a/engines/director/archive.cpp b/engines/director/archive.cpp index 5b1a26ffd4..398b287b90 100644 --- a/engines/director/archive.cpp +++ b/engines/director/archive.cpp @@ -100,6 +100,18 @@ Common::SeekableSubReadStreamEndian *Archive::getResource(uint32 tag, uint16 id) return new Common::SeekableSubReadStreamEndian(_stream, res.offset, res.offset + res.size, _isBigEndian, DisposeAfterUse::NO); } +Resource Archive::getResourceDetail(uint32 tag, uint16 id) { + if (!_types.contains(tag)) + error("Archive does not contain '%s' %04x", tag2str(tag), id); + + const ResourceMap &resMap = _types[tag]; + + if (!resMap.contains(id)) + error("Archive does not contain '%s' %04x", tag2str(tag), id); + + return resMap[id]; +} + uint32 Archive::getOffset(uint32 tag, uint16 id) const { if (!_types.contains(tag)) error("Archive does not contain '%s' %04x", tag2str(tag), id); @@ -365,6 +377,7 @@ bool RIFXArchive::openStream(Common::SeekableReadStream *stream, uint32 startOff subStream.readUint32(); // unknown Common::Array<Resource> resources; + resources.reserve(2048); // Need to look for these two resources const Resource *keyRes = 0; @@ -395,6 +408,8 @@ bool RIFXArchive::openStream(Common::SeekableReadStream *stream, uint32 startOff keyRes = &resources[resources.size() - 1]; else if (tag == MKTAG('C', 'A', 'S', '*')) casRes = &resources[resources.size() - 1]; + else + _types[tag][i] = res; } // We need to have found the 'File' resource already @@ -409,6 +424,8 @@ bool RIFXArchive::openStream(Common::SeekableReadStream *stream, uint32 startOff return false; } + uint castTag = MKTAG('C', 'A', 'S', 't'); + // Parse the CAS*, if present if (casRes) { Common::SeekableSubReadStreamEndian casStream(stream, casRes->offset + 8, casRes->offset + 8 + casRes->size, _isBigEndian, DisposeAfterUse::NO); @@ -420,8 +437,10 @@ bool RIFXArchive::openStream(Common::SeekableReadStream *stream, uint32 startOff for (uint i = 0; i < casSize; i++) { uint32 index = casStream.readUint32(); - const Resource &res = resources[index]; - _types[MKTAG('C', 'A', 'S', 't')][i + 1] = res; + Resource &res = resources[index]; + res.index = index; + res.castId = i + 1; + _types[castTag][res.castId] = res; debugCN(2, kDebugLoading, "%d ", index); } @@ -444,10 +463,20 @@ bool RIFXArchive::openStream(Common::SeekableReadStream *stream, uint32 startOff debugC(2, kDebugLoading, "KEY*: index: %d id: %d resTag: %s", index, id, tag2str(resTag)); - const Resource &res = resources[index]; + Resource &res = resources[index]; debug(3, "Found RIFX resource: '%s' id: 0x%04x, %d @ 0x%08x (%d)", tag2str(resTag), id, res.size, res.offset, res.offset); _types[resTag][id] = res; - _types[resTag][1024 + i + 1] = res; + //_types[resTag][1024 + i + 1] = res; + + if (id < 1024) { + for (uint cast = 0; cast < _types[castTag].size(); cast++) { + if (_types[castTag][cast].index == id) { + res.index = index; + _types[castTag][cast].children.push_back(res); + break; + } + } + } } _stream = stream; @@ -471,5 +500,17 @@ Common::SeekableSubReadStreamEndian *RIFXArchive::getResource(uint32 tag, uint16 return new Common::SeekableSubReadStreamEndian(_stream, offset, offset + size, true, DisposeAfterUse::NO); } +Resource RIFXArchive::getResourceDetail(uint32 tag, uint16 id) { + if (!_types.contains(tag)) + error("Archive does not contain '%s' %04x", tag2str(tag), id); + + const ResourceMap &resMap = _types[tag]; + + if (!resMap.contains(id)) + error("Archive does not contain '%s' %04x", tag2str(tag), id); + + return resMap[id]; +} + } // End of namespace Director diff --git a/engines/director/archive.h b/engines/director/archive.h index 93f4ce7ee9..b77bace9ba 100644 --- a/engines/director/archive.h +++ b/engines/director/archive.h @@ -33,6 +33,15 @@ class MacResManager; namespace Director { // Completely ripped off of Mohawk's Archive code + +struct Resource { + uint32 index; + uint32 offset; + uint32 size; + uint32 castId; + Common::String name; + Common::Array<Resource> children; +}; class Archive { public: @@ -50,6 +59,7 @@ public: bool hasResource(uint32 tag, uint16 id) const; bool hasResource(uint32 tag, const Common::String &resName) const; virtual Common::SeekableSubReadStreamEndian *getResource(uint32 tag, uint16 id); + virtual Resource getResourceDetail(uint32 tag, uint16 id); uint32 getOffset(uint32 tag, uint16 id) const; uint16 findResourceID(uint32 tag, const Common::String &resName) const; Common::String getName(uint32 tag, uint16 id) const; @@ -61,11 +71,6 @@ public: protected: Common::SeekableReadStream *_stream; - struct Resource { - uint32 offset; - uint32 size; - Common::String name; - }; typedef Common::HashMap<uint16, Resource> ResourceMap; typedef Common::HashMap<uint32, ResourceMap> TypeMap; TypeMap _types; @@ -103,6 +108,7 @@ public: bool openStream(Common::SeekableReadStream *stream, uint32 startOffset = 0); Common::SeekableSubReadStreamEndian *getResource(uint32 tag, uint16 id); + Resource getResourceDetail(uint32 tag, uint16 id); }; } // End of namespace Director diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp index 892ac48f8c..81637b9684 100644 --- a/engines/director/cast.cpp +++ b/engines/director/cast.cpp @@ -41,6 +41,9 @@ BitmapCast::BitmapCast(Common::ReadStreamEndian &stream, uint16 version) { unk2 = stream.readUint16(); } } else { + stream.readByte(); + stream.readByte(); + initialRect = Score::readRect(stream); boundingRect = Score::readRect(stream); regX = stream.readUint16(); @@ -59,8 +62,10 @@ BitmapCast::BitmapCast(Common::ReadStreamEndian &stream, uint16 version) { } TextCast::TextCast(Common::ReadStreamEndian &stream, uint16 version) { - if (version < 4) { - flags1 = stream.readByte(); + if (version < 5) { + if (version <= 3) + flags1 = stream.readByte(); + borderSize = static_cast<SizeType>(stream.readByte()); gutterSize = static_cast<SizeType>(stream.readByte()); boxShadow = static_cast<SizeType>(stream.readByte()); @@ -109,6 +114,9 @@ ShapeCast::ShapeCast(Common::ReadStreamEndian &stream, uint16 version) { lineThickness = stream.readByte(); lineDirection = stream.readByte(); } else { + stream.readByte(); + stream.readByte(); + initialRect = Score::readRect(stream); boundingRect = Score::readRect(stream); } @@ -119,8 +127,13 @@ ButtonCast::ButtonCast(Common::ReadStreamEndian &stream, uint16 version) : TextC if (version < 4) { buttonType = static_cast<ButtonType>(stream.readUint16BE()); } else { + stream.readByte(); + stream.readByte(); + initialRect = Score::readRect(stream); boundingRect = Score::readRect(stream); + + buttonType = static_cast<ButtonType>(stream.readUint16BE()); } modified = 0; } @@ -129,6 +142,9 @@ ScriptCast::ScriptCast(Common::ReadStreamEndian &stream, uint16 version) { if (version < 4) { error("Unhandled Script cast"); } else { + stream.readByte(); + stream.readByte(); + initialRect = Score::readRect(stream); boundingRect = Score::readRect(stream); diff --git a/engines/director/cast.h b/engines/director/cast.h index 69edf8ce89..a739ccc25d 100644 --- a/engines/director/cast.h +++ b/engines/director/cast.h @@ -25,6 +25,7 @@ #include "common/rect.h" #include "common/substream.h" +#include "director/archive.h" namespace Director { @@ -46,6 +47,7 @@ struct Cast { CastType type; Common::Rect initialRect; Common::Rect boundingRect; + Common::Array<Resource> children; byte modified; }; diff --git a/engines/director/director.h b/engines/director/director.h index 7ec9608662..ead143758e 100644 --- a/engines/director/director.h +++ b/engines/director/director.h @@ -73,6 +73,7 @@ public: Common::Language getLanguage() const; Common::String getEXEName() const; DirectorSound *getSoundManager() const { return _soundManager; } + Graphics::MacWindowManager *getMacWindowManager() const { return _wm; } Archive *getMainArchive() const { return _mainArchive; } Lingo *getLingo() const { return _lingo; } Score *getCurrentScore() const { return _currentScore; } diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp index de0de6d4d0..7c52cf8ba7 100644 --- a/engines/director/frame.cpp +++ b/engines/director/frame.cpp @@ -114,54 +114,61 @@ void Frame::readChannel(Common::SeekableSubReadStreamEndian &stream, uint16 offs } void Frame::readChannels(Common::ReadStreamEndian *stream) { - _actionId = stream->readByte(); - _soundType1 = stream->readByte(); // type: 0x17 for sounds (sound is cast id), 0x16 for MIDI (sound is cmd id) - uint8 transFlags = stream->readByte(); // 0x80 is whole stage (vs changed area), rest is duration in 1/4ths of a second - - if (transFlags & 0x80) - _transArea = 1; - else - _transArea = 0; - _transDuration = transFlags & 0x7f; - - _transChunkSize = stream->readByte(); - _tempo = stream->readByte(); - _transType = static_cast<TransitionType>(stream->readByte()); - _sound1 = stream->readUint16(); - if (_vm->getPlatform() == Common::kPlatformMacintosh) { - _sound2 = stream->readUint16(); - _soundType2 = stream->readByte(); - } else { - byte unk[3]; - stream->read(unk, 3); - warning("unk1: %x unk2: %x unk3: %x", unk[0], unk[1], unk[2]); - } - _skipFrameFlag = stream->readByte(); - _blend = stream->readByte(); + byte unk[16]; - if (_vm->getPlatform() != Common::kPlatformMacintosh) { - _sound2 = stream->readUint16(); - _soundType2 = stream->readByte(); - } + if (_vm->getVersion() < 4) { + _actionId = stream->readByte(); + _soundType1 = stream->readByte(); // type: 0x17 for sounds (sound is cast id), 0x16 for MIDI (sound is cmd id) + uint8 transFlags = stream->readByte(); // 0x80 is whole stage (vs changed area), rest is duration in 1/4ths of a second - uint16 palette = stream->readUint16(); + if (transFlags & 0x80) + _transArea = 1; + else + _transArea = 0; + _transDuration = transFlags & 0x7f; + + _transChunkSize = stream->readByte(); + _tempo = stream->readByte(); + _transType = static_cast<TransitionType>(stream->readByte()); + _sound1 = stream->readUint16(); + if (_vm->getPlatform() == Common::kPlatformMacintosh) { + _sound2 = stream->readUint16(); + _soundType2 = stream->readByte(); + } else { + stream->read(unk, 3); + warning("unk1: %x unk2: %x unk3: %x", unk[0], unk[1], unk[2]); + } + _skipFrameFlag = stream->readByte(); + _blend = stream->readByte(); - if (palette) { - warning("STUB: Palette info"); - } + if (_vm->getPlatform() != Common::kPlatformMacintosh) { + _sound2 = stream->readUint16(); + _soundType2 = stream->readByte(); + } - debugC(kDebugLoading, 8, "%d %d %d %d %d %d %d %d %d %d %d", _actionId, _soundType1, _transDuration, _transChunkSize, _tempo, _transType, _sound1, _skipFrameFlag, _blend, _sound2, _soundType2); + uint16 palette = stream->readUint16(); - _palette = new PaletteInfo(); - _palette->firstColor = stream->readByte(); // for cycles. note: these start at 0x80 (for pal entry 0)! - _palette->lastColor = stream->readByte(); - _palette->flags = stream->readByte(); - _palette->speed = stream->readByte(); - _palette->frameCount = stream->readUint16(); + if (palette) { + warning("STUB: Palette info"); + } + + debugC(kDebugLoading, 8, "%d %d %d %d %d %d %d %d %d %d %d", _actionId, _soundType1, _transDuration, _transChunkSize, _tempo, _transType, _sound1, _skipFrameFlag, _blend, _sound2, _soundType2); + + _palette = new PaletteInfo(); + _palette->firstColor = stream->readByte(); // for cycles. note: these start at 0x80 (for pal entry 0)! + _palette->lastColor = stream->readByte(); + _palette->flags = stream->readByte(); + _palette->speed = stream->readByte(); + _palette->frameCount = stream->readUint16(); + + _palette->cycleCount = stream->readUint16(); + } else if (_vm->getVersion() < 5) { + stream->read(unk, 16); + _actionId = stream->readUint16(); + stream->read(unk, 5); + } - _palette->cycleCount = stream->readUint16(); - byte unk[11]; stream->read(unk, 6); if (_vm->getPlatform() == Common::kPlatformMacintosh) { @@ -181,8 +188,9 @@ void Frame::readChannels(Common::ReadStreamEndian *stream) { for (int i = 0; i < CHANNEL_COUNT; i++) { Sprite &sprite = *_sprites[i + 1]; - sprite._x1 = stream->readByte(); - sprite._enabled = (stream->readByte() != 0); + sprite._scriptId = stream->readByte(); + sprite._spriteType = stream->readByte(); + sprite._enabled = sprite._spriteType != 0; sprite._x2 = stream->readUint16(); sprite._flags = stream->readUint16(); @@ -199,8 +207,6 @@ void Frame::readChannels(Common::ReadStreamEndian *stream) { sprite._height = stream->readUint16(); sprite._width = stream->readUint16(); - debugC(kDebugLoading, 8, "%03d(%d)[%x,%x,%04x,%d/%d/%d/%d]", sprite._castId, sprite._enabled, sprite._x1, sprite._x2, sprite._flags, sprite._startPoint.x, sprite._startPoint.y, sprite._width, sprite._height); - if (_vm->getPlatform() == Common::kPlatformMacintosh && _vm->getVersion() >= 4) { sprite._scriptId = stream->readUint16(); sprite._flags2 = stream->readByte(); // 0x40 editable, 0x80 moveable @@ -209,6 +215,10 @@ void Frame::readChannels(Common::ReadStreamEndian *stream) { if (_vm->getVersion() >= 5) sprite._unk3 = stream->readUint32(); } + + debugC(kDebugLoading, 8, "%03d(%d)[%x,%x,%04x,%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._scriptId); } } @@ -360,6 +370,7 @@ void Frame::readSprite(Common::SeekableSubReadStreamEndian &stream, uint16 offse } void Frame::prepareFrame(Score *score) { + _drawRects.clear(); renderSprites(*score->_surface, false); renderSprites(*score->_trailSurface, true); @@ -529,82 +540,144 @@ void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) { if ((_sprites[i]->_trails == 0 && renderTrail) || (_sprites[i]->_trails == 1 && !renderTrail)) continue; + CastType castType; Cast *cast; - if (!_vm->_currentScore->_casts.contains(_sprites[i]->_castId)) { - if (!_vm->getSharedCasts()->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); + if (_vm->getVersion() < 4) { + switch (_sprites[i]->_spriteType) { + case 0x01: + case 0x0c: //this is actually a mouse-over shape? I don't think it's a real button. + castType = kCastBitmap; + break; + case 0x02: + castType = kCastShape; + break; + case 0x07: + castType = kCastText; + break; } } else { - cast = _vm->_currentScore->_casts[_sprites[i]->_castId]; - } - - if (cast->type == kCastText) { - renderText(surface, i); - continue; + if (!_vm->_currentScore->_casts.contains(_sprites[i]->_castId)) { + if (!_vm->getSharedCasts()->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); + } + } else { + cast = _vm->_currentScore->_casts[_sprites[i]->_castId]; + } + castType = cast->type; } - Image::ImageDecoder *img = getImageFrom(_sprites[i]->_castId); + //this needs precedence to be hit first... D3 does something really tricky with cast IDs for shapes. + //I don't like this implementation 100% as the 'cast' above might not actually hit a member and be null? + if (castType == kCastShape) { + renderShape(surface, i); + } else if (castType == kCastText) { + renderText(surface, i, _vm->getVersion() < 4 ? _sprites[i]->_castId + 1024 : cast->children[0].index); + } 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 not found", _sprites[i]->_castId); - continue; - } + if (!img) { + warning("Image with id %d not found", _sprites[i]->_castId); + continue; + } - if (!img->getSurface()) { - warning("Frame::renderSprites: Could not load image %d", _sprites[i]->_castId); - continue; - } + if (!img->getSurface()) { + warning("Frame::renderSprites: Could not load image %d", _sprites[i]->_castId); + continue; + } - assert(_sprites[i]->_cast); - - uint32 regX = static_cast<BitmapCast *>(_sprites[i]->_cast)->regX; - uint32 regY = static_cast<BitmapCast *>(_sprites[i]->_cast)->regY; - uint32 rectLeft = static_cast<BitmapCast *>(_sprites[i]->_cast)->initialRect.left; - uint32 rectTop = static_cast<BitmapCast *>(_sprites[i]->_cast)->initialRect.top; - - int x = _sprites[i]->_startPoint.x - regX + rectLeft; - int y = _sprites[i]->_startPoint.y - regY + rectTop; - int height = _sprites[i]->_height; - int width = _sprites[i]->_width; - - Common::Rect drawRect = Common::Rect(x, y, x + width, y + height); - _drawRects.push_back(drawRect); - - switch (_sprites[i]->_ink) { - case kInkTypeCopy: - surface.blitFrom(*img->getSurface(), Common::Point(x, y)); - break; - case kInkTypeTransparent: - // FIXME: is it always white (last entry in pallette)? - surface.transBlitFrom(*img->getSurface(), Common::Point(x, y), _vm->getPaletteColorCount() - 1); - break; - case kInkTypeBackgndTrans: - drawBackgndTransSprite(surface, *img->getSurface(), drawRect); - break; - case kInkTypeMatte: - drawMatteSprite(surface, *img->getSurface(), drawRect); - break; - case kInkTypeGhost: - drawGhostSprite(surface, *img->getSurface(), drawRect); - break; - case kInkTypeReverse: - drawReverseSprite(surface, *img->getSurface(), drawRect); - break; - default: - warning("Unhandled ink type %d", _sprites[i]->_ink); - surface.blitFrom(*img->getSurface(), Common::Point(x, y)); - break; + assert(_sprites[i]->_cast); + + uint32 regX = static_cast<BitmapCast *>(_sprites[i]->_cast)->regX; + uint32 regY = static_cast<BitmapCast *>(_sprites[i]->_cast)->regY; + uint32 rectLeft = static_cast<BitmapCast *>(_sprites[i]->_cast)->initialRect.left; + uint32 rectTop = static_cast<BitmapCast *>(_sprites[i]->_cast)->initialRect.top; + + int x = _sprites[i]->_startPoint.x - regX + rectLeft; + int y = _sprites[i]->_startPoint.y - regY + rectTop; + int height = _sprites[i]->_height; + int width = _sprites[i]->_width; + + Common::Rect drawRect = Common::Rect(x, y, x + width, y + height); + _drawRects[i] = drawRect; + + switch (_sprites[i]->_ink) { + case kInkTypeCopy: + surface.blitFrom(*img->getSurface(), Common::Point(x, y)); + break; + case kInkTypeTransparent: + // FIXME: is it always white (last entry in pallette)? + surface.transBlitFrom(*img->getSurface(), Common::Point(x, y), _vm->getPaletteColorCount() - 1); + break; + case kInkTypeBackgndTrans: + drawBackgndTransSprite(surface, *img->getSurface(), drawRect); + break; + case kInkTypeMatte: + drawMatteSprite(surface, *img->getSurface(), drawRect); + break; + case kInkTypeGhost: + drawGhostSprite(surface, *img->getSurface(), drawRect); + break; + case kInkTypeReverse: + drawReverseSprite(surface, *img->getSurface(), drawRect); + break; + default: + warning("Unhandled ink type %d", _sprites[i]->_ink); + surface.blitFrom(*img->getSurface(), Common::Point(x, y)); + break; + } } } } } -void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId) { - renderText(surface, spriteId); +void Frame::renderShape(Graphics::ManagedSurface &surface, uint16 spriteID) { + Common::Rect r = Common::Rect(_sprites[spriteID]->_startPoint.x, + _sprites[spriteID]->_startPoint.y, + _sprites[spriteID]->_startPoint.x + _sprites[spriteID]->_width, + _sprites[spriteID]->_startPoint.y + _sprites[spriteID]->_height); + + Graphics::Surface tmpSurface; + tmpSurface.create(r.width(), r.height(), Graphics::PixelFormat::createFormatCLUT8()); + + tmpSurface.fillRect(Common::Rect(r.width(), r.height()), 0); + + switch (_sprites[spriteID]->_ink) { + case kInkTypeCopy: + surface.blitFrom(tmpSurface, Common::Point(_sprites[spriteID]->_startPoint.x, _sprites[spriteID]->_startPoint.y)); + break; + case kInkTypeTransparent: + // FIXME: is it always white (last entry in pallette)? + surface.transBlitFrom(tmpSurface, Common::Point(_sprites[spriteID]->_startPoint.x, _sprites[spriteID]->_startPoint.y), _vm->getPaletteColorCount() - 1); + break; + case kInkTypeBackgndTrans: + drawBackgndTransSprite(surface, tmpSurface, r); + break; + case kInkTypeMatte: + drawMatteSprite(surface, tmpSurface, r); + break; + case kInkTypeGhost: + drawGhostSprite(surface, tmpSurface, r); + break; + case kInkTypeReverse: + drawReverseSprite(surface, tmpSurface, r); + break; + default: + warning("Unhandled ink type %d", _sprites[spriteID]->_ink); + surface.blitFrom(tmpSurface, Common::Point(_sprites[spriteID]->_startPoint.x, _sprites[spriteID]->_startPoint.y)); + break; + } + + _drawRects[spriteID] = r; +} + +void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId, uint16 textId) { + renderText(surface, spriteId, _vm->getMainArchive()->getResource(MKTAG('S', 'T', 'X', 'T'), textId), true); uint16 castID = _sprites[spriteId]->_castId; ButtonCast *button = static_cast<ButtonCast *>(_vm->_currentScore->_casts[castID]); @@ -617,13 +690,19 @@ void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId) { int height = _sprites[spriteId]->_height; int width = _sprites[spriteId]->_width; + Common::Rect _rect; + switch (button->buttonType) { case kTypeCheckBox: // Magic numbers: checkbox square need to move left about 5px from text and 12px side size (D4) - surface.frameRect(Common::Rect(x - 17, y, x + 12, y + 12), 0); + _rect = Common::Rect(x - 17, y, x + 12, y + 12); + surface.frameRect(_rect, 0); + _drawRects[spriteId] = _rect; break; case kTypeButton: - surface.frameRect(Common::Rect(x, y, x + width, y + height), 0); + _rect = Common::Rect(x, y, x + width, y + height); + surface.frameRect(_rect, 0); + _drawRects[spriteId] = _rect; break; case kTypeRadio: warning("STUB: renderButton: kTypeRadio"); @@ -633,6 +712,10 @@ void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId) { Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId) { uint16 imgId = spriteId + 1024; + + if (_vm->getVersion() >= 4 && _vm->_currentScore->_casts[spriteId]->children.size() > 0) + imgId = _vm->_currentScore->_casts[spriteId]->children[0].index; + Image::ImageDecoder *img = NULL; if (_vm->_currentScore->getArchive()->hasResource(MKTAG('D', 'I', 'B', ' '), imgId)) { @@ -650,13 +733,20 @@ Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId) { if (_vm->_currentScore->getArchive()->hasResource(MKTAG('B', 'I', 'T', 'D'), imgId)) { Common::SeekableReadStream *pic = _vm->_currentScore->getArchive()->getResource(MKTAG('B', 'I', 'T', 'D'), imgId); - if (_vm->getVersion() <= 4) { + if (_vm->getVersion() < 4) { BitmapCast *bc = static_cast<BitmapCast *>(_vm->_currentScore->_casts[spriteId]); int w = bc->initialRect.width(), h = bc->initialRect.height(); debugC(2, 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) { + BitmapCast *bc = static_cast<BitmapCast *>(_vm->_currentScore->_casts[spriteId]); + int w = bc->initialRect.width(), h = bc->initialRect.height(); + + debugC(2, 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); } else { img = new Image::BitmapDecoder(); } @@ -666,6 +756,7 @@ Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId) { byte buf[1024]; int n = s->read(buf, 1024); Common::hexdump(buf, n); + s->seek(0); } img->loadStream(*pic); @@ -683,17 +774,26 @@ Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId) { } -void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteID) { - uint16 castID = _sprites[spriteID]->_castId; - - TextCast *textCast = static_cast<TextCast *>(_vm->_currentScore->_casts[castID]); - Common::SeekableSubReadStreamEndian *textStream; +void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteID, uint16 castID) { + Common::SeekableSubReadStreamEndian *textStream = NULL; - if (_vm->_currentScore->_movieArchive->hasResource(MKTAG('S','T','X','T'), castID + 1024)) { - textStream = _vm->_currentScore->_movieArchive->getResource(MKTAG('S','T','X','T'), castID + 1024); - } else { + if (_vm->_currentScore->_movieArchive->hasResource(MKTAG('S', 'T', 'X', 'T'), castID)) { + textStream = _vm->_currentScore->_movieArchive->getResource(MKTAG('S', 'T', 'X', 'T'), castID); + } else if (_vm->getSharedSTXT() != nullptr) { textStream = _vm->getSharedSTXT()->getVal(spriteID + 1024); } + + renderText(surface, spriteID, textStream, false); +} + +void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteID, Common::SeekableSubReadStreamEndian *textStream, bool isButtonLabel) { + if (textStream == NULL) return; + + uint16 castID = _sprites[spriteID]->_castId; + TextCast *textCast = static_cast<TextCast *>(_vm->_currentScore->_casts[castID]); + + + uint32 unk1 = textStream->readUint32(); uint32 strLen = textStream->readUint32(); uint32 dataLen = textStream->readUint32(); @@ -711,11 +811,11 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteID) { if (strLen < 200) debugC(3, kDebugText, "text: '%s'", text.c_str()); - uint32 rectLeft = static_cast<TextCast *>(_sprites[spriteID]->_cast)->initialRect.left; - uint32 rectTop = static_cast<TextCast *>(_sprites[spriteID]->_cast)->initialRect.top; + uint32 rectLeft = textCast->initialRect.left; + uint32 rectTop = textCast->initialRect.top; - int x = _sprites[spriteID]->_startPoint.x + rectLeft; - int y = _sprites[spriteID]->_startPoint.y + rectTop; + int x = _sprites[spriteID]->_startPoint.x;// +rectLeft; + int y = _sprites[spriteID]->_startPoint.y;// +rectTop; int height = _sprites[spriteID]->_height; int width = _sprites[spriteID]->_width; @@ -730,7 +830,11 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteID) { debugC(3, kDebugText, "renderText: x: %d y: %d w: %d h: %d font: '%s'", x, y, width, height, _vm->_wm->_fontMan->getFontName(macFont)); - font->drawString(&surface, text, x, y, width, 0); + //TODO: the colour is wrong here... need to determine the correct colour for all versions! + font->drawString(&surface, text, x, y, width, (_sprites[spriteID]->_ink == kInkTypeReverse ? 255 : 0), (Graphics::TextAlign)textCast->textAlign); + + if (isButtonLabel) + return; if (textCast->borderSize != kSizeNone) { uint16 size = textCast->borderSize; @@ -884,10 +988,10 @@ void Frame::drawMatteSprite(Graphics::ManagedSurface &target, const Graphics::Su uint16 Frame::getSpriteIDFromPos(Common::Point pos) { // Find first from top to bottom - for (uint16 i = _drawRects.size() - 1; i > 0; i--) { - if (_drawRects[i].contains(pos)) - return i; - } + //TODO: THIS NEEDS TO BE REVERSED! + for (Common::HashMap<uint16, Common::Rect>::const_iterator dr = _drawRects.begin(); dr != _drawRects.end(); dr++) + if (dr->_value.contains(pos)) + return dr->_key; return 0; } diff --git a/engines/director/frame.h b/engines/director/frame.h index ce82fa527c..29ae9dd596 100644 --- a/engines/director/frame.h +++ b/engines/director/frame.h @@ -119,8 +119,10 @@ private: void playTransition(Score *score); void playSoundChannel(); void renderSprites(Graphics::ManagedSurface &surface, bool renderTrail); - void renderText(Graphics::ManagedSurface &surface, uint16 spriteId); - void renderButton(Graphics::ManagedSurface &surface, uint16 spriteId); + void renderText(Graphics::ManagedSurface &surface, uint16 spriteId, uint16 castID); + void renderText(Graphics::ManagedSurface &surface, uint16 spriteID, Common::SeekableSubReadStreamEndian *textStream, bool isButtonLabel); + void renderShape(Graphics::ManagedSurface &surface, uint16 spriteID); + void renderButton(Graphics::ManagedSurface &surface, uint16 spriteId, uint16 textId); void readPaletteInfo(Common::SeekableSubReadStreamEndian &stream); void readSprite(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size); void readMainChannels(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size); @@ -148,7 +150,7 @@ public: uint8 _skipFrameFlag; uint8 _blend; Common::Array<Sprite *> _sprites; - Common::Array<Common::Rect > _drawRects; + Common::HashMap<uint16, Common::Rect> _drawRects; DirectorEngine *_vm; }; diff --git a/engines/director/images.cpp b/engines/director/images.cpp index 0ec84af0d3..9b55402a18 100644 --- a/engines/director/images.cpp +++ b/engines/director/images.cpp @@ -201,4 +201,122 @@ bool BITDDecoder::loadStream(Common::SeekableReadStream &stream) { return true; } +/**************************** +* BITD V4+ +****************************/ + +BITDDecoderV4::BITDDecoderV4(int w, int h) { + _surface = new Graphics::Surface(); + + // We make the surface pitch a multiple of 16. + int pitch = w; + if (w % 16) + pitch += 16 - (w % 16); + + // HACK: Create a padded surface by adjusting w after create() + _surface->create(pitch, h, Graphics::PixelFormat::createFormatCLUT8()); + _surface->w = w; + + _palette = new byte[256 * 3]; + + _palette[0] = _palette[1] = _palette[2] = 0; + _palette[255 * 3 + 0] = _palette[255 * 3 + 1] = _palette[255 * 3 + 2] = 0xff; + + _paletteColorCount = 2; +} + +BITDDecoderV4::~BITDDecoderV4() { + destroy(); +} + +void BITDDecoderV4::destroy() { + _surface = 0; + + delete[] _palette; + _palette = 0; + _paletteColorCount = 0; +} + +void BITDDecoderV4::loadPalette(Common::SeekableReadStream &stream) { + // no op +} + +bool BITDDecoderV4::loadStream(Common::SeekableReadStream &stream) { + int x = 0, y = 0; + + // If the stream has exactly the required number of bits for this image, + // we assume it is uncompressed. + if (stream.size() * 8 == _surface->pitch * _surface->h) { + debugC(3, kDebugImages, "Skipping compression"); + for (y = 0; y < _surface->h; y++) { + for (x = 0; x < _surface->pitch; ) { + byte color = stream.readByte(); + for (int c = 0; c < 8; c++) + *((byte *)_surface->getBasePtr(x++, y)) = (color & (1 << (7 - c))) ? 0 : 0xff; + } + } + + return true; + } + + Common::Array<int> pixels; + pixels.reserve(4096); + + while (!stream.eos()) { + int data = stream.readByte(); + int len = data + 1; + if ((data & 0x80) != 0) { + len = ((data ^ 0xFF) & 0xff) + 2; + data = stream.readByte(); + for (int p = 0; p < len; p++) { + pixels.push_back(data); + //*((byte *)_surface->getBasePtr(x, y)) = data; + } + //data = stream.readByte(); + } else { + for (int p = 0; p < len; p++) { + data = stream.readByte(); + pixels.push_back(data); + } + } + //if (bpp == 32 && pixels.Count % (w * 3) == 0) + // source += 2; + } + + if (pixels.size() > 0) { + //this needs to be calculated a lot earlier! + int bpp = pixels.size() / (_surface->w * _surface->h); + switch (bpp) { + case 1: + for (uint pix = 0; pix < pixels.size(); pix++) { + //this calculation is wrong.. need a demo with colours. + *((byte *)_surface->getBasePtr(x, y)) = 0xff - pixels[pix]; + x++; + if (x == _surface->w) { + y++; + x = 0; + } + } + break; + /* + case 32: + SetPixel(x, y, Color.FromArgb( + pixels[((y * dxr.nodes[c].w) * 3) + x], + pixels[(((y * dxr.nodes[c].w) * 3) + (dxr.nodes[c].w)) + x], + pixels[(((y * dxr.nodes[c].w) * 3) + (2 * dxr.nodes[c].w)) + x])); + break; + case 16: + SetPixel(x, y, Color.FromArgb( + (pixels[((y * dxr.nodes[c].w) * 2) + x] & 0x7c) << 1, + (pixels[((y * dxr.nodes[c].w) * 2) + x] & 0x03) << 6 | + (pixels[((y * dxr.nodes[c].w) * 2) + (dxr.nodes[c].w) + x] & 0xe0) >> 2, + (pixels[((y * dxr.nodes[c].w) * 2) + (dxr.nodes[c].w) + x] & 0x1f) << 3)); + break; + */ + } + } + + return true; +} + } // End of namespace Director diff --git a/engines/director/images.h b/engines/director/images.h index 54e824588f..3be0e11a9e 100644 --- a/engines/director/images.h +++ b/engines/director/images.h @@ -81,6 +81,25 @@ private: uint8 _paletteColorCount; }; +class BITDDecoderV4 : public Image::ImageDecoder { +public: + BITDDecoderV4(int w, int h); + virtual ~BITDDecoderV4(); + + // ImageDecoder API + void destroy(); + virtual bool loadStream(Common::SeekableReadStream &stream); + virtual const Graphics::Surface *getSurface() const { return _surface; } + const byte *getPalette() const { return _palette; } + void loadPalette(Common::SeekableReadStream &stream); + uint16 getPaletteColorCount() const { return _paletteColorCount; } + +private: + Graphics::Surface *_surface; + byte *_palette; + uint8 _paletteColorCount; +}; + } // End of namespace Director #endif diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp index 1d93b9ab44..a53601366d 100644 --- a/engines/director/lingo/lingo-builtins.cpp +++ b/engines/director/lingo/lingo-builtins.cpp @@ -615,7 +615,7 @@ void Lingo::b_alert(int nargs) { void Lingo::b_cursor(int nargs) { Datum d = g_lingo->pop(); d.toInt(); - warning("STUB: b_cursor(%d)", d.u.i); + g_lingo->func_cursor(d.u.i); } void Lingo::b_showGlobals(int nargs) { @@ -767,7 +767,7 @@ void Lingo::b_point(int nargs) { /////////////////// void Lingo::b_beep(int nargs) { Datum d = g_lingo->pop(); - warning("STUB: b_beep(%d)", d.u.i); + g_lingo->func_beep(d.u.i); } void Lingo::b_mci(int nargs) { diff --git a/engines/director/lingo/lingo-funcs.cpp b/engines/director/lingo/lingo-funcs.cpp index e22044c1e9..6becd1410d 100644 --- a/engines/director/lingo/lingo-funcs.cpp +++ b/engines/director/lingo/lingo-funcs.cpp @@ -26,6 +26,7 @@ #include "common/util.h" #include "director/lingo/lingo-gr.h" #include "director/sound.h" +#include "graphics/macgui/macwindowmanager.h" namespace Director { @@ -210,4 +211,38 @@ void Lingo::func_gotoprevious() { _vm->_currentScore->gotoprevious(); } +void Lingo::func_cursor(int c) { + if (_cursorOnStack) { + //pop cursor + _vm->getMacWindowManager()->popCursor(); + } + + //and then push cursor. + switch (c) { + case 0: + case -1: + _vm->getMacWindowManager()->pushArrowCursor(); + break; + case 1: + _vm->getMacWindowManager()->pushBeamCursor(); + break; + case 2: + _vm->getMacWindowManager()->pushCrossHairCursor(); + break; + case 3: + _vm->getMacWindowManager()->pushCrossBarCursor(); + break; + case 4: + _vm->getMacWindowManager()->pushWatchCursor(); + break; + } + + warning("STUB: func_cursor(%d)", c); +} + +void Lingo::func_beep(int repeats) { + for (int r = 0; r <= repeats; r++) + _vm->getSoundManager()->systemBeep(); +} + } diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h index 5e7242abe6..67ab57ae22 100644 --- a/engines/director/lingo/lingo.h +++ b/engines/director/lingo/lingo.h @@ -401,10 +401,12 @@ public: void func_mci(Common::String &s); void func_mciwait(Common::String &s); + void func_beep(int repeats); void func_goto(Datum &frame, Datum &movie); void func_gotoloop(); void func_gotonext(); void func_gotoprevious(); + void func_cursor(int c); public: void setTheEntity(int entity, Datum &id, int field, Datum &d); @@ -440,6 +442,8 @@ public: bool _exitRepeat; + bool _cursorOnStack; + private: int parse(const char *code); void parseMenu(const char *code); diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp index 2f8ef3e432..711ce0474d 100644 --- a/engines/director/resource.cpp +++ b/engines/director/resource.cpp @@ -217,7 +217,7 @@ void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Common::Array<uint16> cast = shardcst->getResourceIDList(MKTAG('C','A','S','t')); if (cast.size() > 0) { for (Common::Array<uint16>::iterator iterator = cast.begin(); iterator != cast.end(); ++iterator) - castScore->loadCastData(*shardcst->getResource(MKTAG('C','A','S','t'), *iterator), *iterator); + castScore->loadCastData(*shardcst->getResource(MKTAG('C','A','S','t'), *iterator), *iterator, NULL); } castScore->setSpriteCasts(); diff --git a/engines/director/score.cpp b/engines/director/score.cpp index 8a80e30765..b3aee97fd8 100644 --- a/engines/director/score.cpp +++ b/engines/director/score.cpp @@ -216,16 +216,19 @@ void Score::loadArchive() { Common::Array<uint16> cast = _movieArchive->getResourceIDList(MKTAG('C','A','S','t')); if (cast.size() > 0) { - for (Common::Array<uint16>::iterator iterator = cast.begin(); iterator != cast.end(); ++iterator) - loadCastData(*_movieArchive->getResource(MKTAG('C','A','S','t'), *iterator), *iterator); + 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); + loadCastData(*stream, *iterator, &res); + } } setSpriteCasts(); - Common::Array<uint16> stxt = _movieArchive->getResourceIDList(MKTAG('S','T','X','T')); - if (stxt.size() > 0) { - loadScriptText(*_movieArchive->getResource(MKTAG('S','T','X','T'), *stxt.begin())); - } + //Common::Array<uint16> stxt = _movieArchive->getResourceIDList(MKTAG('S','T','X','T')); + //if (stxt.size() > 0) { + // loadScriptText(*_movieArchive->getResource(MKTAG('S','T','X','T'), *stxt.begin())); + //} } Score::~Score() { @@ -397,7 +400,7 @@ void Score::setSpriteCasts() { } } -void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id) { +void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id, Resource *res) { // d4+ variant if (stream.size() == 0) return; @@ -415,7 +418,7 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id) uint32 size1, size2, size3, castType; byte unk1 = 0, unk2 = 0, unk3 = 0; - if (_vm->getVersion() < 5) { + if (_vm->getVersion() < 4) { size1 = stream.readUint16(); size2 = stream.readUint32(); size3 = 0; @@ -423,6 +426,12 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id) unk1 = stream.readByte(); unk2 = stream.readByte(); unk3 = stream.readByte(); + } else if (_vm->getVersion() < 5) { + size1 = stream.readUint16() + 2; + size2 = stream.readUint32(); + size3 = 0; + castType = stream.readByte(); + unk1 = stream.readByte(); } else { // FIXME: only the cast type and the strings are good castType = stream.readUint32(); @@ -436,7 +445,7 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id) debugC(3, kDebugLoading, "CASt: id: %d type: %x size1: %d size2: %d (%x) size3: %d unk1: %d unk2: %d unk3: %d", id, castType, size1, size2, size2, size3, unk1, unk2, unk3); - byte *data = (byte *)calloc(size1, 1); // 16 is for bounding rects + byte *data = (byte *)calloc(size1 + 16, 1); // 16 is for bounding rects stream.read(data, size1 + 16); Common::MemoryReadStreamEndian castStream(data, size1 + 16, stream.isBE()); @@ -469,6 +478,9 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id) _casts[id]->type = kCastButton; break; case kCastScript: + warning("CASt: Script"); + Common::hexdump(data, size1 + 16); + _casts[id] = new ScriptCast(castStream, _vm->getVersion()); _casts[id]->type = kCastScript; break; @@ -477,6 +489,11 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id) 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) { @@ -500,6 +517,11 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id) ci->fileName = castStrings[3]; ci->type = castStrings[4]; + if (!ci->script.empty()) { + //the script type here could be wrong! + _lingo->addCode(ci->script.c_str(), _casts[id]->type == kCastScript ? kFrameScript : kSpriteScript, id); + } + _castsInfo[id] = ci; } @@ -802,7 +824,7 @@ Common::Array<Common::String> Score::loadStrings(Common::SeekableSubReadStreamEn byte *data = (byte *)malloc(entries[count - 1]); stream.read(data, entries[count - 1]); - for (uint i = 0; i < count - 1; i++) { + for (uint16 i = 0; i < count - 1; i++) { Common::String entryString; for (uint j = entries[i]; j < entries[i + 1]; j++) @@ -821,6 +843,9 @@ Common::Array<Common::String> Score::loadStrings(Common::SeekableSubReadStreamEn } void Score::loadFontMap(Common::SeekableSubReadStreamEndian &stream) { + if (stream.size() == 0) + return; + uint16 count = stream.readUint16(); uint32 offset = (count * 2) + 2; uint16 currentRawPosition = offset; @@ -908,9 +933,11 @@ void Score::update() { _currentFrame++; Common::SortedArray<Label *>::iterator i; - for (i = _labels->begin(); i != _labels->end(); ++i) { - if ((*i)->number == _currentFrame) { - _currentLabel = (*i)->name; + if (_labels != NULL) { + for (i = _labels->begin(); i != _labels->end(); ++i) { + if ((*i)->number == _currentFrame) { + _currentLabel = (*i)->name; + } } } diff --git a/engines/director/score.h b/engines/director/score.h index 49e4f357b0..b665842bb0 100644 --- a/engines/director/score.h +++ b/engines/director/score.h @@ -25,6 +25,7 @@ #include "common/substream.h" #include "common/rect.h" +#include "director/archive.h" namespace Graphics { class ManagedSurface; @@ -67,7 +68,7 @@ public: Archive *getArchive() const { return _movieArchive; }; void loadConfig(Common::SeekableSubReadStreamEndian &stream); void loadCastDataVWCR(Common::SeekableSubReadStreamEndian &stream); - void loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id); + void loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id, Resource *res); void setCurrentFrame(uint16 frameId) { _currentFrame = frameId; } int getCurrentFrame() { return _currentFrame; } Common::String getMacName() const { return _macName; } diff --git a/engines/director/sound.cpp b/engines/director/sound.cpp index 1bd70d257d..0fc1a43666 100644 --- a/engines/director/sound.cpp +++ b/engines/director/sound.cpp @@ -34,6 +34,11 @@ DirectorSound::DirectorSound() { _sound2 = new Audio::SoundHandle(); _scriptSound = new Audio::SoundHandle(); _mixer = g_system->getMixer(); + + _speaker = new Audio::PCSpeaker(); + _pcSpeakerHandle = new Audio::SoundHandle(); + _mixer->playStream(Audio::Mixer::kSFXSoundType, + _pcSpeakerHandle, _speaker, -1, 50, 0, DisposeAfterUse::NO, true); } DirectorSound::~DirectorSound() { @@ -100,6 +105,11 @@ bool DirectorSound::isChannelActive(uint8 channelID) { void DirectorSound::stopSound() { _mixer->stopHandle(*_sound1); _mixer->stopHandle(*_sound2); + _mixer->stopHandle(*_pcSpeakerHandle); +} + +void DirectorSound::systemBeep() { + _speaker->play(Audio::PCSpeaker::kWaveFormSquare, 500, 150); } } // End of namespace Director diff --git a/engines/director/sound.h b/engines/director/sound.h index 0472da0ef7..6a770314a3 100644 --- a/engines/director/sound.h +++ b/engines/director/sound.h @@ -22,6 +22,7 @@ #include "audio/audiostream.h" #include "audio/mixer.h" +#include "audio/softsynth/pcspk.h" #ifndef DIRECTOR_SOUND_H #define DIRECTOR_SOUND_H @@ -35,6 +36,8 @@ private: Audio::SoundHandle *_sound2; Audio::SoundHandle *_scriptSound; Audio::Mixer *_mixer; + Audio::PCSpeaker *_speaker; + Audio::SoundHandle *_pcSpeakerHandle; public: DirectorSound(); @@ -43,6 +46,7 @@ public: void playWAV(Common::String filename, uint8 channelID); void playAIFF(Common::String filename, uint8 channelID); void playMCI(Audio::AudioStream &stream, uint32 from, uint32 to); + void systemBeep(); bool isChannelActive(uint8 channelID); void stopSound(); }; diff --git a/engines/director/sprite.h b/engines/director/sprite.h index d248036693..d9b7729a87 100644 --- a/engines/director/sprite.h +++ b/engines/director/sprite.h @@ -106,7 +106,8 @@ public: uint32 _unk3; bool _enabled; - byte _castId; + uint16 _castId; + byte _spriteType; InkType _ink; uint16 _trails; Cast *_cast; diff --git a/graphics/macgui/macwindowmanager.cpp b/graphics/macgui/macwindowmanager.cpp index 42cab7cf8e..bad4ad3acc 100644 --- a/graphics/macgui/macwindowmanager.cpp +++ b/graphics/macgui/macwindowmanager.cpp @@ -88,6 +88,60 @@ static const byte macCursorBeam[] = { 3, 3, 0, 3, 0, 3, 3, 3, 3, 3, 3, 0, 0, 3, 3, 3, 0, 0, 3, 3, 3, 3, }; +static const byte macCursorCrossHair[] = { + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; +static const byte macCursorWatch[] = { + 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, + 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, +}; +static const byte macCursorCrossBar[] = { + 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, + 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; MacWindowManager::MacWindowManager() { _screen = 0; @@ -327,6 +381,22 @@ void MacWindowManager::pushArrowCursor() { CursorMan.pushCursor(macCursorArrow, 11, 16, 1, 1, 3); } +void MacWindowManager::pushBeamCursor() { + CursorMan.pushCursor(macCursorBeam, 11, 16, 1, 1, 3); +} + +void MacWindowManager::pushCrossHairCursor() { + CursorMan.pushCursor(macCursorCrossHair, 11, 16, 1, 1, 3); +} + +void MacWindowManager::pushCrossBarCursor() { + CursorMan.pushCursor(macCursorCrossBar, 11, 16, 1, 1, 3); +} + +void MacWindowManager::pushWatchCursor() { + CursorMan.pushCursor(macCursorWatch, 11, 16, 1, 1, 3); +} + void MacWindowManager::popCursor() { CursorMan.popCursor(); } diff --git a/graphics/macgui/macwindowmanager.h b/graphics/macgui/macwindowmanager.h index 3449ab13c2..9f62403813 100644 --- a/graphics/macgui/macwindowmanager.h +++ b/graphics/macgui/macwindowmanager.h @@ -146,6 +146,10 @@ public: void drawFilledRoundRect(ManagedSurface *surface, Common::Rect &rect, int arc, int color); void pushArrowCursor(); + void pushBeamCursor(); + void pushCrossHairCursor(); + void pushCrossBarCursor(); + void pushWatchCursor(); void popCursor(); public: |