[Scummvm-cvs-logs] scummvm master -> f8483d2dabc080857e71aa135b4e5ba1b0c5f181

sev- sev at scummvm.org
Tue Aug 23 09:58:39 CEST 2016


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
f8483d2dab DIRECTOR: Split score.cpp file into classes


Commit: f8483d2dabc080857e71aa135b4e5ba1b0c5f181
    https://github.com/scummvm/scummvm/commit/f8483d2dabc080857e71aa135b4e5ba1b0c5f181
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2016-08-23T09:41:00+02:00

Commit Message:
DIRECTOR: Split score.cpp file into classes

Changed paths:
  A engines/director/frame.cpp
  A engines/director/frame.h
  A engines/director/sprite.cpp
  A engines/director/sprite.h
    engines/director/lingo/lingo-the.cpp
    engines/director/module.mk
    engines/director/score.cpp
    engines/director/score.h



diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
new file mode 100644
index 0000000..abb880a
--- /dev/null
+++ b/engines/director/frame.cpp
@@ -0,0 +1,760 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/system.h"
+#include "graphics/macgui/macwindowmanager.h"
+#include "image/bmp.h"
+
+#include "director/director.h"
+#include "director/frame.h"
+#include "director/images.h"
+#include "director/score.h"
+#include "director/sprite.h"
+
+namespace Director {
+
+Frame::Frame(DirectorEngine *vm) {
+	_vm = vm;
+	_transDuration = 0;
+	_transType = kTransNone;
+	_transArea = 0;
+	_transChunkSize = 0;
+	_tempo = 0;
+
+	_sound1 = 0;
+	_sound2 = 0;
+	_soundType1 = 0;
+	_soundType2 = 0;
+
+	_actionId = 0;
+	_skipFrameFlag = 0;
+	_blend = 0;
+
+	_sprites.resize(CHANNEL_COUNT);
+
+	for (uint16 i = 0; i < _sprites.size(); i++) {
+		Sprite *sp = new Sprite();
+		_sprites[i] = sp;
+	}
+}
+
+Frame::Frame(const Frame &frame) {
+	_vm = frame._vm;
+	_actionId = frame._actionId;
+	_transArea = frame._transArea;
+	_transDuration = frame._transDuration;
+	_transType = frame._transType;
+	_transChunkSize = frame._transChunkSize;
+	_tempo = frame._tempo;
+	_sound1 = frame._sound1;
+	_sound2 = frame._sound2;
+	_soundType1 = frame._soundType1;
+	_soundType2 = frame._soundType2;
+	_skipFrameFlag = frame._skipFrameFlag;
+	_blend = frame._blend;
+	_palette = new PaletteInfo();
+
+	_sprites.resize(CHANNEL_COUNT);
+
+	for (uint16 i = 0; i < CHANNEL_COUNT; i++) {
+		_sprites[i] = new Sprite(*frame._sprites[i]);
+	}
+}
+
+Frame::~Frame() {
+	delete _palette;
+}
+
+void Frame::readChannel(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size) {
+	if (offset >= 32) {
+		if (size <= 16)
+			readSprite(stream, offset, size);
+		else {
+			//read > 1 sprites channel
+			while (size > 16) {
+				byte spritePosition = (offset - 32) / 16;
+				uint16 nextStart = (spritePosition + 1) * 16 + 32;
+				uint16 needSize = nextStart - offset;
+				readSprite(stream, offset, needSize);
+				offset += needSize;
+				size -= needSize;
+			}
+			readSprite(stream, offset, size);
+		}
+	} else {
+		readMainChannels(stream, offset, size);
+	}
+}
+
+void Frame::readMainChannels(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size) {
+	uint16 finishPosition = offset + size;
+
+	while (offset < finishPosition) {
+		switch(offset) {
+		case kScriptIdPosition:
+			_actionId = stream.readByte();
+			offset++;
+			break;
+		case kSoundType1Position:
+			_soundType1 = stream.readByte();
+			offset++;
+			break;
+		case kTransFlagsPosition: {
+			uint8 transFlags = stream.readByte();
+			if (transFlags & 0x80)
+				_transArea = 1;
+			else
+				_transArea = 0;
+			_transDuration = transFlags & 0x7f;
+			offset++;
+			}
+			break;
+		case kTransChunkSizePosition:
+			_transChunkSize = stream.readByte();
+			offset++;
+			break;
+		case kTempoPosition:
+			_tempo = stream.readByte();
+			offset++;
+			break;
+		case kTransTypePosition:
+			_transType = static_cast<TransitionType>(stream.readByte());
+			offset++;
+			break;
+		case kSound1Position:
+			_sound1 = stream.readUint16();
+			offset+=2;
+			break;
+		case kSkipFrameFlagsPosition:
+			_skipFrameFlag = stream.readByte();
+			offset++;
+			break;
+		case kBlendPosition:
+			_blend = stream.readByte();
+			offset++;
+			break;
+		case kSound2Position:
+			_sound2 = stream.readUint16();
+			offset += 2;
+			break;
+		case kSound2TypePosition:
+			_soundType2 = stream.readByte();
+			offset += 1;
+			break;
+		case kPaletePosition:
+			if (stream.readUint16())
+				readPaletteInfo(stream);
+			offset += 16;
+			break;
+		default:
+			offset++;
+			stream.readByte();
+			debug("Field Position %d, Finish Position %d", offset, finishPosition);
+			break;
+		}
+	}
+}
+
+void Frame::readPaletteInfo(Common::SeekableSubReadStreamEndian &stream) {
+	_palette->firstColor = stream.readByte();
+	_palette->lastColor = stream.readByte();
+	_palette->flags = stream.readByte();
+	_palette->speed = stream.readByte();
+	_palette->frameCount = stream.readUint16();
+	stream.skip(8); //unknown
+}
+
+void Frame::readSprite(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size) {
+	uint16 spritePosition = (offset - 32) / 16;
+	uint16 spriteStart = spritePosition * 16 + 32;
+
+	uint16 fieldPosition = offset - spriteStart;
+	uint16 finishPosition = fieldPosition + size;
+
+	Sprite &sprite = *_sprites[spritePosition];
+
+	while (fieldPosition < finishPosition) {
+		switch (fieldPosition) {
+		case kSpritePositionUnk1:
+			/*byte x1 = */ stream.readByte();
+			fieldPosition++;
+			break;
+		case kSpritePositionEnabled:
+			sprite._enabled = (stream.readByte() != 0);
+			fieldPosition++;
+			break;
+		case kSpritePositionUnk2:
+			/*byte x2 = */ stream.readUint16();
+			fieldPosition += 2;
+			break;
+		case kSpritePositionFlags:
+			sprite._flags = stream.readUint16();
+			sprite._ink = static_cast<InkType>(sprite._flags & 0x3f);
+
+			if (sprite._flags & 0x40)
+				sprite._trails = 1;
+			else
+				sprite._trails = 0;
+
+			fieldPosition += 2;
+			break;
+		case kSpritePositionCastId:
+			sprite._castId = stream.readUint16();
+			fieldPosition += 2;
+			break;
+		case kSpritePositionY:
+			sprite._startPoint.y = stream.readUint16();
+			fieldPosition += 2;
+			break;
+		case kSpritePositionX:
+			sprite._startPoint.x = stream.readUint16();
+			fieldPosition += 2;
+			break;
+		case kSpritePositionWidth:
+			sprite._width = stream.readUint16();
+			fieldPosition += 2;
+			break;
+		case kSpritePositionHeight:
+			sprite._height = stream.readUint16();
+			fieldPosition += 2;
+			break;
+		default:
+			//end cycle, go to next sprite channel
+			readSprite(stream, spriteStart + 16, finishPosition - fieldPosition);
+			fieldPosition = finishPosition;
+			break;
+		}
+	}
+}
+
+void Frame::prepareFrame(Score *score) {
+	renderSprites(*score->_surface, false);
+	renderSprites(*score->_trailSurface, true);
+
+	if (_transType != 0)
+		//TODO Handle changing area case
+		playTransition(score);
+
+	if (_sound1 != 0 || _sound2 != 0) {
+		playSoundChannel();
+	}
+
+	g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, score->_surface->getBounds().width(), score->_surface->getBounds().height());
+}
+
+void Frame::playSoundChannel() {
+	debug(0, "Sound2 %d", _sound2);
+	debug(0, "Sound1 %d", _sound1);
+}
+
+void Frame::playTransition(Score *score) {
+	uint16 duration = _transDuration * 250; // _transDuration in 1/4 of sec
+	duration = (duration == 0 ? 250 : duration); // director support transition duration = 0, but animation play like value = 1, idk.
+
+	if (_transChunkSize == 0)
+		_transChunkSize = 1; //equal 1 step
+
+	uint16 stepDuration = duration / _transChunkSize;
+	uint16 steps = duration / stepDuration;
+
+	switch (_transType) {
+	case kTransCoverDown:
+		{
+			uint16 stepSize = score->_movieRect.height() / steps;
+			Common::Rect r = score->_movieRect;
+
+			for (uint16 i = 1; i < steps; i++) {
+				r.setHeight(stepSize * i);
+
+				g_system->delayMillis(stepDuration);
+				score->processEvents();
+
+				g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, r.width(), r.height());
+				g_system->updateScreen();
+			}
+		}
+		break;
+	case kTransCoverUp:
+		{
+			uint16 stepSize = score->_movieRect.height() / steps;
+			Common::Rect r = score->_movieRect;
+
+			for (uint16 i = 1; i < steps; i++) {
+				r.setHeight(stepSize * i);
+
+				g_system->delayMillis(stepDuration);
+				score->processEvents();
+
+				g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, score->_movieRect.height() - stepSize * i, r.width(), r.height());
+				g_system->updateScreen();
+			}
+		}
+		break;
+	case kTransCoverRight: {
+			uint16 stepSize = score->_movieRect.width() / steps;
+			Common::Rect r = score->_movieRect;
+
+			for (uint16 i = 1; i < steps; i++) {
+				r.setWidth(stepSize * i);
+
+				g_system->delayMillis(stepDuration);
+				score->processEvents();
+
+				g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, r.width(), r.height());
+				g_system->updateScreen();
+			}
+		}
+		break;
+	case kTransCoverLeft: {
+			uint16 stepSize = score->_movieRect.width() / steps;
+			Common::Rect r = score->_movieRect;
+
+			for (uint16 i = 1; i < steps; i++) {
+				r.setWidth(stepSize * i);
+
+				g_system->delayMillis(stepDuration);
+				score->processEvents();
+
+				g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, score->_movieRect.width() - stepSize * i, 0, r.width(), r.height());
+				g_system->updateScreen();
+			}
+		}
+		break;
+	case kTransCoverUpLeft: {
+			uint16 stepSize = score->_movieRect.width() / steps;
+			Common::Rect r = score->_movieRect;
+
+			for (uint16 i = 1; i < steps; i++) {
+				r.setWidth(stepSize * i);
+				r.setHeight(stepSize * i);
+
+				g_system->delayMillis(stepDuration);
+				score->processEvents();
+
+				g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, score->_movieRect.width() - stepSize * i, score->_movieRect.height() - stepSize * i, r.width(), r.height());
+				g_system->updateScreen();
+			}
+		}
+		break;
+	case kTransCoverUpRight: {
+			uint16 stepSize = score->_movieRect.width() / steps;
+			Common::Rect r = score->_movieRect;
+
+			for (uint16 i = 1; i < steps; i++) {
+				r.setWidth(stepSize * i);
+				r.setHeight(stepSize * i);
+
+				g_system->delayMillis(stepDuration);
+				score->processEvents();
+
+				g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, score->_movieRect.height() - stepSize * i, r.width(), r.height());
+				g_system->updateScreen();
+			}
+		}
+		break;
+	case kTransCoverDownLeft: {
+			uint16 stepSize = score->_movieRect.width() / steps;
+			Common::Rect r = score->_movieRect;
+
+			for (uint16 i = 1; i < steps; i++) {
+				r.setWidth(stepSize * i);
+				r.setHeight(stepSize * i);
+
+				g_system->delayMillis(stepDuration);
+				score->processEvents();
+
+				g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, score->_movieRect.width() - stepSize * i, 0, r.width(), r.height());
+				g_system->updateScreen();
+			}
+		}
+		break;
+	case kTransCoverDownRight: {
+			uint16 stepSize = score->_movieRect.width() / steps;
+			Common::Rect r = score->_movieRect;
+
+			for (uint16 i = 1; i < steps; i++) {
+				r.setWidth(stepSize * i);
+				r.setHeight(stepSize * i);
+
+				g_system->delayMillis(stepDuration);
+				score->processEvents();
+
+				g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, r.width(), r.height());
+				g_system->updateScreen();
+			}
+		}
+		break;
+	default:
+		warning("Unhandled transition type %d %d %d", _transType, duration, _transChunkSize);
+		break;
+
+	}
+}
+
+void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) {
+	for (uint16 i = 0; i < CHANNEL_COUNT; i++) {
+		if (_sprites[i]->_enabled) {
+			if ((_sprites[i]->_trails == 0 && renderTrail) || (_sprites[i]->_trails == 1 && !renderTrail))
+				continue;
+
+			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 {
+					cast = _vm->getSharedCasts()->getVal(_sprites[i]->_castId);
+				}
+			} else {
+				cast = _vm->_currentScore->_casts[_sprites[i]->_castId];
+			}
+
+			if (cast->type == kCastText) {
+				renderText(surface, i);
+				continue;
+			}
+
+			Image::ImageDecoder *img = getImageFrom(_sprites[i]->_castId, _sprites[i]->_width, _sprites[i]->_height);
+
+			if (!img) {
+				warning("Image with id %d not found", _sprites[i]->_castId);
+				continue;
+			}
+
+			if (!img->getSurface()) {
+				//TODO
+				//BMPDecoder doesnt cover all BITD resources (not all have first two bytes 'BM')
+				//Some BITD's first two bytes 0x6 0x0
+				warning("Can not load image %d", _sprites[i]->_castId);
+				continue;
+			}
+
+			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 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);
+
+	uint16 castID = _sprites[spriteId]->_castId;
+	ButtonCast *button = static_cast<ButtonCast *>(_vm->_currentScore->_casts[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 = _sprites[spriteId]->_height;
+	int width = _sprites[spriteId]->_width;
+
+	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);
+		break;
+	case kTypeButton:
+		surface.frameRect(Common::Rect(x, y, x + width, y + height), 0);
+		break;
+	case kTypeRadio:
+		warning("STUB: renderButton: kTypeRadio");
+		break;
+	}
+}
+
+Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId, int w, int h) {
+	uint16 imgId = spriteId + 1024;
+	Image::ImageDecoder *img = NULL;
+
+	if (_vm->_currentScore->getArchive()->hasResource(MKTAG('D', 'I', 'B', ' '), imgId)) {
+		img = new DIBDecoder();
+		img->loadStream(*_vm->_currentScore->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;
+	}
+
+	if (_vm->_currentScore->getArchive()->hasResource(MKTAG('B', 'I', 'T', 'D'), imgId)) {
+		if (_vm->getVersion() < 4) {
+			img = new BITDDecoder(w, h);
+		} else {
+			img = new Image::BitmapDecoder();
+		}
+
+		if (debugChannelSet(8, kDebugLoading)) {
+			Common::SeekableReadStream *s = _vm->_currentScore->getArchive()->getResource(MKTAG('B', 'I', 'T', 'D'), imgId);
+			byte buf[1024];
+			int n = s->read(buf, 1024);
+			Common::hexdump(buf, n);
+		}
+
+		img->loadStream(*_vm->_currentScore->getArchive()->getResource(MKTAG('B', 'I', 'T', 'D'), imgId));
+		return img;
+	}
+
+	if (_vm->getSharedBMP() != NULL && _vm->getSharedBMP()->contains(imgId)) {
+		img = new Image::BitmapDecoder();
+		img->loadStream(*_vm->getSharedBMP()->getVal(imgId));
+		return img;
+	}
+
+	warning("Image %d not found", spriteId);
+	return img;
+}
+
+
+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;
+
+	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 {
+		textStream = _vm->getSharedSTXT()->getVal(spriteID + 1024);
+	}
+	/*uint32 unk1 = */ textStream->readUint32();
+	uint32 strLen = textStream->readUint32();
+	/*uin32 dataLen = */ textStream->readUint32();
+	Common::String text;
+
+	for (uint32 i = 0; i < strLen; i++) {
+		byte ch = textStream->readByte();
+		if (ch == 0x0d) {
+			ch = '\n';
+		}
+		text += ch;
+	}
+
+	uint32 rectLeft = static_cast<TextCast *>(_sprites[spriteID]->_cast)->initialRect.left;
+	uint32 rectTop = static_cast<TextCast *>(_sprites[spriteID]->_cast)->initialRect.top;
+
+	int x = _sprites[spriteID]->_startPoint.x + rectLeft;
+	int y = _sprites[spriteID]->_startPoint.y + rectTop;
+	int height = _sprites[spriteID]->_height;
+	int width = _sprites[spriteID]->_width;
+
+	const char *fontName;
+
+	if (_vm->_currentScore->_fontMap.contains(textCast->fontId)) {
+		fontName = _vm->_currentScore->_fontMap[textCast->fontId].c_str();
+	} else if ((fontName = _vm->_wm->getFontName(textCast->fontId, textCast->fontSize)) == NULL) {
+		warning("Unknown font id %d, falling back to default", textCast->fontId);
+		fontName = _vm->_wm->getFontName(0, 12);
+	}
+
+	const Graphics::Font *font = _vm->_wm->getFont(fontName, Graphics::FontManager::kBigGUIFont);
+
+	font->drawString(&surface, text, x, y, width, 0);
+
+	if (textCast->borderSize != kSizeNone) {
+		uint16 size = textCast->borderSize;
+
+		//Indent from borders, measured in d4
+		x -= 1;
+		y -= 4;
+
+		height += 4;
+		width += 1;
+
+		while (size) {
+			surface.frameRect(Common::Rect(x, y, x + height, y + width), 0);
+			x--;
+			y--;
+			height += 2;
+			width += 2;
+			size--;
+		}
+	}
+
+	if (textCast->gutterSize != kSizeNone) {
+		x -= 1;
+		y -= 4;
+
+		height += 4;
+		width += 1;
+		uint16 size = textCast->gutterSize;
+
+		surface.frameRect(Common::Rect(x, y, x + height, y + width), 0);
+
+		while (size) {
+			surface.drawLine(x + width, y, x + width, y + height, 0);
+			surface.drawLine(x, y + height, x + width, y + height, 0);
+			x++;
+			y++;
+			size--;
+		}
+	}
+}
+
+void Frame::drawBackgndTransSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) {
+	uint8 skipColor = _vm->getPaletteColorCount() - 1; //FIXME is it always white (last entry in pallette) ?
+
+	for (int ii = 0; ii < sprite.h; ii++) {
+		const byte *src = (const byte *)sprite.getBasePtr(0, ii);
+		byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + ii);
+
+		for (int j = 0; j < drawRect.width(); j++) {
+			if (*src != skipColor)
+				*dst = *src;
+
+			src++;
+			dst++;
+		}
+	}
+}
+
+void Frame::drawGhostSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) {
+	uint8 skipColor = _vm->getPaletteColorCount() - 1;
+	for (int ii = 0; ii < sprite.h; ii++) {
+		const byte *src = (const byte *)sprite.getBasePtr(0, ii);
+		byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + ii);
+
+		for (int j = 0; j < drawRect.width(); j++) {
+			if ((getSpriteIDFromPos(Common::Point(drawRect.left + j, drawRect.top + ii)) != 0) && (*src != skipColor))
+				*dst = (_vm->getPaletteColorCount() - 1) - *src; //Oposite color
+
+			src++;
+			dst++;
+		}
+	}
+}
+
+void Frame::drawReverseSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) {
+	uint8 skipColor = _vm->getPaletteColorCount() - 1;
+	for (int ii = 0; ii < sprite.h; ii++) {
+		const byte *src = (const byte *)sprite.getBasePtr(0, ii);
+		byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + ii);
+
+		for (int j = 0; j < drawRect.width(); j++) {
+			if ((getSpriteIDFromPos(Common::Point(drawRect.left + j, drawRect.top + ii)) != 0))
+				*dst = (_vm->getPaletteColorCount() - 1) - *src;
+			else if (*src != skipColor)
+				*dst = *src;
+			src++;
+			dst++;
+		}
+	}
+}
+
+void Frame::drawMatteSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) {
+	//Like background trans, but all white pixels NOT ENCLOSED by coloured pixels are transparent
+	Graphics::Surface tmp;
+	tmp.copyFrom(sprite);
+
+	// Searching white color in the corners
+	int whiteColor = -1;
+
+	for (int corner = 0; corner < 4; corner++) {
+		int x = (corner & 0x1) ? tmp.w - 1 : 0;
+		int y = (corner & 0x2) ? tmp.h - 1 : 0;
+
+		byte color = *(byte *)tmp.getBasePtr(x, y);
+
+		if (_vm->getPalette()[color * 3 + 0] == 0xff &&
+			_vm->getPalette()[color * 3 + 1] == 0xff &&
+			_vm->getPalette()[color * 3 + 2] == 0xff) {
+			whiteColor = color;
+			break;
+		}
+	}
+
+	if (whiteColor == -1) {
+		warning("No white color for Matte image");
+		whiteColor = *(byte *)tmp.getBasePtr(0, 0);
+	}
+
+	Graphics::FloodFill ff(&tmp, whiteColor, 0, true);
+
+	for (int yy = 0; yy < tmp.h; yy++) {
+		ff.addSeed(0, yy);
+		ff.addSeed(tmp.w - 1, yy);
+	}
+
+	for (int xx = 0; xx < tmp.w; xx++) {
+		ff.addSeed(xx, 0);
+		ff.addSeed(xx, tmp.h - 1);
+	}
+	ff.fillMask();
+
+	for (int yy = 0; yy < tmp.h; yy++) {
+		const byte *src = (const byte *)tmp.getBasePtr(0, yy);
+		const byte *mask = (const byte *)ff.getMask()->getBasePtr(0, yy);
+		byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + yy);
+
+		for (int xx = 0; xx < drawRect.width(); xx++, src++, dst++, mask++)
+			if (*mask == 0)
+				*dst = *src;
+	}
+
+	tmp.free();
+}
+
+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;
+	}
+
+	return 0;
+}
+
+} //End of namespace Director
diff --git a/engines/director/frame.h b/engines/director/frame.h
new file mode 100644
index 0000000..f9cef67
--- /dev/null
+++ b/engines/director/frame.h
@@ -0,0 +1,146 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef DIRECTOR_FRAME_H
+#define DIRECTOR_FRAME_H
+
+#include "graphics/managed_surface.h"
+#include "image/image_decoder.h"
+
+namespace Director {
+
+class Sprite;
+
+#define CHANNEL_COUNT 24
+
+enum TransitionType {
+	kTransNone,
+	kTransWipeRight,
+	kTransWipeLeft,
+	kTransWipeDown,
+	kTransWipeUp,
+	kTransCenterOutHorizontal,
+	kTransEdgesInHorizontal,
+	kTransCenterOutVertical,
+	kTransEdgesInVertical,
+	kTransCenterOutSquare,
+	kTransEdgesInSquare,
+	kTransPushLeft,
+	kTransPushRight,
+	kTransPushDown,
+	kTransPushUp,
+	kTransRevealUp,
+	kTransRevealUpRight,
+	kTransRevealRight,
+	kTransRevealDown,
+	kTransRevealDownRight,
+	kTransRevealDownLeft,
+	kTransRevealLeft,
+	kTransRevealUpLeft,
+	kTransDissolvePixelsFast,
+	kTransDissolveBoxyRects,
+	kTransDissolveBoxySquares,
+	kTransDissolvePatterns,
+	kTransRandomRows,
+	kTransRandomColumns,
+	kTransCoverDown,
+	kTransCoverDownLeft,
+	kTransCoverDownRight,
+	kTransCoverLeft,
+	kTransCoverRight,
+	kTransCoverUp,
+	kTransCoverUpLeft,
+	kTransCoverUpRight,
+	kTransTypeVenitianBlind,
+	kTransTypeCheckerboard,
+	kTransTypeStripsBottomBuildLeft,
+	kTransTypeStripsBottomBuildRight,
+	kTransTypeStripsLeftBuildDown,
+	kTransTypeStripsLeftBuildUp,
+	kTransTypeStripsRightBuildDown,
+	kTransTypeStripsRightBuildUp,
+	kTransTypeStripsTopBuildLeft,
+	kTransTypeStripsTopBuildRight,
+	kTransZoomOpen,
+	kTransZoomClose,
+	kTransVerticalBinds,
+	kTransDissolveBitsTrans,
+	kTransDissolvePixels,
+	kTransDissolveBits
+};
+
+struct PaletteInfo {
+	uint8 firstColor;
+	uint8 lastColor;
+	uint8 flags;
+	uint8 speed;
+	uint16 frameCount;
+};
+
+
+class Frame {
+public:
+	Frame(DirectorEngine *vm);
+	Frame(const Frame &frame);
+	~Frame();
+	void readChannel(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size);
+	void prepareFrame(Score *score);
+	uint16 getSpriteIDFromPos(Common::Point pos);
+
+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 readPaletteInfo(Common::SeekableSubReadStreamEndian &stream);
+	void readSprite(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size);
+	void readMainChannels(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size);
+	Image::ImageDecoder *getImageFrom(uint16 spriteID, int w, int h);
+	void drawBackgndTransSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect);
+	void drawMatteSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect);
+	void drawGhostSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect);
+	void drawReverseSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect);
+public:
+	uint8 _actionId;
+	uint8 _transDuration;
+	uint8 _transArea; //1 - Whole Stage, 0 - Changing Area
+	uint8 _transChunkSize;
+	TransitionType _transType;
+	PaletteInfo *_palette;
+	uint8 _tempo;
+
+	uint16 _sound1;
+	uint8 _soundType1;
+	uint16 _sound2;
+	uint8 _soundType2;
+
+	uint8 _skipFrameFlag;
+	uint8 _blend;
+	Common::Array<Sprite *> _sprites;
+	Common::Array<Common::Rect > _drawRects;
+	DirectorEngine *_vm;
+};
+
+} //End of namespace Director
+
+#endif
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index d868b8a..879ff48 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "engines/director/lingo/lingo.h"
+#include "director/sprite.h"
 
 namespace Director {
 
diff --git a/engines/director/module.mk b/engines/director/module.mk
index 05e92b7..c37e9d9 100644
--- a/engines/director/module.mk
+++ b/engines/director/module.mk
@@ -3,11 +3,13 @@ MODULE := engines/director
 MODULE_OBJS = \
 	detection.o \
 	director.o \
+	frame.o \
 	images.o \
 	movie.o \
 	resource.o \
 	score.o \
 	sound.o \
+	sprite.o \
 	lingo/lingo-gr.o \
 	lingo/lingo.o \
 	lingo/lingo-builtins.o \
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index ccadac2..2812f29 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -32,11 +32,12 @@
 #include "engines/util.h"
 #include "graphics/managed_surface.h"
 #include "graphics/macgui/macwindowmanager.h"
-#include "image/bmp.h"
 #include "graphics/fontman.h"
 #include "graphics/fonts/bdf.h"
 
 #include "director/score.h"
+#include "director/frame.h"
+#include "director/sprite.h"
 #include "director/images.h"
 #include "director/resource.h"
 #include "director/lingo/lingo.h"
@@ -839,785 +840,4 @@ Sprite *Score::getSpriteById(uint16 id) {
 	}
 }
 
