aboutsummaryrefslogtreecommitdiff
path: root/engines/mads
diff options
context:
space:
mode:
Diffstat (limited to 'engines/mads')
-rw-r--r--engines/mads/msurface.cpp15
-rw-r--r--engines/mads/msurface.h7
-rw-r--r--engines/mads/palette.cpp26
-rw-r--r--engines/mads/palette.h3
-rw-r--r--engines/mads/screen.cpp122
-rw-r--r--engines/mads/screen.h13
6 files changed, 183 insertions, 3 deletions
diff --git a/engines/mads/msurface.cpp b/engines/mads/msurface.cpp
index 39824bac4b..d8d01f307c 100644
--- a/engines/mads/msurface.cpp
+++ b/engines/mads/msurface.cpp
@@ -485,7 +485,6 @@ void MSurface::scrollY(int yAmount) {
delete[] tempData;
}
-
void MSurface::translate(Common::Array<RGB6> &palette) {
for (int y = 0; y < this->h; ++y) {
byte *pDest = getBasePtr(0, y);
@@ -521,6 +520,20 @@ MSurface *MSurface::flipHorizontal() const {
return dest;
}
+void MSurface::copyRectTranslate(MSurface &srcSurface, const byte *paletteMap,
+ const Common::Point &destPos, const Common::Rect &srcRect) {
+ // Loop through the lines
+ for (int yCtr = 0; yCtr < srcRect.height(); ++yCtr) {
+ const byte *srcP = srcSurface.getBasePtr(srcRect.left, srcRect.top + yCtr);
+ byte *destP = getBasePtr(destPos.x, destPos.y + yCtr);
+
+ // Copy the line over
+ for (int xCtr = 0; xCtr < srcRect.width(); ++xCtr, ++srcP, ++destP) {
+ *destP = paletteMap[*srcP];
+ }
+ }
+}
+
/*------------------------------------------------------------------------*/
int DepthSurface::getDepth(const Common::Point &pt) {
diff --git a/engines/mads/msurface.h b/engines/mads/msurface.h
index 650d7fdaee..754e70bf7f 100644
--- a/engines/mads/msurface.h
+++ b/engines/mads/msurface.h
@@ -220,6 +220,13 @@ public:
* Create a new surface which is a flipped horizontal copy of the current one
*/
MSurface *flipHorizontal() const;
+
+ /**
+ * Copy an area from one surface to another, translating it using a palette
+ * map as it's done
+ */
+ void copyRectTranslate(MSurface &srcSurface, const byte *paletteMap,
+ const Common::Point &destPos, const Common::Rect &srcRect);
};
class DepthSurface : public MSurface {
diff --git a/engines/mads/palette.cpp b/engines/mads/palette.cpp
index 250eb75955..250c98b074 100644
--- a/engines/mads/palette.cpp
+++ b/engines/mads/palette.cpp
@@ -885,4 +885,30 @@ void Palette::refreshSceneColors() {
setPalette(_mainPalette + (val * 3), val, 256 - val);
}
+int Palette::closestColor(const byte *matchColor, const byte *refPalette,
+ int listWrap, int count) {
+ int bestColor = 0;
+ int bestDifference = 0x7fff;
+
+ for (int idx = 0; idx < count; ++idx) {
+ // Figure out hash for color
+ int hash = 0;
+ for (int rgbIdx = 0; rgbIdx < 3; ++rgbIdx, ++refPalette) {
+ byte diff = *refPalette - matchColor[rgbIdx];
+ hash += (int)diff * (int)diff;
+ }
+
+ // If the given color is a closer match to our color, store the index
+ if (hash < bestDifference) {
+ bestDifference = hash;
+ bestColor = idx;
+ }
+
+ refPalette += listWrap - 3;
+ }
+
+ return bestColor;
+}
+
+
} // End of namespace MADS
diff --git a/engines/mads/palette.h b/engines/mads/palette.h
index 27d25f266b..1c387b4368 100644
--- a/engines/mads/palette.h
+++ b/engines/mads/palette.h
@@ -318,6 +318,9 @@ public:
void unlock();
void refreshSceneColors();
+
+ static int closestColor(const byte *matchColor, const byte *refPalette,
+ int listWrap, int count);
};
} // End of namespace MADS
diff --git a/engines/mads/screen.cpp b/engines/mads/screen.cpp
index 8552effd98..f7179877d5 100644
--- a/engines/mads/screen.cpp
+++ b/engines/mads/screen.cpp
@@ -607,6 +607,7 @@ void ScreenSurface::updateScreen() {
void ScreenSurface::transition(ScreenTransition transitionType, bool surfaceFlag) {
Palette &pal = *_vm->_palette;
+ Scene &scene = _vm->_game->_scene;
byte palData[PALETTE_SIZE];
switch (transitionType) {
@@ -639,8 +640,9 @@ void ScreenSurface::transition(ScreenTransition transitionType, bool surfaceFlag
case kTransitionPanLeftToRight:
case kTransitionPanRightToLeft:
- warning("TODO: pan transition");
- transition(kTransitionFadeIn, surfaceFlag);
+ panTransition(scene._backgroundSurface, pal._mainPalette,
+ transitionType - kTransitionPanLeftToRight,
+ Common::Point(0, 0), scene._posAdjust, THROUGH_BLACK2, true, 1);
break;
case kTransitionCircleIn1:
@@ -674,5 +676,121 @@ void ScreenSurface::resetClipBounds() {
setClipBounds(Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT));
}
+void ScreenSurface::panTransition(MSurface &newScreen, byte *palData, int entrySide,
+ const Common::Point &srcPos, const Common::Point &destPos,
+ ThroughBlack throughBlack, bool setPalette, int numTicks) {
+ EventsManager &events = *_vm->_events;
+ Palette &palette = *_vm->_palette;
+ Common::Point size;
+ int y1, y2;
+ int startX = 0;
+ int deltaX;
+ int sizeY;
+ int xAt;
+ int loopStart;
+// uint32 baseTicks, currentTicks;
+ byte paletteMap[256];
+
+ size.x = MIN(newScreen.w, (uint16)MADS_SCREEN_WIDTH);
+ size.y = newScreen.h;
+ if (newScreen.h >= MADS_SCREEN_HEIGHT)
+ size.y = MADS_SCENE_HEIGHT;
+
+ // Set starting position and direction delta for the transition
+ if (entrySide == 1)
+ // Right to left
+ startX = size.x - 1;
+ deltaX = startX ? -1 : 1;
+
+ if (setPalette & !throughBlack)
+ palette.setFullPalette(palData);
+
+ // TODO: Original uses a different frequency ticks counter. Need to
+ // confirm frequency and see whether we need to implement it, or
+ // if the current frame ticks can substitute for it
+// baseTicks = events.getFrameCounter();
+
+ y1 = 0;
+ y2 = size.y - 1;
+ sizeY = y2 - y1 + 1;
+
+ if (throughBlack == THROUGH_BLACK2)
+ swapForeground(palData, &paletteMap[0]);
+
+ loopStart = throughBlack == THROUGH_BLACK1 ? 0 : 1;
+ for (int loop = loopStart; loop < 2; ++loop) {
+ xAt = startX;
+ for (int xCtr = 0; xCtr < size.x; ++xCtr, xAt += deltaX) {
+ if (!loop) {
+ fillRect(Common::Rect(xAt + destPos.x, y1 + destPos.y,
+ xAt + destPos.x + 1, y2 + destPos.y), 0);
+ } else if (throughBlack == THROUGH_BLACK2) {
+ copyRectTranslate(newScreen, paletteMap,
+ Common::Point(xAt, destPos.y),
+ Common::Rect(srcPos.x + xAt, srcPos.y,
+ srcPos.x + xAt + 1, srcPos.y + size.y));
+ } else {
+ newScreen.copyRectToSurface(*this, xAt, destPos.y,
+ Common::Rect(srcPos.x + xAt, srcPos.y,
+ srcPos.x + xAt + 1, srcPos.y + size.y));
+ }
+
+ copyRectToScreen(Common::Rect(xAt, destPos.y, xAt + 1, destPos.y + size.y));
+
+ // Slight delay
+ events.delay(1);
+ }
+
+ if ((setPalette && !loop) || throughBlack == THROUGH_BLACK2)
+ palette.setFullPalette(palData);
+ }
+
+ if (throughBlack == THROUGH_BLACK2) {
+ Common::Rect r(srcPos.x, srcPos.y, srcPos.x + size.x, srcPos.y + size.y);
+ copyRectToSurface(newScreen, destPos.x, destPos.y, r);
+ copyRectToScreen(r);
+ }
+}
+
+void ScreenSurface::swapForeground(byte palData[PALETTE_SIZE], byte *paletteMap) {
+ Palette &palette = *_vm->_palette;
+ byte oldPalette[PALETTE_SIZE];
+ byte oldMap[256];
+ byte newMap[256];
+
+ palette.getFullPalette(oldPalette);
+ swapPalette(oldPalette, oldMap, true);
+ swapPalette(palData, newMap, false);
+
+ Common::copy(&palData[3], &palData[PALETTE_SIZE], &oldPalette[3]);
+
+ copyRectTranslate(*this, oldMap, Common::Point(0, 0),
+ Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT));
+ palette.setFullPalette(oldPalette);
+}
+
+void ScreenSurface::swapPalette(byte *palData, byte swapTable[PALETTE_COUNT],
+ int start) {
+ byte *dynamicList = &palData[start * 3];
+ int staticStart = 1 - start;
+ byte *staticList = &palData[staticStart * 3];
+ const int PALETTE_START = 1;
+ const int PALETTE_END = 252;
+
+ // Set initial index values
+ for (int idx = 0; idx < PALETTE_COUNT; ++idx)
+ swapTable[idx] = idx;
+
+ for (int idx = 0; idx < 128; ++idx) {
+ if (start >= PALETTE_START && start <= PALETTE_END) {
+ swapTable[start] = Palette::closestColor(dynamicList, staticList,
+ 6, 128) * 2 + staticStart;
+ }
+
+ dynamicList += 6;
+ start += 2;
+ }
+}
+
} // End of namespace MADS
diff --git a/engines/mads/screen.h b/engines/mads/screen.h
index 6800523f92..35042e88d2 100644
--- a/engines/mads/screen.h
+++ b/engines/mads/screen.h
@@ -56,6 +56,11 @@ enum InputMode {
kInputLimitedSentences = 2 // Use only scene hotspots
};
+enum ThroughBlack {
+ THROUGH_BLACK1 = 1,
+ THROUGH_BLACK2 = 2
+};
+
class SpriteSlot;
class TextDisplay;
class UISlot;
@@ -207,6 +212,14 @@ private:
uint16 _random;
byte *_surfacePixels;
Common::Rect _clipBounds;
+
+ void panTransition(MSurface &newScreen, byte *palData, int entrySide,
+ const Common::Point &srcPos, const Common::Point &destPos,
+ ThroughBlack throughBlack, bool setPalette, int numTicks);
+
+ void swapForeground(byte *palData, byte *paletteMap);
+
+ void swapPalette(byte palData[PALETTE_SIZE], byte swapTable[PALETTE_COUNT], int start);
public:
int _shakeCountdown;
public: