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