-Frame::Frame(DirectorEngine *vm) {
-	_vm = vm;
-	_transDuration = 0;
-	_transType = kTransNone;
-	_transArea = 0;
-	_transChunkSize = 0;
-	_tempo = 0;
-
-	_sound1 = 0;
-	_sound2 = 0;
-	_soundType1 = 0;
-	_soundType2 = 0;
-
-	_actionId = 0;
-	_skipFrameFlag = 0;
-	_blend = 0;
-
-	_sprites.resize(CHANNEL_COUNT);
-
-	for (uint16 i = 0; i < _sprites.size(); i++) {
-		Sprite *sp = new Sprite();
-		_sprites[i] = sp;
-	}
-}
-
-Frame::Frame(const Frame &frame) {
-	_vm = frame._vm;
-	_actionId = frame._actionId;
-	_transArea = frame._transArea;
-	_transDuration = frame._transDuration;
-	_transType = frame._transType;
-	_transChunkSize = frame._transChunkSize;
-	_tempo = frame._tempo;
-	_sound1 = frame._sound1;
-	_sound2 = frame._sound2;
-	_soundType1 = frame._soundType1;
-	_soundType2 = frame._soundType2;
-	_skipFrameFlag = frame._skipFrameFlag;
-	_blend = frame._blend;
-	_palette = new PaletteInfo();
-
-	_sprites.resize(CHANNEL_COUNT);
-
-	for (uint16 i = 0; i < CHANNEL_COUNT; i++) {
-		_sprites[i] = new Sprite(*frame._sprites[i]);
-	}
-}
-
-Frame::~Frame() {
-	delete _palette;
-}
-
-void Frame::readChannel(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size) {
-	if (offset >= 32) {
-		if (size <= 16)
-			readSprite(stream, offset, size);
-		else {
-			//read > 1 sprites channel
-			while (size > 16) {
-				byte spritePosition = (offset - 32) / 16;
-				uint16 nextStart = (spritePosition + 1) * 16 + 32;
-				uint16 needSize = nextStart - offset;
-				readSprite(stream, offset, needSize);
-				offset += needSize;
-				size -= needSize;
-			}
-			readSprite(stream, offset, size);
-		}
-	} else {
-		readMainChannels(stream, offset, size);
-	}
-}
-
-void Frame::readMainChannels(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size) {
-	uint16 finishPosition = offset + size;
-
-	while (offset < finishPosition) {
-		switch(offset) {
-		case kScriptIdPosition:
-			_actionId = stream.readByte();
-			offset++;
-			break;
-		case kSoundType1Position:
-			_soundType1 = stream.readByte();
-			offset++;
-			break;
-		case kTransFlagsPosition: {
-			uint8 transFlags = stream.readByte();
-			if (transFlags & 0x80)
-				_transArea = 1;
-			else
-				_transArea = 0;
-			_transDuration = transFlags & 0x7f;
-			offset++;
-			}
-			break;
-		case kTransChunkSizePosition:
-			_transChunkSize = stream.readByte();
-			offset++;
-			break;
-		case kTempoPosition:
-			_tempo = stream.readByte();
-			offset++;
-			break;
-		case kTransTypePosition:
-			_transType = static_cast<TransitionType>(stream.readByte());
-			offset++;
-			break;
-		case kSound1Position:
-			_sound1 = stream.readUint16();
-			offset+=2;
-			break;
-		case kSkipFrameFlagsPosition:
-			_skipFrameFlag = stream.readByte();
-			offset++;
-			break;
-		case kBlendPosition:
-			_blend = stream.readByte();
-			offset++;
-			break;
-		case kSound2Position:
-			_sound2 = stream.readUint16();
-			offset += 2;
-			break;
-		case kSound2TypePosition:
-			_soundType2 = stream.readByte();
-			offset += 1;
-			break;
-		case kPaletePosition:
-			if (stream.readUint16())
-				readPaletteInfo(stream);
-			offset += 16;
-			break;
-		default:
-			offset++;
-			stream.readByte();
-			debug("Field Position %d, Finish Position %d", offset, finishPosition);
-			break;
-		}
-	}
-}
-
-void Frame::readPaletteInfo(Common::SeekableSubReadStreamEndian &stream) {
-	_palette->firstColor = stream.readByte();
-	_palette->lastColor = stream.readByte();
-	_palette->flags = stream.readByte();
-	_palette->speed = stream.readByte();
-	_palette->frameCount = stream.readUint16();
-	stream.skip(8); //unknown
-}
-
-void Frame::readSprite(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size) {
-	uint16 spritePosition = (offset - 32) / 16;
-	uint16 spriteStart = spritePosition * 16 + 32;
-
-	uint16 fieldPosition = offset - spriteStart;
-	uint16 finishPosition = fieldPosition + size;
-
-	Sprite &sprite = *_sprites[spritePosition];
-
-	while (fieldPosition < finishPosition) {
-		switch (fieldPosition) {
-		case kSpritePositionUnk1:
-			/*byte x1 = */ stream.readByte();
-			fieldPosition++;
-			break;
-		case kSpritePositionEnabled:
-			sprite._enabled = (stream.readByte() != 0);
-			fieldPosition++;
-			break;
-		case kSpritePositionUnk2:
-			/*byte x2 = */ stream.readUint16();
-			fieldPosition += 2;
-			break;
-		case kSpritePositionFlags:
-			sprite._flags = stream.readUint16();
-			sprite._ink = static_cast<InkType>(sprite._flags & 0x3f);
-
-			if (sprite._flags & 0x40)
-				sprite._trails = 1;
-			else
-				sprite._trails = 0;
-
-			fieldPosition += 2;
-			break;
-		case kSpritePositionCastId:
-			sprite._castId = stream.readUint16();
-			fieldPosition += 2;
-			break;
-		case kSpritePositionY:
-			sprite._startPoint.y = stream.readUint16();
-			fieldPosition += 2;
-			break;
-		case kSpritePositionX:
-			sprite._startPoint.x = stream.readUint16();
-			fieldPosition += 2;
-			break;
-		case kSpritePositionWidth:
-			sprite._width = stream.readUint16();
-			fieldPosition += 2;
-			break;
-		case kSpritePositionHeight:
-			sprite._height = stream.readUint16();
-			fieldPosition += 2;
-			break;
-		default:
-			//end cycle, go to next sprite channel
-			readSprite(stream, spriteStart + 16, finishPosition - fieldPosition);
-			fieldPosition = finishPosition;
-			break;
-		}
-	}
-}
-
-void Frame::prepareFrame(Score *score) {
-	renderSprites(*score->_surface, false);
-	renderSprites(*score->_trailSurface, true);
-
-	if (_transType != 0)
-		//TODO Handle changing area case
-		playTransition(score);
-
-	if (_sound1 != 0 || _sound2 != 0) {
-		playSoundChannel();
-	}
-
-	g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, score->_surface->getBounds().width(), score->_surface->getBounds().height());
-}
-
-void Frame::playSoundChannel() {
-	debug(0, "Sound2 %d", _sound2);
-	debug(0, "Sound1 %d", _sound1);
-}
-
-void Frame::playTransition(Score *score) {
-	uint16 duration = _transDuration * 250; // _transDuration in 1/4 of sec
-	duration = (duration == 0 ? 250 : duration); // director support transition duration = 0, but animation play like value = 1, idk.
-
-	if (_transChunkSize == 0)
-		_transChunkSize = 1; //equal 1 step
-
-	uint16 stepDuration = duration / _transChunkSize;
-	uint16 steps = duration / stepDuration;
-
-	switch (_transType) {
-	case kTransCoverDown:
-		{
-			uint16 stepSize = score->_movieRect.height() / steps;
-			Common::Rect r = score->_movieRect;
-
-			for (uint16 i = 1; i < steps; i++) {
-				r.setHeight(stepSize * i);
-
-				g_system->delayMillis(stepDuration);
-				score->processEvents();
-
-				g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, r.width(), r.height());
-				g_system->updateScreen();
-			}
-		}
-		break;
-	case kTransCoverUp:
-		{
-			uint16 stepSize = score->_movieRect.height() / steps;
-			Common::Rect r = score->_movieRect;
-
-			for (uint16 i = 1; i < steps; i++) {
-				r.setHeight(stepSize * i);
-
-				g_system->delayMillis(stepDuration);
-				score->processEvents();
-
-				g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, score->_movieRect.height() - stepSize * i, r.width(), r.height());
-				g_system->updateScreen();
-			}
-		}
-		break;
-	case kTransCoverRight: {
-			uint16 stepSize = score->_movieRect.width() / steps;
-			Common::Rect r = score->_movieRect;
-
-			for (uint16 i = 1; i < steps; i++) {
-				r.setWidth(stepSize * i);
-
-				g_system->delayMillis(stepDuration);
-				score->processEvents();
-
-				g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, r.width(), r.height());
-				g_system->updateScreen();
-			}
-		}
-		break;
-	case kTransCoverLeft: {
-			uint16 stepSize = score->_movieRect.width() / steps;
-			Common::Rect r = score->_movieRect;
-
-			for (uint16 i = 1; i < steps; i++) {
-				r.setWidth(stepSize * i);
-
-				g_system->delayMillis(stepDuration);
-				score->processEvents();
-
-				g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, score->_movieRect.width() - stepSize * i, 0, r.width(), r.height());
-				g_system->updateScreen();
-			}
-		}
-		break;
-	case kTransCoverUpLeft: {
-			uint16 stepSize = score->_movieRect.width() / steps;
-			Common::Rect r = score->_movieRect;
-
-			for (uint16 i = 1; i < steps; i++) {
-				r.setWidth(stepSize * i);
-				r.setHeight(stepSize * i);
-
-				g_system->delayMillis(stepDuration);
-				score->processEvents();
-
-				g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, score->_movieRect.width() - stepSize * i, score->_movieRect.height() - stepSize * i, r.width(), r.height());
-				g_system->updateScreen();
-			}
-		}
-		break;
-	case kTransCoverUpRight: {
-			uint16 stepSize = score->_movieRect.width() / steps;
-			Common::Rect r = score->_movieRect;
-
-			for (uint16 i = 1; i < steps; i++) {
-				r.setWidth(stepSize * i);
-				r.setHeight(stepSize * i);
-
-				g_system->delayMillis(stepDuration);
-				score->processEvents();
-
-				g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, score->_movieRect.height() - stepSize * i, r.width(), r.height());
-				g_system->updateScreen();
-			}
-		}
-		break;
-	case kTransCoverDownLeft: {
-			uint16 stepSize = score->_movieRect.width() / steps;
-			Common::Rect r = score->_movieRect;
-
-			for (uint16 i = 1; i < steps; i++) {
-				r.setWidth(stepSize * i);
-				r.setHeight(stepSize * i);
-
-				g_system->delayMillis(stepDuration);
-				score->processEvents();
-
-				g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, score->_movieRect.width() - stepSize * i, 0, r.width(), r.height());
-				g_system->updateScreen();
-			}
-		}
-		break;
-	case kTransCoverDownRight: {
-			uint16 stepSize = score->_movieRect.width() / steps;
-			Common::Rect r = score->_movieRect;
-
-			for (uint16 i = 1; i < steps; i++) {
-				r.setWidth(stepSize * i);
-				r.setHeight(stepSize * i);
-
-				g_system->delayMillis(stepDuration);
-				score->processEvents();
-
-				g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, r.width(), r.height());
-				g_system->updateScreen();
-			}
-		}
-		break;
-	default:
-		warning("Unhandled transition type %d %d %d", _transType, duration, _transChunkSize);
-		break;
-
-	}
-}
-
-void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) {
-	for (uint16 i = 0; i < CHANNEL_COUNT; i++) {
-		if (_sprites[i]->_enabled) {
-			if ((_sprites[i]->_trails == 0 && renderTrail) || (_sprites[i]->_trails == 1 && !renderTrail))
-				continue;
-
-			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 {
-					cast = _vm->getSharedCasts()->getVal(_sprites[i]->_castId);
-				}
-			} else {
-				cast = _vm->_currentScore->_casts[_sprites[i]->_castId];
-			}
-
-			if (cast->type == kCastText) {
-				renderText(surface, i);
-				continue;
-			}
-
-			Image::ImageDecoder *img = getImageFrom(_sprites[i]->_castId, _sprites[i]->_width, _sprites[i]->_height);
-
-			if (!img) {
-				warning("Image with id %d not found", _sprites[i]->_castId);
-				continue;
-			}
-
-			if (!img->getSurface()) {
-				//TODO
-				//BMPDecoder doesnt cover all BITD resources (not all have first two bytes 'BM')
-				//Some BITD's first two bytes 0x6 0x0
-				warning("Can not load image %d", _sprites[i]->_castId);
-				continue;
-			}
-
-			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 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);
-
-	uint16 castID = _sprites[spriteId]->_castId;
-	ButtonCast *button = static_cast<ButtonCast *>(_vm->_currentScore->_casts[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 = _sprites[spriteId]->_height;
-	int width = _sprites[spriteId]->_width;
-
-	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);
-		break;
-	case kTypeButton:
-		surface.frameRect(Common::Rect(x, y, x + width, y + height), 0);
-		break;
-	case kTypeRadio:
-		warning("STUB: renderButton: kTypeRadio");
-		break;
-	}
-}
-
-Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId, int w, int h) {
-	uint16 imgId = spriteId + 1024;
-	Image::ImageDecoder *img = NULL;
-
-	if (_vm->_currentScore->getArchive()->hasResource(MKTAG('D', 'I', 'B', ' '), imgId)) {
-		img = new DIBDecoder();
-		img->loadStream(*_vm->_currentScore->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;
-	}
-
-	if (_vm->_currentScore->getArchive()->hasResource(MKTAG('B', 'I', 'T', 'D'), imgId)) {
-		if (_vm->getVersion() < 4) {
-			img = new BITDDecoder(w, h);
-		} else {
-			img = new Image::BitmapDecoder();
-		}
-
-		if (debugChannelSet(8, kDebugLoading)) {
-			Common::SeekableReadStream *s = _vm->_currentScore->getArchive()->getResource(MKTAG('B', 'I', 'T', 'D'), imgId);
-			byte buf[1024];
-			int n = s->read(buf, 1024);
-			Common::hexdump(buf, n);
-		}
-
-		img->loadStream(*_vm->_currentScore->getArchive()->getResource(MKTAG('B', 'I', 'T', 'D'), imgId));
-		return img;
-	}
-
-	if (_vm->getSharedBMP() != NULL && _vm->getSharedBMP()->contains(imgId)) {
-		img = new Image::BitmapDecoder();
-		img->loadStream(*_vm->getSharedBMP()->getVal(imgId));
-		return img;
-	}
-
-	warning("Image %d not found", spriteId);
-	return img;
-}
-
-
-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;
-
-	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 {
-		textStream = _vm->getSharedSTXT()->getVal(spriteID + 1024);
-	}
-	/*uint32 unk1 = */ textStream->readUint32();
-	uint32 strLen = textStream->readUint32();
-	/*uin32 dataLen = */ textStream->readUint32();
-	Common::String text;
-
-	for (uint32 i = 0; i < strLen; i++) {
-		byte ch = textStream->readByte();
-		if (ch == 0x0d) {
-			ch = '\n';
-		}
-		text += ch;
-	}
-
-	uint32 rectLeft = static_cast<TextCast *>(_sprites[spriteID]->_cast)->initialRect.left;
-	uint32 rectTop = static_cast<TextCast *>(_sprites[spriteID]->_cast)->initialRect.top;
-
-	int x = _sprites[spriteID]->_startPoint.x + rectLeft;
-	int y = _sprites[spriteID]->_startPoint.y + rectTop;
-	int height = _sprites[spriteID]->_height;
-	int width = _sprites[spriteID]->_width;
-
-	const char *fontName;
-
-	if (_vm->_currentScore->_fontMap.contains(textCast->fontId)) {
-		fontName = _vm->_currentScore->_fontMap[textCast->fontId].c_str();
-	} else if ((fontName = _vm->_wm->getFontName(textCast->fontId, textCast->fontSize)) == NULL) {
-		warning("Unknown font id %d, falling back to default", textCast->fontId);
-		fontName = _vm->_wm->getFontName(0, 12);
-	}
-
-	const Graphics::Font *font = _vm->_wm->getFont(fontName, Graphics::FontManager::kBigGUIFont);
-
-	font->drawString(&surface, text, x, y, width, 0);
-
-	if (textCast->borderSize != kSizeNone) {
-		uint16 size = textCast->borderSize;
-
-		//Indent from borders, measured in d4
-		x -= 1;
-		y -= 4;
-
-		height += 4;
-		width += 1;
-
-		while (size) {
-			surface.frameRect(Common::Rect(x, y, x + height, y + width), 0);
-			x--;
-			y--;
-			height += 2;
-			width += 2;
-			size--;
-		}
-	}
-
-	if (textCast->gutterSize != kSizeNone) {
-		x -= 1;
-		y -= 4;
-
-		height += 4;
-		width += 1;
-		uint16 size = textCast->gutterSize;
-
-		surface.frameRect(Common::Rect(x, y, x + height, y + width), 0);
-
-		while (size) {
-			surface.drawLine(x + width, y, x + width, y + height, 0);
-			surface.drawLine(x, y + height, x + width, y + height, 0);
-			x++;
-			y++;
-			size--;
-		}
-	}
-}
-
-void Frame::drawBackgndTransSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) {
-	uint8 skipColor = _vm->getPaletteColorCount() - 1; //FIXME is it always white (last entry in pallette) ?
-
-	for (int ii = 0; ii < sprite.h; ii++) {
-		const byte *src = (const byte *)sprite.getBasePtr(0, ii);
-		byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + ii);
-
-		for (int j = 0; j < drawRect.width(); j++) {
-			if (*src != skipColor)
-				*dst = *src;
-
-			src++;
-			dst++;
-		}
-	}
-}
-
-void Frame::drawGhostSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) {
-	uint8 skipColor = _vm->getPaletteColorCount() - 1;
-	for (int ii = 0; ii < sprite.h; ii++) {
-		const byte *src = (const byte *)sprite.getBasePtr(0, ii);
-		byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + ii);
-
-		for (int j = 0; j < drawRect.width(); j++) {
-			if ((getSpriteIDFromPos(Common::Point(drawRect.left + j, drawRect.top + ii)) != 0) && (*src != skipColor))
-				*dst = (_vm->getPaletteColorCount() - 1) - *src; //Oposite color
-
-			src++;
-			dst++;
-		}
-	}
-}
-
-void Frame::drawReverseSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) {
-	uint8 skipColor = _vm->getPaletteColorCount() - 1;
-	for (int ii = 0; ii < sprite.h; ii++) {
-		const byte *src = (const byte *)sprite.getBasePtr(0, ii);
-		byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + ii);
-
-		for (int j = 0; j < drawRect.width(); j++) {
-			if ((getSpriteIDFromPos(Common::Point(drawRect.left + j, drawRect.top + ii)) != 0))
-				*dst = (_vm->getPaletteColorCount() - 1) - *src;
-			else if (*src != skipColor)
-				*dst = *src;
-			src++;
-			dst++;
-		}
-	}
-}
-
-void Frame::drawMatteSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) {
-	//Like background trans, but all white pixels NOT ENCLOSED by coloured pixels are transparent
-	Graphics::Surface tmp;
-	tmp.copyFrom(sprite);
-
-	// Searching white color in the corners
-	int whiteColor = -1;
-
-	for (int corner = 0; corner < 4; corner++) {
-		int x = (corner & 0x1) ? tmp.w - 1 : 0;
-		int y = (corner & 0x2) ? tmp.h - 1 : 0;
-
-		byte color = *(byte *)tmp.getBasePtr(x, y);
-
-		if (_vm->getPalette()[color * 3 + 0] == 0xff &&
-			_vm->getPalette()[color * 3 + 1] == 0xff &&
-			_vm->getPalette()[color * 3 + 2] == 0xff) {
-			whiteColor = color;
-			break;
-		}
-	}
-
-	if (whiteColor == -1) {
-		warning("No white color for Matte image");
-		whiteColor = *(byte *)tmp.getBasePtr(0, 0);
-	}
-
-	Graphics::FloodFill ff(&tmp, whiteColor, 0, true);
-
-	for (int yy = 0; yy < tmp.h; yy++) {
-		ff.addSeed(0, yy);
-		ff.addSeed(tmp.w - 1, yy);
-	}
-
-	for (int xx = 0; xx < tmp.w; xx++) {
-		ff.addSeed(xx, 0);
-		ff.addSeed(xx, tmp.h - 1);
-	}
-	ff.fillMask();
-
-	for (int yy = 0; yy < tmp.h; yy++) {
-		const byte *src = (const byte *)tmp.getBasePtr(0, yy);
-		const byte *mask = (const byte *)ff.getMask()->getBasePtr(0, yy);
-		byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + yy);
-
-		for (int xx = 0; xx < drawRect.width(); xx++, src++, dst++, mask++)
-			if (*mask == 0)
-				*dst = *src;
-	}
-
-	tmp.free();
-}
-
-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;
-	}
-
-	return 0;
-}
-
-Sprite::Sprite() {
-	_enabled = false;
-	_trails = 0;
-	_width = 0;
-	_ink = kInkTypeCopy;
-	_flags = 0;
-	_height = 0;
-	_castId = 0;
-	_constraint = 0;
-	_moveable = 0;
-	_castId = 0;
-	_backColor = 0;
-	_foreColor = 0;
-	_left = 0;
-	_right = 0;
-	_top = 0;
-	_bottom = 0;
-	_visible = false;
-	_movieRate = 0;
-	_movieTime = 0;
-	_startTime = 0;
-	_stopTime = 0;
-	_volume = 0;
-	_stretch = 0;
-	_type = kInactiveSprite;
-}
-
-Sprite::Sprite(const Sprite &sprite) {
-	_enabled = sprite._enabled;
-	_castId = sprite._castId;
-	_flags = sprite._flags;
-	_trails = sprite._trails;
-	_ink = sprite._ink;
-	_width = sprite._width;
-	_height = sprite._height;
-	_startPoint.x = sprite._startPoint.x;
-	_startPoint.y = sprite._startPoint.y;
-	_backColor = sprite._backColor;
-	_foreColor = sprite._foreColor;
-	_left = sprite._left;
-	_right = sprite._right;
-	_top = sprite._top;
-	_bottom = sprite._bottom;
-	_visible = sprite._visible;
-	_movieRate = sprite._movieRate;
-	_movieTime = sprite._movieTime;
-	_stopTime = sprite._stopTime;
-	_volume = sprite._volume;
-	_stretch = sprite._stretch;
-	_type = sprite._type;
-}
-
-Sprite::~Sprite() {
-	delete _cast;
-}
-
 } //End of namespace Director
