[Scummvm-cvs-logs] scummvm master -> 7379e531c75294577b4859fceb73ae01559dae0f

bluegr bluegr at gmail.com
Fri Jan 8 09:58:39 CET 2016


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

Summary:
aeee621e44 SCI32: Add initial support for palette cycling (kPalCycle) and fading (kPalFade)
70d89b3e39 SCI32: Add kSetPalStyleRange stub code
8a1d48fc03 SCI32: Add kFrameOut stub code
275db1f7f2 SCI: Remove unused member property _palCycleToColor
7379e531c7 Merge pull request #644 from csnover/sci32-kPalCycle


Commit: aeee621e4413fe71ffada6c4bc096ae2a5a8c204
    https://github.com/scummvm/scummvm/commit/aeee621e4413fe71ffada6c4bc096ae2a5a8c204
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-01-07T16:35:09-06:00

Commit Message:
SCI32: Add initial support for palette cycling (kPalCycle) and fading (kPalFade)

Graphics palette code was rewritten between SCI1 and SCI2, so
SCI32 palette engine code has been moved to a separate GfxPalette32
class.

Changed paths:
  A engines/sci/graphics/palette32.cpp
  A engines/sci/graphics/palette32.h
    engines/sci/console.cpp
    engines/sci/engine/kgraphics.cpp
    engines/sci/engine/kgraphics32.cpp
    engines/sci/engine/kpathing.cpp
    engines/sci/engine/kvideo.cpp
    engines/sci/engine/savegame.cpp
    engines/sci/graphics/frameout.cpp
    engines/sci/graphics/frameout.h
    engines/sci/graphics/maciconbar.cpp
    engines/sci/graphics/palette.cpp
    engines/sci/graphics/palette.h
    engines/sci/module.mk
    engines/sci/sci.cpp
    engines/sci/sci.h



diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index 5cd7b9f..438c725 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -487,8 +487,8 @@ bool Console::cmdGetVersion(int argc, const char **argv) {
 		debugPrintf("SCI2.1 kernel table: %s\n", (_engine->_features->detectSci21KernelType() == SCI_VERSION_2) ? "modified SCI2 (old)" : "SCI2.1 (new)");
 #endif
 	debugPrintf("View type: %s\n", viewTypeDesc[g_sci->getResMan()->getViewType()]);
-	debugPrintf("Uses palette merging: %s\n", g_sci->_gfxPalette->isMerging() ? "yes" : "no");
-	debugPrintf("Uses 16 bit color matching: %s\n", g_sci->_gfxPalette->isUsing16bitColorMatch() ? "yes" : "no");
+	debugPrintf("Uses palette merging: %s\n", g_sci->_gfxPalette16->isMerging() ? "yes" : "no");
+	debugPrintf("Uses 16 bit color matching: %s\n", g_sci->_gfxPalette16->isUsing16bitColorMatch() ? "yes" : "no");
 	debugPrintf("Resource volume version: %s\n", g_sci->getResMan()->getVolVersionDesc());
 	debugPrintf("Resource map version: %s\n", g_sci->getResMan()->getMapVersionDesc());
 	debugPrintf("Contains selector vocabulary (vocab.997): %s\n", hasVocab997 ? "yes" : "no");
@@ -1618,7 +1618,7 @@ bool Console::cmdSetPalette(int argc, const char **argv) {
 
 	uint16 resourceId = atoi(argv[1]);
 
-	_engine->_gfxPalette->kernelSetFromResource(resourceId, true);
+	_engine->_gfxPalette16->kernelSetFromResource(resourceId, true);
 	return true;
 }
 
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index 8b790e6..0b945c1 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -254,7 +254,7 @@ reg_t kGraph(EngineState *s, int argc, reg_t *argv) {
 }
 
 reg_t kGraphGetColorCount(EngineState *s, int argc, reg_t *argv) {
-	return make_reg(0, g_sci->_gfxPalette->getTotalColorCount());
+	return make_reg(0, g_sci->_gfxPalette16->getTotalColorCount());
 }
 
 reg_t kGraphDrawLine(EngineState *s, int argc, reg_t *argv) {
@@ -596,10 +596,10 @@ reg_t kPaletteSetFromResource(EngineState *s, int argc, reg_t *argv) {
 	// Non-VGA games don't use palette resources.
 	// This has been changed to 64 colors because Longbow Amiga does have
 	// one palette (palette 999).
-	if (g_sci->_gfxPalette->getTotalColorCount() < 64)
+	if (g_sci->_gfxPalette16->getTotalColorCount() < 64)
 		return s->r_acc;
 
-	g_sci->_gfxPalette->kernelSetFromResource(resourceId, force);
+	g_sci->_gfxPalette16->kernelSetFromResource(resourceId, force);
 	return s->r_acc;
 }
 
@@ -607,7 +607,7 @@ reg_t kPaletteSetFlag(EngineState *s, int argc, reg_t *argv) {
 	uint16 fromColor = CLIP<uint16>(argv[0].toUint16(), 1, 255);
 	uint16 toColor = CLIP<uint16>(argv[1].toUint16(), 1, 255);
 	uint16 flags = argv[2].toUint16();
-	g_sci->_gfxPalette->kernelSetFlag(fromColor, toColor, flags);
+	g_sci->_gfxPalette16->kernelSetFlag(fromColor, toColor, flags);
 	return s->r_acc;
 }
 
@@ -615,7 +615,7 @@ reg_t kPaletteUnsetFlag(EngineState *s, int argc, reg_t *argv) {
 	uint16 fromColor = CLIP<uint16>(argv[0].toUint16(), 1, 255);
 	uint16 toColor = CLIP<uint16>(argv[1].toUint16(), 1, 255);
 	uint16 flags = argv[2].toUint16();
-	g_sci->_gfxPalette->kernelUnsetFlag(fromColor, toColor, flags);
+	g_sci->_gfxPalette16->kernelUnsetFlag(fromColor, toColor, flags);
 	return s->r_acc;
 }
 
@@ -626,10 +626,10 @@ reg_t kPaletteSetIntensity(EngineState *s, int argc, reg_t *argv) {
 	bool setPalette = (argc < 4) ? true : (argv[3].isNull()) ? true : false;
 
 	// Palette intensity in non-VGA SCI1 games has been removed
-	if (g_sci->_gfxPalette->getTotalColorCount() < 256)
+	if (g_sci->_gfxPalette16->getTotalColorCount() < 256)
 		return s->r_acc;
 
-	g_sci->_gfxPalette->kernelSetIntensity(fromColor, toColor, intensity, setPalette);
+	g_sci->_gfxPalette16->kernelSetIntensity(fromColor, toColor, intensity, setPalette);
 	return s->r_acc;
 }
 
@@ -637,7 +637,7 @@ reg_t kPaletteFindColor(EngineState *s, int argc, reg_t *argv) {
 	uint16 r = argv[0].toUint16();
 	uint16 g = argv[1].toUint16();
 	uint16 b = argv[2].toUint16();
-	return make_reg(0, g_sci->_gfxPalette->kernelFindColor(r, g, b));
+	return make_reg(0, g_sci->_gfxPalette16->kernelFindColor(r, g, b));
 }
 
 reg_t kPaletteAnimate(EngineState *s, int argc, reg_t *argv) {
@@ -645,18 +645,18 @@ reg_t kPaletteAnimate(EngineState *s, int argc, reg_t *argv) {
 	bool paletteChanged = false;
 
 	// Palette animation in non-VGA SCI1 games has been removed
-	if (g_sci->_gfxPalette->getTotalColorCount() < 256)
+	if (g_sci->_gfxPalette16->getTotalColorCount() < 256)
 		return s->r_acc;
 
 	for (argNr = 0; argNr < argc; argNr += 3) {
 		uint16 fromColor = argv[argNr].toUint16();
 		uint16 toColor = argv[argNr + 1].toUint16();
 		int16 speed = argv[argNr + 2].toSint16();
-		if (g_sci->_gfxPalette->kernelAnimate(fromColor, toColor, speed))
+		if (g_sci->_gfxPalette16->kernelAnimate(fromColor, toColor, speed))
 			paletteChanged = true;
 	}
 	if (paletteChanged)
-		g_sci->_gfxPalette->kernelAnimateSet();
+		g_sci->_gfxPalette16->kernelAnimateSet();
 
 	// WORKAROUND: The game scripts in SQ4 floppy count the number of elapsed
 	// cycles in the intro from the number of successive kAnimate calls during
@@ -676,11 +676,11 @@ reg_t kPaletteAnimate(EngineState *s, int argc, reg_t *argv) {
 }
 
 reg_t kPaletteSave(EngineState *s, int argc, reg_t *argv) {
-	return g_sci->_gfxPalette->kernelSave();
+	return g_sci->_gfxPalette16->kernelSave();
 }
 
 reg_t kPaletteRestore(EngineState *s, int argc, reg_t *argv) {
-	g_sci->_gfxPalette->kernelRestore(argv[0]);
+	g_sci->_gfxPalette16->kernelRestore(argv[0]);
 	return argv[0];
 }
 
@@ -695,7 +695,7 @@ reg_t kPalVaryInit(EngineState *s, int argc, reg_t *argv) {
 	uint16 ticks = argv[1].toUint16();
 	uint16 stepStop = argc >= 3 ? argv[2].toUint16() : 64;
 	uint16 direction = argc >= 4 ? argv[3].toUint16() : 1;
-	if (g_sci->_gfxPalette->kernelPalVaryInit(paletteId, ticks, stepStop, direction))
+	if (g_sci->_gfxPalette16->kernelPalVaryInit(paletteId, ticks, stepStop, direction))
 		return SIGNAL_REG;
 	return NULL_REG;
 }
@@ -705,40 +705,40 @@ reg_t kPalVaryReverse(EngineState *s, int argc, reg_t *argv) {
 	int16 stepStop = argc >= 2 ? argv[1].toUint16() : 0;
 	int16 direction = argc >= 3 ? argv[2].toSint16() : -1;
 
-	return make_reg(0, g_sci->_gfxPalette->kernelPalVaryReverse(ticks, stepStop, direction));
+	return make_reg(0, g_sci->_gfxPalette16->kernelPalVaryReverse(ticks, stepStop, direction));
 }
 
 reg_t kPalVaryGetCurrentStep(EngineState *s, int argc, reg_t *argv) {
-	return make_reg(0, g_sci->_gfxPalette->kernelPalVaryGetCurrentStep());
+	return make_reg(0, g_sci->_gfxPalette16->kernelPalVaryGetCurrentStep());
 }
 
 reg_t kPalVaryDeinit(EngineState *s, int argc, reg_t *argv) {
-	g_sci->_gfxPalette->kernelPalVaryDeinit();
+	g_sci->_gfxPalette16->kernelPalVaryDeinit();
 	return NULL_REG;
 }
 
 reg_t kPalVaryChangeTarget(EngineState *s, int argc, reg_t *argv) {
 	GuiResourceId paletteId = argv[0].toUint16();
-	int16 currentStep = g_sci->_gfxPalette->kernelPalVaryChangeTarget(paletteId);
+	int16 currentStep = g_sci->_gfxPalette16->kernelPalVaryChangeTarget(paletteId);
 	return make_reg(0, currentStep);
 }
 
 reg_t kPalVaryChangeTicks(EngineState *s, int argc, reg_t *argv) {
 	uint16 ticks = argv[0].toUint16();
-	g_sci->_gfxPalette->kernelPalVaryChangeTicks(ticks);
+	g_sci->_gfxPalette16->kernelPalVaryChangeTicks(ticks);
 	return NULL_REG;
 }
 
 reg_t kPalVaryPauseResume(EngineState *s, int argc, reg_t *argv) {
 	bool pauseState = !argv[0].isNull();
-	g_sci->_gfxPalette->kernelPalVaryPause(pauseState);
+	g_sci->_gfxPalette16->kernelPalVaryPause(pauseState);
 	return NULL_REG;
 }
 
 reg_t kAssertPalette(EngineState *s, int argc, reg_t *argv) {
 	GuiResourceId paletteId = argv[0].toUint16();
 
-	g_sci->_gfxPalette->kernelAssertPalette(paletteId);
+	g_sci->_gfxPalette16->kernelAssertPalette(paletteId);
 	return s->r_acc;
 }
 
@@ -1253,16 +1253,16 @@ reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) {
 	switch (operation) {
 	case 0: { // remap by percent
 		uint16 percent = argv[1].toUint16();
-		g_sci->_gfxPalette->resetRemapping();
-		g_sci->_gfxPalette->setRemappingPercent(254, percent);
+		g_sci->_gfxPalette16->resetRemapping();
+		g_sci->_gfxPalette16->setRemappingPercent(254, percent);
 		}
 		break;
 	case 1:	{ // remap by range
 		uint16 from = argv[1].toUint16();
 		uint16 to = argv[2].toUint16();
 		uint16 base = argv[3].toUint16();
-		g_sci->_gfxPalette->resetRemapping();
-		g_sci->_gfxPalette->setRemappingRange(254, from, to, base);
+		g_sci->_gfxPalette16->resetRemapping();
+		g_sci->_gfxPalette16->setRemappingRange(254, from, to, base);
 		}
 		break;
 	case 2:	// turn remapping off (unused)
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index 8953f45..5de440c 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -49,6 +49,7 @@
 #include "sci/graphics/text16.h"
 #include "sci/graphics/view.h"
 #ifdef ENABLE_SCI32
+#include "sci/graphics/palette32.h"
 #include "sci/graphics/controls32.h"
 #include "sci/graphics/font.h"	// TODO: remove once kBitmap is moved in a separate class
 #include "sci/graphics/text32.h"
@@ -707,66 +708,64 @@ reg_t kPalVaryUnknown2(EngineState *s, int argc, reg_t *argv) {
 	return kStub(s, argc, argv);
 }
 
+enum {
+	kSetCycle = 0,
+	kDoCycle = 1,
+	kCyclePause = 2,
+	kCycleOn = 3,
+	kCycleOff = 4
+};
+
 reg_t kPalCycle(EngineState *s, int argc, reg_t *argv) {
 	// Examples: GK1 room 480 (Bayou ritual), LSL6 room 100 (title screen)
 
 	switch (argv[0].toUint16()) {
-	case 0: {	// Palette animation initialization
-		// 3 or 4 extra params
-		// Case 1 sends fromColor and speed again, so we don't need them here.
-		// Only toColor is stored
-		//uint16 fromColor = argv[1].toUint16();
-		s->_palCycleToColor = argv[2].toUint16();
-		//uint16 speed = argv[3].toUint16();
-
-		// Invalidate the picture, so that the palette steps calls (case 1
-		// below) can update its palette without it being overwritten by the
-		// view/picture palettes.
-		g_sci->_gfxScreen->_picNotValid = 1;
-
-		// TODO: The fourth optional parameter is an unknown integer, and is 0 by default
-		if (argc == 5) {
-			// When this variant is used, picNotValid doesn't seem to be set
-			// (e.g. GK1 room 480). In this case, the animation step calls are
-			// not made, so perhaps this signifies the palette cycling steps
-			// to make.
-			// GK1 sets this to 6 (6 palette steps?)
-			g_sci->_gfxScreen->_picNotValid = 0;
-		}
-		kStub(s, argc, argv);
+	case kSetCycle: {
+		uint16 fromColor = argv[1].toUint16();
+		uint16 toColor = argv[2].toUint16();
+		int16 direction = argv[3].toSint16();
+		uint16 delay = (argc == 4 ? 0 : argv[4].toUint16());
+
+		g_sci->_gfxPalette32->setCycle(fromColor, toColor, direction, delay);
 		}
 		break;
-	case 1:	{ // Palette animation step
-		// This is the same as the old kPaletteAnimate call, with 1 set of colors.
-		// The end color is set up during initialization in case 0 above.
-
-		// 1 or 2 extra params
+	case kDoCycle: {
 		uint16 fromColor = argv[1].toUint16();
-		uint16 speed = (argc == 2) ? 1 : argv[2].toUint16();
-		// TODO: For some reason, this doesn't set the color correctly
-		// (e.g. LSL6 intro, room 100, Sierra logo)
-		if (g_sci->_gfxPalette->kernelAnimate(fromColor, s->_palCycleToColor, speed))
-			g_sci->_gfxPalette->kernelAnimateSet();
+		int16 speed = (argc == 2) ? 1 : argv[2].toSint16();
+		g_sci->_gfxPalette32->doCycle(fromColor, speed);
 		}
-		// No kStub() call here, as this gets called loads of times, like kPaletteAnimate
 		break;
-	// case 2 hasn't been encountered
-	// case 3 hasn't been encountered
-	case 4:	// reset any palette cycling and make the picture valid again
-		// Gets called when changing rooms and after palette cycling animations finish
-		// 0 or 1 extra params
+	case kCyclePause: {
 		if (argc == 1) {
-			g_sci->_gfxScreen->_picNotValid = 0;
-			// TODO: This also seems to perform more steps
+			g_sci->_gfxPalette32->cycleAllPause();
 		} else {
-			// The variant with the 1 extra param resets remapping to base
-			// TODO
+			uint16 fromColor = argv[1].toUint16();
+			g_sci->_gfxPalette32->cyclePause(fromColor);
+		}
+		}
+		break;
+	case kCycleOn: {
+		if (argc == 1) {
+			g_sci->_gfxPalette32->cycleAllOn();
+		} else {
+			uint16 fromColor = argv[1].toUint16();
+			g_sci->_gfxPalette32->cycleOn(fromColor);
+		}
+		}
+		break;
+	case kCycleOff: {
+		if (argc == 1) {
+			g_sci->_gfxPalette32->cycleAllOff();
+		} else {
+			uint16 fromColor = argv[1].toUint16();
+			g_sci->_gfxPalette32->cycleOff(fromColor);
 		}
-		kStub(s, argc, argv);
 		break;
+		}
 	default:
-		// TODO
-		kStub(s, argc, argv);
+		// In SCI2.1 there are no values above 4, so should never get here;
+		// SCI just returns early if this ever happens.
+		assert(false);
 		break;
 	}
 
@@ -787,7 +786,7 @@ reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) {
 		int16 base = (argc >= 2) ? argv[1].toSint16() : 0;
 		if (base > 0)
 			warning("kRemapColors(0) called with base %d", base);
-		g_sci->_gfxPalette->resetRemapping();
+		g_sci->_gfxPalette32->resetRemapping();
 		}
 		break;
 	case 1:	{ // remap by range
@@ -798,7 +797,7 @@ reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) {
 		uint16 unk5 = (argc >= 6) ? argv[5].toUint16() : 0;
 		if (unk5 > 0)
 			warning("kRemapColors(1) called with 6 parameters, unknown parameter is %d", unk5);
-		g_sci->_gfxPalette->setRemappingRange(color, from, to, base);
+		g_sci->_gfxPalette32->setRemappingRange(color, from, to, base);
 		}
 		break;
 	case 2:	{ // remap by percent
@@ -806,7 +805,7 @@ reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) {
 		uint16 percent = argv[2].toUint16(); // 0 - 100
 		if (argc >= 4)
 			warning("RemapByPercent called with 4 parameters, unknown parameter is %d", argv[3].toUint16());
-		g_sci->_gfxPalette->setRemappingPercent(color, percent);
+		g_sci->_gfxPalette32->setRemappingPercent(color, percent);
 		}
 		break;
 	case 3:	{ // remap to gray
@@ -816,7 +815,7 @@ reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) {
 		int16 percent = argv[2].toSint16(); // 0 - 100
 		if (argc >= 4)
 			warning("RemapToGray called with 4 parameters, unknown parameter is %d", argv[3].toUint16());
-		g_sci->_gfxPalette->setRemappingPercentGray(color, percent);
+		g_sci->_gfxPalette32->setRemappingPercentGray(color, percent);
 		}
 		break;
 	case 4:	{ // remap to percent gray
@@ -826,7 +825,7 @@ reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) {
 		// argv[3] is unknown (a number, e.g. 200) - start color, perhaps?
 		if (argc >= 5)
 			warning("RemapToGrayPercent called with 5 parameters, unknown parameter is %d", argv[4].toUint16());
-		g_sci->_gfxPalette->setRemappingPercentGray(color, percent);
+		g_sci->_gfxPalette32->setRemappingPercentGray(color, percent);
 		}
 		break;
 	case 5:	{ // don't map to range
@@ -834,7 +833,7 @@ reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) {
 		uint16 intensity = argv[2].toUint16();
 		// HACK for PQ4
 		if (g_sci->getGameId() == GID_PQ4)
-			g_sci->_gfxPalette->kernelSetIntensity(0, 255, intensity, true);
+			g_sci->_gfxPalette32->kernelSetIntensity(0, 255, intensity, true);
 
 		kStub(s, argc, argv);
 		}
diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp
index 67d814b..5b2245e 100644
--- a/engines/sci/engine/kpathing.cpp
+++ b/engines/sci/engine/kpathing.cpp
@@ -312,10 +312,10 @@ static void draw_line(EngineState *s, Common::Point p1, Common::Point p2, int ty
 	// Red : Barred access
 	// Yellow: Contained access
 	int poly_colors[4] = {
-		g_sci->_gfxPalette->kernelFindColor(0, 255, 0),	// green
-		g_sci->_gfxPalette->kernelFindColor(0, 0, 255),	// blue
-		g_sci->_gfxPalette->kernelFindColor(255, 0, 0),	// red
-		g_sci->_gfxPalette->kernelFindColor(255, 255, 0)	// yellow
+		g_sci->_gfxPalette16->kernelFindColor(0, 255, 0),	// green
+		g_sci->_gfxPalette16->kernelFindColor(0, 0, 255),	// blue
+		g_sci->_gfxPalette16->kernelFindColor(255, 0, 0),	// red
+		g_sci->_gfxPalette16->kernelFindColor(255, 255, 0)	// yellow
 	};
 
 	// Clip
@@ -334,8 +334,8 @@ static void draw_point(EngineState *s, Common::Point p, int start, int width, in
 	// Green: End point
 	// Blue: Starting point
 	int point_colors[2] = {
-		g_sci->_gfxPalette->kernelFindColor(0, 255, 0),	// green
-		g_sci->_gfxPalette->kernelFindColor(0, 0, 255)		// blue
+		g_sci->_gfxPalette16->kernelFindColor(0, 255, 0),	// green
+		g_sci->_gfxPalette16->kernelFindColor(0, 0, 255)		// blue
 	};
 
 	Common::Rect rect = Common::Rect(p.x - 1, p.y - 1, p.x - 1 + 3, p.y - 1 + 3);
diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp
index 6920466..8db0c54 100644
--- a/engines/sci/engine/kvideo.cpp
+++ b/engines/sci/engine/kvideo.cpp
@@ -231,7 +231,7 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) {
 			initGraphics(screenWidth, screenHeight, screenWidth > 320);
 		else {
 			g_sci->_gfxScreen->kernelSyncWithFramebuffer();
-			g_sci->_gfxPalette->kernelSyncScreenPalette();
+			g_sci->_gfxPalette16->kernelSyncScreenPalette();
 		}
 	}
 
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index b464d34..09ccff3 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -304,7 +304,7 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) {
 	_segMan->saveLoadWithSerializer(s);
 
 	g_sci->_soundCmd->syncPlayList(s);
-	g_sci->_gfxPalette->saveLoadWithSerializer(s);
+	g_sci->_gfxPalette16->saveLoadWithSerializer(s);
 }
 
 void Vocabulary::saveLoadWithSerializer(Common::Serializer &s) {
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index 61aeb00..7396115 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -44,7 +44,7 @@
 #include "sci/graphics/view.h"
 #include "sci/graphics/screen.h"
 #include "sci/graphics/paint32.h"
-#include "sci/graphics/palette.h"
+#include "sci/graphics/palette32.h"
 #include "sci/graphics/picture.h"
 #include "sci/graphics/text32.h"
 #include "sci/graphics/frameout.h"
@@ -59,7 +59,7 @@ enum SciSpeciaPlanelPictureCodes {
 	kPlanePlainColored = 0xffff		// -1
 };
 
-GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxCache *cache, GfxScreen *screen, GfxPalette *palette, GfxPaint32 *paint32)
+GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxCache *cache, GfxScreen *screen, GfxPalette32 *palette, GfxPaint32 *paint32)
 	: _segMan(segMan), _resMan(resMan), _cache(cache), _screen(screen), _palette(palette), _paint32(paint32) {
 
 	_coordAdjuster = (GfxCoordAdjuster32 *)coordAdjuster;
@@ -658,6 +658,11 @@ void GfxFrameout::kernelFrameout() {
 	}
 
 	_palette->palVaryUpdate();
+	_palette->applyCycles();
+	_palette->applyFade();
+	// TODO: This should probably not require screen pic invalidation
+	_screen->_picNotValid = 1;
+	_palette->setOnScreen();
 
 	for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); it++) {
 		reg_t planeObject = it->object;
diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h
index e0c60f9..a422572 100644
--- a/engines/sci/graphics/frameout.h
+++ b/engines/sci/graphics/frameout.h
@@ -114,7 +114,7 @@ class GfxScreen;
  */
 class GfxFrameout {
 public:
-	GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxCache *cache, GfxScreen *screen, GfxPalette *palette, GfxPaint32 *paint32);
+	GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxCache *cache, GfxScreen *screen, GfxPalette32 *palette, GfxPaint32 *paint32);
 	~GfxFrameout();
 
 	void kernelAddPlane(reg_t object);
@@ -161,7 +161,7 @@ private:
 	ResourceManager *_resMan;
 	GfxCoordAdjuster32 *_coordAdjuster;
 	GfxCache *_cache;
-	GfxPalette *_palette;
+	GfxPalette32 *_palette;
 	GfxScreen *_screen;
 	GfxPaint32 *_paint32;
 
diff --git a/engines/sci/graphics/maciconbar.cpp b/engines/sci/graphics/maciconbar.cpp
index 8e2e12b..e10b9fd 100644
--- a/engines/sci/graphics/maciconbar.cpp
+++ b/engines/sci/graphics/maciconbar.cpp
@@ -234,7 +234,7 @@ void GfxMacIconBar::remapColors(Graphics::Surface *surf, const byte *palette) {
 		byte g = palette[color * 3 + 1];
 		byte b = palette[color * 3 + 2];
 
-		*pixels++ = g_sci->_gfxPalette->findMacIconBarColor(r, g, b);
+		*pixels++ = g_sci->_gfxPalette16->findMacIconBarColor(r, g, b);
 	}
 }
 
diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp
index 59abef5..667aef4 100644
--- a/engines/sci/graphics/palette.cpp
+++ b/engines/sci/graphics/palette.cpp
@@ -86,10 +86,6 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen)
 	_macClut = 0;
 	loadMacIconBarPalette();
 
-#ifdef ENABLE_SCI32
-	_clutTable = 0;
-#endif
-
 	switch (_resMan->getViewType()) {
 	case kViewEga:
 		_totalScreenColors = 16;
@@ -117,10 +113,6 @@ GfxPalette::~GfxPalette() {
 		palVaryRemoveTimer();
 
 	delete[] _macClut;
-
-#ifdef ENABLE_SCI32
-	unloadClut();
-#endif
 }
 
 bool GfxPalette::isMerging() {
@@ -819,6 +811,8 @@ bool GfxPalette::palVaryLoadTargetPalette(GuiResourceId resourceId) {
 	return false;
 }
 
+// TODO: This code should not set up an independent timer in SCI32. SCI32 engine palette varies happen in
+// Palette::UpdateForFrame which is called by GraphicsMgr::FrameOut.
 void GfxPalette::palVaryInstallTimer() {
 	// Remove any possible leftover palVary timer callbacks.
 	// This happens for example in QFG1VGA, when sleeping at Erana's place
@@ -1087,58 +1081,4 @@ bool GfxPalette::colorIsFromMacClut(byte index) {
 	return index != 0 && _macClut && (_macClut[index * 3] != 0 || _macClut[index * 3 + 1] != 0 || _macClut[index * 3 + 2] != 0);
 }
 
-#ifdef ENABLE_SCI32
-
-bool GfxPalette::loadClut(uint16 clutId) {
-	// loadClut() will load a color lookup table from a clu file and set
-	// the palette found in the file. This is to be used with Phantasmagoria 2.
-
-	unloadClut();
-
-	Common::String filename = Common::String::format("%d.clu", clutId);
-	Common::File clut;
-
-	if (!clut.open(filename) || clut.size() != 0x10000 + 236 * 3)
-		return false;
-
-	// Read in the lookup table
-	// It maps each RGB565 color to a palette index
-	_clutTable = new byte[0x10000];
-	clut.read(_clutTable, 0x10000);
-
-	Palette pal;
-	memset(&pal, 0, sizeof(Palette));
-
-	// Setup 1:1 mapping
-	for (int i = 0; i < 256; i++) {
-		pal.mapping[i] = i;
-	}
-
-	// Now load in the palette
-	for (int i = 1; i <= 236; i++) {
-		pal.colors[i].used = 1;
-		pal.colors[i].r = clut.readByte();
-		pal.colors[i].g = clut.readByte();
-		pal.colors[i].b = clut.readByte();
-	}
-
-	set(&pal, true);
-	setOnScreen();
-	return true;
-}
-
-byte GfxPalette::matchClutColor(uint16 color) {
-	// Match a color in RGB565 format to a palette index based on the loaded CLUT
-	assert(_clutTable);
-	return _clutTable[color];
-}
-
-void GfxPalette::unloadClut() {
-	// This will only unload the actual table, but not reset any palette
-	delete[] _clutTable;
-	_clutTable = 0;
-}
-
-#endif
-
 } // End of namespace Sci
diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h
index 500a45e..82fd20a 100644
--- a/engines/sci/graphics/palette.h
+++ b/engines/sci/graphics/palette.h
@@ -110,12 +110,6 @@ public:
 	byte findMacIconBarColor(byte r, byte g, byte b);
 	bool colorIsFromMacClut(byte index);
 
-#ifdef ENABLE_SCI32
-	bool loadClut(uint16 clutId);
-	byte matchClutColor(uint16 color);
-	void unloadClut();
-#endif
-
 private:
 	void palVaryInit();
 	void palVaryInstallTimer();
@@ -152,10 +146,6 @@ private:
 
 	void loadMacIconBarPalette();
 	byte *_macClut;
-
-#ifdef ENABLE_SCI32
-	byte *_clutTable;
-#endif
 };
 
 } // End of namespace Sci
diff --git a/engines/sci/graphics/palette32.cpp b/engines/sci/graphics/palette32.cpp
new file mode 100644
index 0000000..61ca1b9
--- /dev/null
+++ b/engines/sci/graphics/palette32.cpp
@@ -0,0 +1,350 @@
+/* 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/file.h"
+
+#include "sci/sci.h"
+#include "sci/graphics/palette32.h"
+
+namespace Sci {
+	
+GfxPalette32::GfxPalette32(ResourceManager *resMan, GfxScreen *screen)
+	: GfxPalette(resMan, screen), _clutTable(0), _cyclers(), _cycleMap() {}
+
+GfxPalette32::~GfxPalette32() {
+	unloadClut();
+	cycleAllOff();
+}
+
+bool GfxPalette32::loadClut(uint16 clutId) {
+	// loadClut() will load a color lookup table from a clu file and set
+	// the palette found in the file. This is to be used with Phantasmagoria 2.
+
+	unloadClut();
+
+	Common::String filename = Common::String::format("%d.clu", clutId);
+	Common::File clut;
+
+	if (!clut.open(filename) || clut.size() != 0x10000 + 236 * 3)
+		return false;
+
+	// Read in the lookup table
+	// It maps each RGB565 color to a palette index
+	_clutTable = new byte[0x10000];
+	clut.read(_clutTable, 0x10000);
+
+	Palette pal;
+	memset(&pal, 0, sizeof(Palette));
+
+	// Setup 1:1 mapping
+	for (int i = 0; i < 256; i++) {
+		pal.mapping[i] = i;
+	}
+
+	// Now load in the palette
+	for (int i = 1; i <= 236; i++) {
+		pal.colors[i].used = 1;
+		pal.colors[i].r = clut.readByte();
+		pal.colors[i].g = clut.readByte();
+		pal.colors[i].b = clut.readByte();
+	}
+
+	set(&pal, true);
+	setOnScreen();
+	return true;
+}
+
+byte GfxPalette32::matchClutColor(uint16 color) {
+	// Match a color in RGB565 format to a palette index based on the loaded CLUT
+	assert(_clutTable);
+	return _clutTable[color];
+}
+
+void GfxPalette32::unloadClut() {
+	// This will only unload the actual table, but not reset any palette
+	delete[] _clutTable;
+	_clutTable = 0;
+}
+
+inline void GfxPalette32::_clearCycleMap(const uint16 fromColor, const uint16 numColorsToClear) {
+	bool *mapEntry = _cycleMap + fromColor;
+	const bool *lastEntry = _cycleMap + numColorsToClear;
+	while (mapEntry < lastEntry) {
+		*mapEntry++ = false;
+	}
+}
+
+inline void GfxPalette32::_setCycleMap(const uint16 fromColor, const uint16 numColorsToSet) {
+	bool *mapEntry = _cycleMap + fromColor;
+	const bool *lastEntry = _cycleMap + numColorsToSet;
+	while (mapEntry < lastEntry) {
+		if (*mapEntry != false) {
+			error("Cycles intersect");
+		}
+		*mapEntry++ = true;
+	}
+}
+
+inline PalCycler *GfxPalette32::_getCycler(const uint16 fromColor) {
+	const int numCyclers = ARRAYSIZE(_cyclers);
+
+	for (int cyclerIndex = 0; cyclerIndex < numCyclers; ++cyclerIndex) {
+		PalCycler *cycler = _cyclers[cyclerIndex];
+		if (cycler != nullptr && cycler->fromColor == fromColor) {
+			return cycler;
+		}
+	}
+
+	return nullptr;
+}
+
+inline void _doCycle(PalCycler *cycler, const int16 speed) {
+	int16 currentCycle = cycler->currentCycle;
+	const uint16 numColorsToCycle = cycler->numColorsToCycle;
+
+	if (cycler->direction == 0) {
+		currentCycle = (currentCycle - (speed % numColorsToCycle)) + numColorsToCycle;
+	} else {
+		currentCycle = currentCycle + speed;
+	}
+
+	cycler->currentCycle = (uint8) (currentCycle % numColorsToCycle);
+}
+
+inline void _applyCycleToPalette(PalCycler *cycler, Palette *palette) {
+	const int16 currentCycle = cycler->currentCycle;
+	const uint16 numColorsToCycle = cycler->numColorsToCycle;
+
+	Sci::Color tempPalette[numColorsToCycle];
+	Sci::Color *sourceColor = palette->colors + cycler->fromColor;
+	memcpy(tempPalette, sourceColor, sizeof(tempPalette));
+
+	Sci::Color *targetColor = sourceColor;
+	for (int numColorsCycled = 0; numColorsCycled < numColorsToCycle; ++numColorsCycled) {
+		Sci::Color sourceColor = *(tempPalette + ((currentCycle + numColorsCycled) % numColorsToCycle));
+		*(targetColor + numColorsCycled) = sourceColor;
+	}
+}
+
+void GfxPalette32::applyAllCycles() {
+	for (int cyclerIndex = 0, numCyclers = ARRAYSIZE(_cyclers); cyclerIndex < numCyclers; ++cyclerIndex) {
+		PalCycler *cycler = _cyclers[cyclerIndex];
+		if (cycler != nullptr) {
+			cycler->currentCycle = (uint8) ((((int) cycler->currentCycle) + 1) % cycler->numColorsToCycle);
+			// Disassembly was not fully evaluated to verify this is exactly the same
+			// as the code from applyCycles, but it appeared to be at a glance
+			_applyCycleToPalette(cycler, &_sysPalette);
+		}
+	}
+}
+
+void GfxPalette32::applyCycles() {
+	for (int i = 0, len = ARRAYSIZE(_cyclers); i < len; ++i) {
+		PalCycler *cycler = _cyclers[i];
+		if (cycler == nullptr) {
+			continue;
+		}
+
+		if (cycler->delay != 0 && cycler->numTimesPaused == 0) {
+			while ((cycler->delay + cycler->lastUpdateTick) < g_sci->getTickCount()) {
+				_doCycle(cycler, 1);
+				cycler->lastUpdateTick += cycler->delay;
+			}
+		}
+
+		_applyCycleToPalette(cycler, &_sysPalette);
+	}
+}
+
+int16 GfxPalette32::setCycle(const uint16 fromColor, const uint16 toColor, const int16 direction, const int16 delay) {
+	assert(fromColor <= UINT8_MAX);
+	assert(toColor <= UINT8_MAX);
+	assert(fromColor < toColor);
+
+	int cyclerIndex;
+	const int numCyclers = ARRAYSIZE(_cyclers);
+
+	PalCycler *cycler = _getCycler(fromColor);
+
+	if (cycler != nullptr) {
+		debug("Resetting existing cycler");
+		_clearCycleMap(fromColor, cycler->numColorsToCycle);
+	} else {
+		for (cyclerIndex = 0; cyclerIndex < numCyclers; ++cyclerIndex) {
+			if (_cyclers[cyclerIndex] == nullptr) {
+				cycler = new PalCycler;
+				_cyclers[cyclerIndex] = cycler;
+				break;
+			}
+		}
+	}
+
+	// SCI engine overrides the first oldest cycler that it finds where
+	// “oldest” is determined by the difference between the tick and now
+	if (cycler == nullptr) {
+		int maxUpdateDelta = -1;
+		// Optimization: Unlike actual SCI (SQ6) engine, we call
+		// getTickCount only once and store it, instead of calling it
+		// twice on each iteration through the loop
+		const uint32 now = g_sci->getTickCount();
+
+		for (cyclerIndex = 0; cyclerIndex < numCyclers; ++cyclerIndex) {
+			PalCycler *candidate = _cyclers[cyclerIndex];
+
+			const int32 updateDelta = now - candidate->lastUpdateTick;
+			if (updateDelta >= maxUpdateDelta) {
+				maxUpdateDelta = updateDelta;
+				cycler = candidate;
+			}
+		}
+
+		_clearCycleMap(cycler->fromColor, cycler->numColorsToCycle);
+	}
+
+	const uint16 numColorsToCycle = 1 + ((uint8) toColor) - fromColor;
+	cycler->fromColor = (uint8) fromColor;
+	cycler->numColorsToCycle = (uint8) numColorsToCycle;
+	cycler->currentCycle = (uint8) fromColor;
+	cycler->direction = direction < 0 ? PalCycleBackward : PalCycleForward;
+	cycler->delay = delay;
+	cycler->lastUpdateTick = g_sci->getTickCount();
+	cycler->numTimesPaused = 0;
+
+	_setCycleMap(fromColor, numColorsToCycle);
+
+	// TODO: Validate that this is the correct return value according
+	// to disassembly
+	return 0;
+}
+
+void GfxPalette32::doCycle(const uint16 fromColor, const int16 speed) {
+	PalCycler *cycler = _getCycler(fromColor);
+	if (cycler != nullptr) {
+		cycler->lastUpdateTick = g_sci->getTickCount();
+		_doCycle(cycler, speed);
+	}
+}
+
+void GfxPalette32::cycleOn(const uint16 fromColor) {
+	PalCycler *cycler = _getCycler(fromColor);
+	if (cycler != nullptr && cycler->numTimesPaused > 0) {
+		--cycler->numTimesPaused;
+	}
+}
+
+void GfxPalette32::cyclePause(const uint16 fromColor) {
+	PalCycler *cycler = _getCycler(fromColor);
+	if (cycler != nullptr) {
+		++cycler->numTimesPaused;
+	}
+}
+
+void GfxPalette32::cycleAllOn() {
+	for (int i = 0, len = ARRAYSIZE(_cyclers); i < len; ++i) {
+		PalCycler *cycler = _cyclers[i];
+		if (cycler != nullptr && cycler->numTimesPaused > 0) {
+			--cycler->numTimesPaused;
+		}
+	}
+}
+
+void GfxPalette32::cycleAllPause() {
+	// TODO: The SCI SQ6 cycleAllPause function does not seem to perform
+	// nullptr checking?? This would definitely cause null pointer
+	// dereference in SCI code. I have not seen anything actually call
+	// this function yet, so it is possible it is just unused and broken
+	// in SCI SQ6. This assert exists so that if this function is called,
+	// it is noticed and can be rechecked in the actual engine.
+	// Obviously this code *does* do nullptr checks instead of crashing. :)
+	assert(0);
+	for (int i = 0, len = ARRAYSIZE(_cyclers); i < len; ++i) {
+		PalCycler *cycler = _cyclers[i];
+		if (cycler != nullptr) {
+			// This seems odd, because currentCycle is 0..numColorsPerCycle,
+			// but fromColor is 0..255. When applyAllCycles runs, the values
+			// end up back in range
+			cycler->currentCycle = cycler->fromColor;
+		}
+	}
+
+	applyAllCycles();
+
+	for (int i = 0, len = ARRAYSIZE(_cyclers); i < len; ++i) {
+		PalCycler *cycler = _cyclers[i];
+		if (cycler != nullptr) {
+			++cycler->numTimesPaused;
+		}
+	}
+}
+
+void GfxPalette32::cycleOff(const uint16 fromColor) {
+	for (int i = 0, len = ARRAYSIZE(_cyclers); i < len; ++i) {
+		PalCycler *cycler = _cyclers[i];
+		if (cycler != nullptr && cycler->fromColor == fromColor) {
+			_clearCycleMap(fromColor, cycler->numColorsToCycle);
+			delete cycler;
+			_cyclers[i] = nullptr;
+			break;
+		}
+	}
+}
+
+void GfxPalette32::cycleAllOff() {
+	for (int i = 0, len = ARRAYSIZE(_cyclers); i < len; ++i) {
+		PalCycler *cycler = _cyclers[i];
+		if (cycler != nullptr) {
+			_clearCycleMap(cycler->fromColor, cycler->numColorsToCycle);
+			delete cycler;
+			_cyclers[i] = nullptr;
+		}
+	}
+}
+
+void GfxPalette32::applyFade() {
+	// TODO: Create and update a _nextPalette, not a single _sysPalette, to
+	// conform to the way the actual SCI32 engine works (writes to a
+	// next-frame-palette and then copies to the current palette on frameout)
+	Sci::Color *color = _sysPalette.colors;
+	uint8 *fadeAmount = _fadeTable;
+	for (int i = 0; i < 256; ++i) {
+		if (*fadeAmount == 100) {
+			continue;
+		}
+
+		color->r = ((int) color->r * ((int) *fadeAmount)) / 100;
+		color->g = ((int) color->r * ((int) *fadeAmount)) / 100;
+		color->b = ((int) color->r * ((int) *fadeAmount)) / 100;
+	}
+}
+
+void GfxPalette32::setFade(uint8 percent, uint16 fromColor, uint16 toColor) {
+	uint8 *fadeAmount = _fadeTable;
+	for (int i = fromColor, len = toColor - fromColor + 1; i < len; ++i) {
+		*fadeAmount++ = percent;
+	}
+}
+
+void GfxPalette32::fadeOff() {
+	setFade(100, 0, 255);
+}
+
+}
diff --git a/engines/sci/graphics/palette32.h b/engines/sci/graphics/palette32.h
new file mode 100644
index 0000000..87bebbb
--- /dev/null
+++ b/engines/sci/graphics/palette32.h
@@ -0,0 +1,122 @@
+/* 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 SCI_GRAPHICS_PALETTE32_H
+#define SCI_GRAPHICS_PALETTE32_H
+
+#include "sci/graphics/palette.h"
+
+enum PalCyclerDirection {
+	PalCycleBackward = 0,
+	PalCycleForward = 1
+};
+
+struct PalCycler {
+	/**
+	 * The color index of the palette cycler. This value is effectively used as the ID for the
+	 * cycler.
+	 */
+	uint8 fromColor;
+
+	/**
+	 * The number of palette slots which are cycled by the palette cycler.
+	 */
+	uint16 numColorsToCycle;
+
+	/**
+	 * The position of the cursor in its cycle.
+	 */
+	uint8 currentCycle;
+
+	/**
+	 * The direction of the cycler.
+	 */
+	PalCyclerDirection direction;
+
+	/**
+	 * The cycle tick at the last time the cycler’s currentCycle was updated.
+	 * 795 days of game time ought to be enough for everyone? :)
+	 */
+	uint32 lastUpdateTick;
+
+	/**
+	 * The amount of time in ticks each cycle should take to complete. In other words,
+	 * the higher the delay, the slower the cycle animation. If delay is 0, the cycler
+	 * does not automatically cycle and needs to be pumped manually with DoCycle.
+	 */
+	int16 delay;
+
+	/**
+	 * The number of times this cycler has been paused.
+	 */
+	uint16 numTimesPaused;
+};
+
+namespace Sci {
+	class GfxPalette32 : public GfxPalette {
+	public:
+		GfxPalette32(ResourceManager *resMan, GfxScreen *screen);
+		~GfxPalette32();
+
+	private:
+		// SCI2 (SQ6) defines 10 cyclers
+		PalCycler *_cyclers[10];
+		/**
+		 * The cycle map is used to detect overlapping cyclers. According to SCI engine code, when two cyclers overlap,
+		 * a fatal error has occurred and the engine will display an error and then exit.
+		 */
+		bool _cycleMap[256];
+		inline void _clearCycleMap(uint16 fromColor, uint16 numColorsToClear);
+		inline void _setCycleMap(uint16 fromColor, uint16 numColorsToClear);
+		inline PalCycler *_getCycler(uint16 fromColor);
+
+		/**
+		 * The fade table records the expected intensity level of each pixel in the palette that will be displayed on
+		 * the next frame.
+		 */
+		byte _fadeTable[256];
+		byte *_clutTable;
+
+	public:
+		void applyAllCycles();
+		void applyCycles();
+		void applyFade();
+
+		bool loadClut(uint16 clutId);
+		byte matchClutColor(uint16 color);
+		void unloadClut();
+
+		int16 setCycle(uint16 fromColor, uint16 toColor, int16 direction, int16 delay);
+		void doCycle(uint16 fromColor, int16 speed);
+		void cycleOn(uint16 fromColor);
+		void cyclePause(uint16 fromColor);
+		void cycleAllOn();
+		void cycleAllPause();
+		void cycleOff(uint16 fromColor);
+		void cycleAllOff();
+
+		void setFade(uint8 percent, uint16 fromColor, uint16 toColor);
+		void fadeOff();
+	};
+}
+
+#endif
diff --git a/engines/sci/module.mk b/engines/sci/module.mk
index 33392e3..08e5ea8 100644
--- a/engines/sci/module.mk
+++ b/engines/sci/module.mk
@@ -84,6 +84,7 @@ MODULE_OBJS += \
 	graphics/controls32.o \
 	graphics/frameout.o \
 	graphics/paint32.o \
+	graphics/palette32.o \
 	graphics/text32.o \
 	video/robot_decoder.o
 endif
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index f1ab65e..598368e 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -63,6 +63,7 @@
 #include "sci/graphics/transitions.h"
 
 #ifdef ENABLE_SCI32
+#include "sci/graphics/palette32.h"
 #include "sci/graphics/text32.h"
 #include "sci/graphics/frameout.h"
 #include "sci/video/robot_decoder.h"
@@ -153,6 +154,9 @@ SciEngine::~SciEngine() {
 	DebugMan.clearAllDebugChannels();
 
 #ifdef ENABLE_SCI32
+	// _gfxPalette32 is the same as _gfxPalette16
+	// and will be destroyed when _gfxPalette16 is
+	// destroyed
 	delete _gfxControls32;
 	delete _gfxText32;
 	delete _robotDecoder;
@@ -168,7 +172,7 @@ SciEngine::~SciEngine() {
 	delete _gfxCoordAdjuster;
 	delete _gfxPorts;
 	delete _gfxCache;
-	delete _gfxPalette;
+	delete _gfxPalette16;
 	delete _gfxCursor;
 	delete _gfxScreen;
 
@@ -614,7 +618,8 @@ void SciEngine::initGraphics() {
 	_gfxMenu = 0;
 	_gfxPaint = 0;
 	_gfxPaint16 = 0;
-	_gfxPalette = 0;
+	_gfxPalette16 = 0;
+	_gfxPalette32 = 0;
 	_gfxPorts = 0;
 	_gfxText16 = 0;
 	_gfxTransitions = 0;
@@ -629,9 +634,19 @@ void SciEngine::initGraphics() {
 	if (hasMacIconBar())
 		_gfxMacIconBar = new GfxMacIconBar();
 
-	_gfxPalette = new GfxPalette(_resMan, _gfxScreen);
-	_gfxCache = new GfxCache(_resMan, _gfxScreen, _gfxPalette);
-	_gfxCursor = new GfxCursor(_resMan, _gfxPalette, _gfxScreen);
+#ifdef ENABLE_SCI32
+	if (getSciVersion() >= SCI_VERSION_2) {
+		_gfxPalette32 = new GfxPalette32(_resMan, _gfxScreen);
+		_gfxPalette16 = _gfxPalette32;
+	} else {
+#endif
+		_gfxPalette16 = new GfxPalette(_resMan, _gfxScreen);
+#ifdef ENABLE_SCI32
+	}
+#endif
+
+	_gfxCache = new GfxCache(_resMan, _gfxScreen, _gfxPalette16);
+	_gfxCursor = new GfxCursor(_resMan, _gfxPalette16, _gfxScreen);
 
 #ifdef ENABLE_SCI32
 	if (getSciVersion() >= SCI_VERSION_2) {
@@ -639,12 +654,12 @@ void SciEngine::initGraphics() {
 		_gfxCoordAdjuster = new GfxCoordAdjuster32(_gamestate->_segMan);
 		_gfxCursor->init(_gfxCoordAdjuster, _eventMan);
 		_gfxCompare = new GfxCompare(_gamestate->_segMan, _gfxCache, _gfxScreen, _gfxCoordAdjuster);
-		_gfxPaint32 = new GfxPaint32(_resMan, _gfxCoordAdjuster, _gfxScreen, _gfxPalette);
+		_gfxPaint32 = new GfxPaint32(_resMan, _gfxCoordAdjuster, _gfxScreen, _gfxPalette32);
 		_gfxPaint = _gfxPaint32;
 		_gfxText32 = new GfxText32(_gamestate->_segMan, _gfxCache, _gfxScreen);
 		_gfxControls32 = new GfxControls32(_gamestate->_segMan, _gfxCache, _gfxText32);
 		_robotDecoder = new RobotDecoder(getPlatform() == Common::kPlatformMacintosh);
-		_gfxFrameout = new GfxFrameout(_gamestate->_segMan, _resMan, _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette, _gfxPaint32);
+		_gfxFrameout = new GfxFrameout(_gamestate->_segMan, _resMan, _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette32, _gfxPaint32);
 	} else {
 #endif
 		// SCI0-SCI1.1 graphic objects creation
@@ -652,10 +667,10 @@ void SciEngine::initGraphics() {
 		_gfxCoordAdjuster = new GfxCoordAdjuster16(_gfxPorts);
 		_gfxCursor->init(_gfxCoordAdjuster, _eventMan);
 		_gfxCompare = new GfxCompare(_gamestate->_segMan, _gfxCache, _gfxScreen, _gfxCoordAdjuster);
-		_gfxTransitions = new GfxTransitions(_gfxScreen, _gfxPalette);
-		_gfxPaint16 = new GfxPaint16(_resMan, _gamestate->_segMan, _gfxCache, _gfxPorts, _gfxCoordAdjuster, _gfxScreen, _gfxPalette, _gfxTransitions, _audio);
+		_gfxTransitions = new GfxTransitions(_gfxScreen, _gfxPalette16);
+		_gfxPaint16 = new GfxPaint16(_resMan, _gamestate->_segMan, _gfxCache, _gfxPorts, _gfxCoordAdjuster, _gfxScreen, _gfxPalette16, _gfxTransitions, _audio);
 		_gfxPaint = _gfxPaint16;
-		_gfxAnimate = new GfxAnimate(_gamestate, _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen, _gfxPalette, _gfxCursor, _gfxTransitions);
+		_gfxAnimate = new GfxAnimate(_gamestate, _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen, _gfxPalette16, _gfxCursor, _gfxTransitions);
 		_gfxText16 = new GfxText16(_gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen);
 		_gfxControls16 = new GfxControls16(_gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen);
 		_gfxMenu = new GfxMenu(_eventMan, _gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen, _gfxCursor);
@@ -670,7 +685,7 @@ void SciEngine::initGraphics() {
 #endif
 
 	// Set default (EGA, amiga or resource 999) palette
-	_gfxPalette->setDefault();
+	_gfxPalette16->setDefault();
 }
 
 void SciEngine::initStackBaseWithSelector(Selector selector) {
@@ -1022,4 +1037,9 @@ void SciEngine::loadMacExecutable() {
 	}
 }
 
+// Note that SCI engine also has a corresponding TimeMgr::SetTickCount method
+// which is used by TimeMgr::SaveRestore when loading a save game.
+uint32 SciEngine::getTickCount() {
+	return (uint32) ((g_system->getMillis() * 60) / 1000);
+}
 } // End of namespace Sci
diff --git a/engines/sci/sci.h b/engines/sci/sci.h
index 15034d5..c5528e4 100644
--- a/engines/sci/sci.h
+++ b/engines/sci/sci.h
@@ -79,6 +79,7 @@ class GfxTransitions;
 #ifdef ENABLE_SCI32
 class RobotDecoder;
 class GfxFrameout;
+class GfxPalette32;
 #endif
 
 // our engine debug levels
@@ -235,6 +236,7 @@ public:
 	bool canLoadGameStateCurrently();
 	bool canSaveGameStateCurrently();
 	void syncSoundSettings();
+	uint32 getTickCount();
 
 	/**
 	 * Syncs the audio options of the ScummVM launcher (speech, subtitles or
@@ -343,7 +345,8 @@ public:
 	GfxCoordAdjuster *_gfxCoordAdjuster;
 	GfxCursor *_gfxCursor;
 	GfxMenu *_gfxMenu; // Menu for 16-bit gfx
-	GfxPalette *_gfxPalette;
+	GfxPalette *_gfxPalette16;
+	GfxPalette32 *_gfxPalette32; // Palette for 32-bit gfx
 	GfxPaint *_gfxPaint;
 	GfxPaint16 *_gfxPaint16; // Painting in 16-bit gfx
 	GfxPaint32 *_gfxPaint32; // Painting in 32-bit gfx


Commit: 70d89b3e394e46bc96a7fde681cd84f36763ee52
    https://github.com/scummvm/scummvm/commit/70d89b3e394e46bc96a7fde681cd84f36763ee52
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-01-07T16:35:09-06:00

Commit Message:
SCI32: Add kSetPalStyleRange stub code

Changed paths:
    engines/sci/engine/kernel.h
    engines/sci/engine/kernel_tables.h
    engines/sci/engine/kgraphics32.cpp



diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index 5d929a3..56009e4 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -450,6 +450,7 @@ reg_t kAddPlane(EngineState *s, int argc, reg_t *argv);
 reg_t kDeletePlane(EngineState *s, int argc, reg_t *argv);
 reg_t kUpdatePlane(EngineState *s, int argc, reg_t *argv);
 reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv);
+reg_t kSetPalStyleRange(EngineState *s, int argc, reg_t *argv);
 reg_t kGetHighPlanePri(EngineState *s, int argc, reg_t *argv);
 reg_t kFrameOut(EngineState *s, int argc, reg_t *argv);
 
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index 49dfa17..98ea067 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -694,6 +694,8 @@ static SciKernelMapEntry s_kernelMap[] = {
 	// MovePlaneItems - used by SQ6 to scroll through the inventory via the up/down buttons
 	// SetPalStyleRange - 2 integer parameters, start and end. All styles from start-end
 	//   (inclusive) are set to 0
+	{ MAP_CALL(SetPalStyleRange),  SIG_EVERYWHERE,            "ii",                   NULL,            NULL },
+
 	// MorphOn - used by SQ6, script 900, the datacorder reprogramming puzzle (from room 270)
 
 	// SCI3 Kernel Functions
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index 5de440c..2ae6b1f 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -131,6 +131,22 @@ reg_t kFrameOut(EngineState *s, int argc, reg_t *argv) {
 	return NULL_REG;
 }
 
+reg_t kSetPalStyleRange(EngineState *s, int argc, reg_t *argv) {
+/* TODO: Transcribed from SCI engine disassembly.
+	 uint16 start = argv[0].toUint16();
+	 uint16 end = argv[1].toUint16();
+	 if (end <= start) {
+		uint16 index = start;
+		while (index <= end) {
+			g_PalStyleRanges[index] = 0;
+		}
+	 }
+*/
+
+	kStub(s, argc, argv);
+	return NULL_REG;
+}
+
 reg_t kObjectIntersect(EngineState *s, int argc, reg_t *argv) {
 	Common::Rect objRect1 = g_sci->_gfxCompare->getNSRect(argv[0]);
 	Common::Rect objRect2 = g_sci->_gfxCompare->getNSRect(argv[1]);


Commit: 8a1d48fc0373730d9239786aea070b363b346729
    https://github.com/scummvm/scummvm/commit/8a1d48fc0373730d9239786aea070b363b346729
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-01-07T16:35:09-06:00

Commit Message:
SCI32: Add kFrameOut stub code

Changed paths:
    engines/sci/engine/kgraphics32.cpp
    engines/sci/graphics/frameout.cpp



diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index 2ae6b1f..a765fe8 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -127,6 +127,26 @@ reg_t kGetHighPlanePri(EngineState *s, int argc, reg_t *argv) {
 }
 
 reg_t kFrameOut(EngineState *s, int argc, reg_t *argv) {
+/* TODO: Transcribed from SCI engine disassembly.
+	GraphicsMgr &graphicsMgr = g_sci->_graphicsMgr;
+	if (graphicsMgr.palMorphNeeded) {
+		graphicsMgr.PalMorphFrameOut(&g_PalStyleRanges, false);
+	}
+	else {
+		// TODO: Not sure if this is a pointer or not yet.
+		if (g_ScrollState != nullptr) {
+			kFrameOutDoScroll();
+		}
+
+		bool showBits = true;
+		if (argc == 1) {
+			showBits = (bool) argv[0].toUint16();
+		}
+
+		rect SOL_Rect = { .left = 0, .top = 0, .right = UINT32_MAX, .bottom = UINT32_MAX };
+		graphicsMgr.FrameOut(showBits, &rect);
+	}
+*/
 	g_sci->_gfxFrameout->kernelFrameout();
 	return NULL_REG;
 }
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index 7396115..9512ec2 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -651,6 +651,97 @@ void GfxFrameout::drawPicture(FrameoutEntry *itemEntry, int16 planeOffsetX, int1
 	//	warning("picture cel %d %d", itemEntry->celNo, itemEntry->priority);
 }
 
+/* TODO: This is the proper implementation of GraphicsMgr::FrameOut transcribed from SQ6 SCI engine disassembly.
+static DrawList* g_drawLists[100];
+static RectList* g_rectLists[100];
+void GfxFrameout::FrameOut(bool shouldShowBits, SOL_Rect *rect) {
+	if (robot) {
+		robot.doRobot();
+	}
+
+	auto planeCount = screen.planeList.planeCount;
+	if (planeCount > 0) {
+		for (int planeIndex = 0; planeIndex < planeCount; ++planeIndex) {
+			Plane plane = *screen.planeList[planeIndex];
+
+			DrawList* drawList = new DrawList();
+			g_drawLists[planeIndex] = drawList;
+			RectList* rectList = new RectList();
+			g_rectLists[planeIndex] = rectList;
+		}
+	}
+ 
+	if (g_Remap_numActiveRemaps > 0 && remapNeeded) {
+		screen.RemapMarkRedraw();
+	}
+ 
+	CalcLists(&g_drawLists, &g_rectLists, rect);
+
+	// SCI engine stores reference *after* CalcLists
+	planeCount = screen.planeList.planeCount;
+	if (planeCount > 0) {
+		for (int drawListIndex = 0; drawListIndex < planeCount; ++i) {
+			DrawList* drawList = g_drawLists[drawListIndex];
+			drawList->Sort();
+		}
+
+		for (int drawListIndex = 0; drawListIndex < planeCount; ++i) {
+			DrawList* drawList = g_drawLists[drawListIndex];
+			if (drawList == nullptr || drawList->count == 0) {
+				continue;
+			}
+
+			for (int screenItemIndex = 0, screenItemCount = drawList->count; screenItemIndex < screenItemCount; ++screenItemIndex) {
+				ScreenItem* screenItem = drawList->items[screenItemIndex];
+				screenItem->GetCelObj()->SubmitPalette();
+			}
+		}
+	}
+
+	// UpdateForFrame is where all palette mutations occur (cycles, varies, etc.)
+	bool remapNeeded = GPalette().UpdateForFrame();
+	if (planeCount > 0) {
+		frameNowVisible = false;
+
+		for (int planeIndex = 0; planeIndex < planeCount; ++planeIndex) {
+			Plane* plane = screen.planeList[planeIndex];
+
+			DrawEraseList(g_rectLists[planeIndex], plane);
+			DrawScreenItemsList(g_drawLists[planeIndex]);
+		}
+	}
+
+	if (robot) {
+		robot.FrameAlmostVisible();
+	}
+
+	GPalette().UpdateHardware();
+
+	if (shouldShowBits) {
+		ShowBits();
+	}
+
+	frameNowVisible = true;
+
+	if (robot) {
+		robot.FrameNowVisible();
+	}
+
+	if (planeCount > 0) {
+		for (int planeIndex = 0; planeIndex < planeCount; ++planeIndex) {
+			if (g_rectLists[planeIndex] != nullptr) {
+				delete g_rectLists[planeIndex];
+			}
+			if (g_drawLists[planeIndex] != nullptr) {
+				delete g_drawLists[planeIndex];
+			}
+		}
+	}
+}
+void GfxFrameout::CalcLists(DrawList **drawLists, RectList **rectLists, SOL_Rect *rect) {
+	screen.CalcLists(&visibleScreen, drawLists, rectLists, rect);
+}
+*/
 void GfxFrameout::kernelFrameout() {
 	if (g_sci->_robotDecoder->isVideoLoaded()) {
 		showVideo();


Commit: 275db1f7f24e373bd41b6b689303fee9f6f771be
    https://github.com/scummvm/scummvm/commit/275db1f7f24e373bd41b6b689303fee9f6f771be
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-01-07T16:35:09-06:00

Commit Message:
SCI: Remove unused member property _palCycleToColor

Changed paths:
    engines/sci/engine/state.cpp
    engines/sci/engine/state.h



diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp
index 417d98e..d53e6b4 100644
--- a/engines/sci/engine/state.cpp
+++ b/engines/sci/engine/state.cpp
@@ -129,8 +129,6 @@ void EngineState::reset(bool isRestoring) {
 
 	_vmdPalStart = 0;
 	_vmdPalEnd = 256;
-
-	_palCycleToColor = 255;
 }
 
 void EngineState::speedThrottler(uint32 neededSleep) {
diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h
index e7499e6..eb9f3bb 100644
--- a/engines/sci/engine/state.h
+++ b/engines/sci/engine/state.h
@@ -203,8 +203,6 @@ public:
 	uint16 _vmdPalStart, _vmdPalEnd;
 	bool _syncedAudioOptions;
 
-	uint16 _palCycleToColor;
-
 	/**
 	 * Resets the engine state.
 	 */


Commit: 7379e531c75294577b4859fceb73ae01559dae0f
    https://github.com/scummvm/scummvm/commit/7379e531c75294577b4859fceb73ae01559dae0f
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-01-08T10:58:03+02:00

Commit Message:
Merge pull request #644 from csnover/sci32-kPalCycle

SCI32: palette management (full kPalCycle, partial kSetPalStyleRange and kPalFade)

Changed paths:
  A engines/sci/graphics/palette32.cpp
  A engines/sci/graphics/palette32.h
    engines/sci/console.cpp
    engines/sci/engine/kernel.h
    engines/sci/engine/kernel_tables.h
    engines/sci/engine/kgraphics.cpp
    engines/sci/engine/kgraphics32.cpp
    engines/sci/engine/kpathing.cpp
    engines/sci/engine/kvideo.cpp
    engines/sci/engine/savegame.cpp
    engines/sci/engine/state.cpp
    engines/sci/engine/state.h
    engines/sci/graphics/frameout.cpp
    engines/sci/graphics/frameout.h
    engines/sci/graphics/maciconbar.cpp
    engines/sci/graphics/palette.cpp
    engines/sci/graphics/palette.h
    engines/sci/module.mk
    engines/sci/sci.cpp
    engines/sci/sci.h









More information about the Scummvm-git-logs mailing list