aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/graphics/animate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/graphics/animate.cpp')
-rw-r--r--engines/sci/graphics/animate.cpp123
1 files changed, 74 insertions, 49 deletions
diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp
index b962e819a6..62c5f9c19e 100644
--- a/engines/sci/graphics/animate.cpp
+++ b/engines/sci/graphics/animate.cpp
@@ -96,7 +96,7 @@ bool GfxAnimate::invoke(List *list, int argc, reg_t *argv) {
invokeSelector(_s, curObject, SELECTOR(doit), argc, argv, 0);
// If a game is being loaded, stop processing
- if (_s->abortScriptProcessing != kAbortNone || g_engine->shouldQuit())
+ if (_s->abortScriptProcessing != kAbortNone)
return true; // Stop processing
// Lookup node again, since the nodetable it was in may have been reallocated.
@@ -141,6 +141,7 @@ void GfxAnimate::makeSortedList(List *list) {
AnimateEntry listEntry;
const reg_t curObject = curNode->value;
listEntry.object = curObject;
+ listEntry.castHandle = NULL_REG;
// Get data from current object
listEntry.givenOrderNo = listNr;
@@ -190,6 +191,34 @@ void GfxAnimate::makeSortedList(List *list) {
Common::sort(_list.begin(), _list.end(), sortHelper);
}
+void GfxAnimate::applyGlobalScaling(AnimateList::iterator entry, GfxView *view) {
+ reg_t curObject = entry->object;
+
+ // Global scaling uses global var 2 and some other stuff to calculate scaleX/scaleY
+ int16 maxScale = readSelectorValue(_s->_segMan, curObject, SELECTOR(maxScale));
+ int16 celHeight = view->getHeight(entry->loopNo, entry->celNo);
+ int16 maxCelHeight = (maxScale * celHeight) >> 7;
+ reg_t globalVar2 = _s->variables[VAR_GLOBAL][2]; // current room object
+ int16 vanishingY = readSelectorValue(_s->_segMan, globalVar2, SELECTOR(vanishingY));
+
+ int16 fixedPortY = _ports->getPort()->rect.bottom - vanishingY;
+ int16 fixedEntryY = entry->y - vanishingY;
+ if (!fixedEntryY)
+ fixedEntryY = 1;
+
+ if ((celHeight == 0) || (fixedPortY == 0))
+ error("global scaling panic");
+
+ entry->scaleY = ( maxCelHeight * fixedEntryY ) / fixedPortY;
+ entry->scaleY = (entry->scaleY * 128) / celHeight;
+
+ entry->scaleX = entry->scaleY;
+
+ // and set objects scale selectors
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleX), entry->scaleX);
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleY), entry->scaleY);
+}
+
void GfxAnimate::fill(byte &old_picNotValid, bool maySetNsRect) {
reg_t curObject;
uint16 signal;
@@ -229,44 +258,22 @@ void GfxAnimate::fill(byte &old_picNotValid, bool maySetNsRect) {
it->celNo = viewCelCount - 1;
}
- // Process global scaling, if needed
- if (it->scaleSignal & kScaleSignalDoScaling) {
- if (it->scaleSignal & kScaleSignalGlobalScaling) {
- // Global scaling uses global var 2 and some other stuff to calculate scaleX/scaleY
- int16 maxScale = readSelectorValue(_s->_segMan, curObject, SELECTOR(maxScale));
- int16 celHeight = view->getHeight(it->loopNo, it->celNo);
- int16 maxCelHeight = (maxScale * celHeight) >> 7;
- reg_t globalVar2 = _s->variables[VAR_GLOBAL][2]; // current room object
- int16 vanishingY = readSelectorValue(_s->_segMan, globalVar2, SELECTOR(vanishingY));
-
- int16 fixedPortY = _ports->getPort()->rect.bottom - vanishingY;
- int16 fixedEntryY = it->y - vanishingY;
- if (!fixedEntryY)
- fixedEntryY = 1;
-
- if ((celHeight == 0) || (fixedPortY == 0))
- error("global scaling panic");
-
- it->scaleY = ( maxCelHeight * fixedEntryY ) / fixedPortY;
- it->scaleY = (it->scaleY * 128) / celHeight;
-
- it->scaleX = it->scaleY;
-
- // and set objects scale selectors
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleX), it->scaleX);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleY), it->scaleY);
- }
- }
-
- //warning("%s view %d, loop %d, cel %d", _s->_segMan->getObjectName(curObject), it->viewId, it->loopNo, it->celNo);
-
if (!view->isScaleable()) {
// Laura Bow 2 (especially floppy) depends on this, some views are not supposed to be scaleable
// this "feature" was removed in later versions of SCI1.1
it->scaleSignal = 0;
it->scaleY = it->scaleX = 128;
+ } else {
+ // Process global scaling, if needed
+ if (it->scaleSignal & kScaleSignalDoScaling) {
+ if (it->scaleSignal & kScaleSignalGlobalScaling) {
+ applyGlobalScaling(it, view);
+ }
+ }
}
+ //warning("%s view %d, loop %d, cel %d, signal %x", _s->_segMan->getObjectName(curObject), it->viewId, it->loopNo, it->celNo, it->signal);
+
bool setNsRect = maySetNsRect;
// Create rect according to coordinates and given cel
@@ -278,6 +285,16 @@ void GfxAnimate::fill(byte &old_picNotValid, bool maySetNsRect) {
} else {
view->getCelRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->celRect);
}
+
+ // This statement must be here for Hoyle4, otherwise cards are unclickable.
+ // This is probably one of the experimental features that were occasionally
+ // added to SCI interpreters; the corresponding check is absent in many SSCI
+ // versions. m_kiewitz knew about this flag before I (lskovlun) implemented it,
+ // so it is possible that more test cases are known. Also, some presently open
+ // SCI1.1 bugs may be fixed by this and should be re-tested with this patch generalized.
+ if (it->scaleSignal & kScaleSignalDontSetNsrect)
+ setNsRect = false;
+
if (setNsRect) {
writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsLeft), it->celRect.left);
writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsTop), it->celRect.top);
@@ -533,19 +550,6 @@ void GfxAnimate::reAnimate(Common::Rect rect) {
}
}
-void GfxAnimate::preprocessAddToPicList() {
- AnimateList::iterator it;
- const AnimateList::iterator end = _list.end();
-
- for (it = _list.begin(); it != end; ++it) {
- if (it->priority == -1)
- it->priority = _ports->kernelCoordinateToPriority(it->y);
-
- // Do not allow priority to get changed by fill()
- it->signal |= kSignalFixedPriority;
- }
-}
-
void GfxAnimate::addToPicDrawCels() {
reg_t curObject;
GfxView *view = NULL;
@@ -558,8 +562,31 @@ void GfxAnimate::addToPicDrawCels() {
// Get the corresponding view
view = _cache->getView(it->viewId);
+ // kAddToPic does not do loop/cel-number fixups, it also doesn't support global scaling
+
+ if (it->priority == -1)
+ it->priority = _ports->kernelCoordinateToPriority(it->y);
+
+ if (!view->isScaleable()) {
+ // Laura Bow 2 specific - ffs. fill()
+ it->scaleSignal = 0;
+ it->scaleY = it->scaleX = 128;
+ }
+
+ // Create rect according to coordinates and given cel
+ if (it->scaleSignal & kScaleSignalDoScaling) {
+ applyGlobalScaling(it, view);
+ view->getCelScaledRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->scaleX, it->scaleY, it->celRect);
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsLeft), it->celRect.left);
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsTop), it->celRect.top);
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsRight), it->celRect.right);
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsBottom), it->celRect.bottom);
+ } else {
+ view->getCelRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->celRect);
+ }
+
// draw corresponding cel
- _paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY);
+ _paint16->drawCel(view, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY);
if ((it->signal & kSignalIgnoreActor) == 0) {
it->celRect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(it->priority) - 1, it->celRect.top, it->celRect.bottom - 1);
_paint16->fillRect(it->celRect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15);
@@ -677,6 +704,7 @@ void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t
int16 onlyWidth = onlyCast->celRect.width();
if (((onlyWidth == 12) && (onlyHeight == 35)) || // regular benchmark view ("fred", "Speedy", "ego")
((onlyWidth == 29) && (onlyHeight == 45)) || // King's Quest 5 french "fred"
+ ((onlyWidth == 1) && (onlyHeight == 5)) || // Freddy Pharkas "fred"
((onlyWidth == 1) && (onlyHeight == 1))) { // Laura Bow 2 Talkie
// check further that there is only one cel in that view
GfxView *onlyView = _cache->getView(onlyCast->viewId);
@@ -703,7 +731,6 @@ void GfxAnimate::addToPicSetPicNotValid() {
void GfxAnimate::kernelAddToPicList(reg_t listReference, int argc, reg_t *argv) {
List *list;
- byte tempPicNotValid = 0;
_ports->setPort((Port *)_ports->_picWind);
@@ -712,8 +739,6 @@ void GfxAnimate::kernelAddToPicList(reg_t listReference, int argc, reg_t *argv)
error("kAddToPic called with non-list as parameter");
makeSortedList(list);
- preprocessAddToPicList();
- fill(tempPicNotValid, getSciVersion() >= SCI_VERSION_1_1 ? true : false);
addToPicDrawCels();
addToPicSetPicNotValid();