diff --git a/engines/director/score.h b/engines/director/score.h
index 929dae6..9d92de9 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -36,11 +36,11 @@ namespace Director {
 
 class Lingo;
 class DirectorSound;
+class Frame;
+class Sprite;
 class Score;
 class DirectorEngine;
 
-#define CHANNEL_COUNT 24
-
 enum CastType {
 	kCastBitmap = 1,
 	kCastFilmLoop,
@@ -55,71 +55,6 @@ enum CastType {
 	kCastScript
 };
 
-//Director v4
-enum SpriteType {
-	kInactiveSprite, //turns the sprite off
-	kBitmapSprite,
-	kRectangleSprite,
-	kRoundedRectangleSprite,
-	kOvalSprite,
-	kLineTopBottomSprite, //line from top left to bottom right
-	kLineBottomTopSprite, //line from bottom left to top right
-	kTextSprite,
-	kButtonSprite,
-	kCheckboxSprite,
-	kRadioButtonSprite,
-	kUndeterminedSprite = 16 //use castType property to examine the type of cast member associated with sprite
-};
-
-enum SpritePosition {
-	kSpritePositionUnk1 = 0,
-	kSpritePositionEnabled,
-	kSpritePositionUnk2,
-	kSpritePositionFlags = 4,
-	kSpritePositionCastId = 6,
-	kSpritePositionY = 8,
-	kSpritePositionX = 10,
-	kSpritePositionHeight = 12,
-	kSpritePositionWidth = 14
-};
-
-enum MainChannelsPosition {
-	kScriptIdPosition = 0,
-	kSoundType1Position,
-	kTransFlagsPosition,
-	kTransChunkSizePosition,
-	kTempoPosition,
-	kTransTypePosition,
-	kSound1Position,
-	kSkipFrameFlagsPosition = 8,
-	kBlendPosition,
-	kSound2Position,
-	kSound2TypePosition = 11,
-	kPaletePosition = 15
-};
-
-enum InkType {
-	kInkTypeCopy,
-	kInkTypeTransparent,
-	kInkTypeReverse,
-	kInkTypeGhost,
-	kInkTypeNotCopy,
-	kInkTypeNotTrans,
-	kInkTypeNotReverse,
-	kInkTypeNotGhost,
-	kInkTypeMatte,
-	kInkTypeMask,
-	//10-31 Not used (Lingo in a Nutshell)
-	kInkTypeBlend = 32,
-	kInkTypeAddPin,
-	kInkTypeAdd,
-	kInkTypeSubPin,
-	kInkTypeBackgndTrans,
-	kInkTypeLight,
-	kInkTypeSub,
-	kInkTypeDark
-};
-
 enum ScriptType {
 	kMovieScript = 0,
 	kSpriteScript = 1,
@@ -127,62 +62,6 @@ enum ScriptType {
 	kMaxScriptType = 2
 };
 
-enum TransitionType {
-	kTransNone,
-	kTransWipeRight,
-	kTransWipeLeft,
-	kTransWipeDown,
-	kTransWipeUp,
-	kTransCenterOutHorizontal,
-	kTransEdgesInHorizontal,
-	kTransCenterOutVertical,
-	kTransEdgesInVertical,
-	kTransCenterOutSquare,
-	kTransEdgesInSquare,
-	kTransPushLeft,
-	kTransPushRight,
-	kTransPushDown,
-	kTransPushUp,
-	kTransRevealUp,
-	kTransRevealUpRight,
-	kTransRevealRight,
-	kTransRevealDown,
-	kTransRevealDownRight,
-	kTransRevealDownLeft,
-	kTransRevealLeft,
-	kTransRevealUpLeft,
-	kTransDissolvePixelsFast,
-	kTransDissolveBoxyRects,
-	kTransDissolveBoxySquares,
-	kTransDissolvePatterns,
-	kTransRandomRows,
-	kTransRandomColumns,
-	kTransCoverDown,
-	kTransCoverDownLeft,
-	kTransCoverDownRight,
-	kTransCoverLeft,
-	kTransCoverRight,
-	kTransCoverUp,
-	kTransCoverUpLeft,
-	kTransCoverUpRight,
-	kTransTypeVenitianBlind,
-	kTransTypeCheckerboard,
-	kTransTypeStripsBottomBuildLeft,
-	kTransTypeStripsBottomBuildRight,
-	kTransTypeStripsLeftBuildDown,
-	kTransTypeStripsLeftBuildUp,
-	kTransTypeStripsRightBuildDown,
-	kTransTypeStripsRightBuildUp,
-	kTransTypeStripsTopBuildLeft,
-	kTransTypeStripsTopBuildRight,
-	kTransZoomOpen,
-	kTransZoomClose,
-	kTransVerticalBinds,
-	kTransDissolveBitsTrans,
-	kTransDissolvePixels,
-	kTransDissolveBits
-};
-
 struct Cast {
 	CastType type;
 	Common::Rect initialRect;
@@ -281,98 +160,6 @@ struct CastInfo {
 	Common::String type;
 };
 
-struct PaletteInfo {
-	uint8 firstColor;
-	uint8 lastColor;
-	uint8 flags;
-	uint8 speed;
-	uint16 frameCount;
-};
-
-class Sprite {
-public:
-	Sprite();
-	Sprite(const Sprite &sprite);
-	~Sprite();
-	bool _enabled;
-	byte _castId;
-	InkType _ink;
-	uint16 _trails;
-	Cast *_cast;
-	uint16 _flags;
-	Common::Point _startPoint;
-	uint16 _width;
-	uint16 _height;
-	//TODO: default constraint = 0, if turned on, sprite is constrainted to the bounding rect
-	//As i know, constrainted != 0 only if sprite moveable
-	byte _constraint;
-	byte _moveable;
-	byte _backColor;
-	byte _foreColor;
-	uint16 _left;
-	uint16 _right;
-	uint16 _top;
-	uint16 _bottom;
-	byte _blend;
-	bool _visible;
-	SpriteType _type;
-	//Using in digital movie sprites
-	byte _movieRate;
-	uint16 _movieTime;
-	uint16 _startTime;
-	uint16 _stopTime;
-	byte _volume;
-	byte _stretch;
-	//Using in shape sprites
-	byte _lineSize;
-	//Using in text sprites
-	Common::String _editableText;
-};
-
-class Frame {
-public:
-	Frame(DirectorEngine *vm);
-	Frame(const Frame &frame);
-	~Frame();
-	void readChannel(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size);
-	void prepareFrame(Score *score);
-	uint16 getSpriteIDFromPos(Common::Point pos);
-
-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 readPaletteInfo(Common::SeekableSubReadStreamEndian &stream);
-	void readSprite(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size);
-	void readMainChannels(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size);
-	Image::ImageDecoder *getImageFrom(uint16 spriteID, int w, int h);
-	void drawBackgndTransSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect);
-	void drawMatteSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect);
-	void drawGhostSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect);
-	void drawReverseSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect);
-public:
-	uint8 _actionId;
-	uint8 _transDuration;
-	uint8 _transArea; //1 - Whole Stage, 0 - Changing Area
-	uint8 _transChunkSize;
-	TransitionType _transType;
-	PaletteInfo *_palette;
-	uint8 _tempo;
-
-	uint16 _sound1;
-	uint8 _soundType1;
-	uint16 _sound2;
-	uint8 _soundType2;
-
-	uint8 _skipFrameFlag;
-	uint8 _blend;
-	Common::Array<Sprite *> _sprites;
-	Common::Array<Common::Rect > _drawRects;
-	DirectorEngine *_vm;
-};
-
 struct Label {
 	Common::String name;
 	uint16 number;
diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
new file mode 100644
index 0000000..7fd5b3d
--- /dev/null
+++ b/engines/director/sprite.cpp
@@ -0,0 +1,85 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "director/director.h"
+#include "director/score.h"
+#include "director/sprite.h"
+
+namespace Director {
+
+Sprite::Sprite() {
+	_enabled = false;
+	_trails = 0;
+	_width = 0;
+	_ink = kInkTypeCopy;
+	_flags = 0;
+	_height = 0;
+	_castId = 0;
+	_constraint = 0;
+	_moveable = 0;
+	_castId = 0;
+	_backColor = 0;
+	_foreColor = 0;
+	_left = 0;
+	_right = 0;
+	_top = 0;
+	_bottom = 0;
+	_visible = false;
+	_movieRate = 0;
+	_movieTime = 0;
+	_startTime = 0;
+	_stopTime = 0;
+	_volume = 0;
+	_stretch = 0;
+	_type = kInactiveSprite;
+}
+
+Sprite::Sprite(const Sprite &sprite) {
+	_enabled = sprite._enabled;
+	_castId = sprite._castId;
+	_flags = sprite._flags;
+	_trails = sprite._trails;
+	_ink = sprite._ink;
+	_width = sprite._width;
+	_height = sprite._height;
+	_startPoint.x = sprite._startPoint.x;
+	_startPoint.y = sprite._startPoint.y;
+	_backColor = sprite._backColor;
+	_foreColor = sprite._foreColor;
+	_left = sprite._left;
+	_right = sprite._right;
+	_top = sprite._top;
+	_bottom = sprite._bottom;
+	_visible = sprite._visible;
+	_movieRate = sprite._movieRate;
+	_movieTime = sprite._movieTime;
+	_stopTime = sprite._stopTime;
+	_volume = sprite._volume;
+	_stretch = sprite._stretch;
+	_type = sprite._type;
+}
+
+Sprite::~Sprite() {
+	delete _cast;
+}
+
+} //End of namespace Director
diff --git a/engines/director/sprite.h b/engines/director/sprite.h
new file mode 100644
index 0000000..c66c66d
--- /dev/null
+++ b/engines/director/sprite.h
@@ -0,0 +1,137 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef DIRECTOR_SPRITE_H
+#define DIRECTOR_SPRITE_H
+
+#include "common/rect.h"
+
+namespace Director {
+
+enum InkType {
+	kInkTypeCopy,
+	kInkTypeTransparent,
+	kInkTypeReverse,
+	kInkTypeGhost,
+	kInkTypeNotCopy,
+	kInkTypeNotTrans,
+	kInkTypeNotReverse,
+	kInkTypeNotGhost,
+	kInkTypeMatte,
+	kInkTypeMask,
+	//10-31 Not used (Lingo in a Nutshell)
+	kInkTypeBlend = 32,
+	kInkTypeAddPin,
+	kInkTypeAdd,
+	kInkTypeSubPin,
+	kInkTypeBackgndTrans,
+	kInkTypeLight,
+	kInkTypeSub,
+	kInkTypeDark
+};
+
+//Director v4
+enum SpriteType {
+	kInactiveSprite, //turns the sprite off
+	kBitmapSprite,
+	kRectangleSprite,
+	kRoundedRectangleSprite,
+	kOvalSprite,
+	kLineTopBottomSprite, //line from top left to bottom right
+	kLineBottomTopSprite, //line from bottom left to top right
+	kTextSprite,
+	kButtonSprite,
+	kCheckboxSprite,
+	kRadioButtonSprite,
+	kUndeterminedSprite = 16 //use castType property to examine the type of cast member associated with sprite
+};
+
+enum SpritePosition {
+	kSpritePositionUnk1 = 0,
+	kSpritePositionEnabled,
+	kSpritePositionUnk2,
+	kSpritePositionFlags = 4,
+	kSpritePositionCastId = 6,
+	kSpritePositionY = 8,
+	kSpritePositionX = 10,
+	kSpritePositionHeight = 12,
+	kSpritePositionWidth = 14
+};
+
+enum MainChannelsPosition {
+	kScriptIdPosition = 0,
+	kSoundType1Position,
+	kTransFlagsPosition,
+	kTransChunkSizePosition,
+	kTempoPosition,
+	kTransTypePosition,
+	kSound1Position,
+	kSkipFrameFlagsPosition = 8,
+	kBlendPosition,
+	kSound2Position,
+	kSound2TypePosition = 11,
+	kPaletePosition = 15
+};
+
+class Sprite {
+public:
+	Sprite();
+	Sprite(const Sprite &sprite);
+	~Sprite();
+	bool _enabled;
+	byte _castId;
+	InkType _ink;
+	uint16 _trails;
+	Cast *_cast;
+	uint16 _flags;
+	Common::Point _startPoint;
+	uint16 _width;
+	uint16 _height;
+	//TODO: default constraint = 0, if turned on, sprite is constrainted to the bounding rect
+	//As i know, constrainted != 0 only if sprite moveable
+	byte _constraint;
+	byte _moveable;
+	byte _backColor;
+	byte _foreColor;
+	uint16 _left;
+	uint16 _right;
+	uint16 _top;
+	uint16 _bottom;
+	byte _blend;
+	bool _visible;
+	SpriteType _type;
+	//Using in digital movie sprites
+	byte _movieRate;
+	uint16 _movieTime;
+	uint16 _startTime;
+	uint16 _stopTime;
+	byte _volume;
+	byte _stretch;
+	//Using in shape sprites
+	byte _lineSize;
+	//Using in text sprites
+	Common::String _editableText;
+};
+
+} //End of namespace Director
+
+#endif






More information about the Scummvm-git-logs mailing list