[Scummvm-cvs-logs] scummvm master -> 08821cf4e3cec6d8b65b4cb1fa49f466430eb330

csnover csnover at users.noreply.github.com
Mon Jul 11 17:41:39 CEST 2016


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

Summary:
1714cf8aa5 SCI32: Minor Audio32 cleanup
ec73fa1e4a SCI32: Fix audio deadlocks
7f53a26d9e SCI32: Split kPalCycle into subop functions
4cfc387602 SCI32: Split GfxPalette and GfxPalette32 + HunkPalette
6a13adb638 SCI32: Fix sign comparison warning
8fb55564a6 SCI32: Fix bad output caused by missing palette copies
bc362e5b7c SCI32: Minor cleanup of GfxPalette32
60c3663142 SCI32: Fix incorrect logic of cycler overflow
e4588a7134 SCI32: Silence non-monitored channels while monitoring is active
f171db965c SCI32: Guard against no split count
08821cf4e3 SCI32: Give planes a default type


Commit: 1714cf8aa562e0eb25e957e9bf7636ceb4785216
    https://github.com/scummvm/scummvm/commit/1714cf8aa562e0eb25e957e9bf7636ceb4785216
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-07-11T10:39:50-05:00

Commit Message:
SCI32: Minor Audio32 cleanup

Changed paths:
    engines/sci/sound/audio32.cpp



diff --git a/engines/sci/sound/audio32.cpp b/engines/sci/sound/audio32.cpp
index 4689d13..98c2a51 100644
--- a/engines/sci/sound/audio32.cpp
+++ b/engines/sci/sound/audio32.cpp
@@ -124,10 +124,10 @@ Audio32::Audio32(ResourceManager *resMan) :
 
 	_attenuatedMixing(true),
 
-	 _monitoredChannelIndex(-1),
-	 _monitoredBuffer(nullptr),
-	 _monitoredBufferSize(0),
-	 _numMonitoredSamples(0) {
+	_monitoredChannelIndex(-1),
+	_monitoredBuffer(nullptr),
+	_monitoredBufferSize(0),
+	_numMonitoredSamples(0) {
 
 	if (getSciVersion() < SCI_VERSION_3) {
 		_channels.resize(5);
@@ -146,15 +146,10 @@ Audio32::Audio32(ResourceManager *resMan) :
 		default:
 			break;
 		}
-	} else if (getSciVersion() == SCI_VERSION_2_1_EARLY) {
-		switch (g_sci->getGameId()) {
-		// 1.51 uses the non-standard attenuation, but 2.00b
+	} else if (getSciVersion() == SCI_VERSION_2_1_EARLY && g_sci->getGameId() == GID_KQ7) {
+		// KQ7 1.51 uses the non-standard attenuation, but 2.00b
 		// does not, which is strange.
-		case GID_KQ7:
-			_useModifiedAttenuation = true;
-		default:
-			break;
-		}
+		_useModifiedAttenuation = true;
 	}
 
 	_mixer->playStream(Audio::Mixer::kSFXSoundType, &_handle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);


Commit: ec73fa1e4af4acc9806e948993f702dfc363a094
    https://github.com/scummvm/scummvm/commit/ec73fa1e4af4acc9806e948993f702dfc363a094
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-07-11T10:39:50-05:00

Commit Message:
SCI32: Fix audio deadlocks

Several functions in Audio32 would call into the mixer to pause
or resume the audio handle, which would cause a deadlock if the
mixer's mixCallback timer fired while one of these functions was
running on the main thread.

To address this, calls to mixer to pause/unpause the digital audio
handle have been removed. Since this was just an optimisation to
prevent unnecessary calls to fill the audio buffer, the only
problem now is that a tiny amount of CPU is wasted on unnecessary
callbacks to read from the empty SCI mixer.

Changed paths:
    engines/sci/sound/audio32.cpp



diff --git a/engines/sci/sound/audio32.cpp b/engines/sci/sound/audio32.cpp
index 98c2a51..e7d0246 100644
--- a/engines/sci/sound/audio32.cpp
+++ b/engines/sci/sound/audio32.cpp
@@ -153,7 +153,6 @@ Audio32::Audio32(ResourceManager *resMan) :
 	}
 
 	_mixer->playStream(Audio::Mixer::kSFXSoundType, &_handle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-	_mixer->pauseHandle(_handle, true);
 }
 
 Audio32::~Audio32() {
@@ -235,16 +234,16 @@ int Audio32::writeAudioInternal(Audio::RewindableAudioStream *const sourceStream
 int Audio32::readBuffer(Audio::st_sample_t *buffer, const int numSamples) {
 	Common::StackLock lock(_mutex);
 
+	if (_pausedAtTick != 0 || _numActiveChannels == 0) {
+		return 0;
+	}
+
 	// ResourceManager is not thread-safe so we need to
 	// avoid calling into it from the audio thread, but at
 	// the same time we need to be able to clear out any
 	// finished channels on a regular basis
 	_inAudioThread = true;
 
-	// The system mixer should not try to get data when
-	// Audio32 is paused
-	assert(_pausedAtTick == 0 && _numActiveChannels > 0);
-
 	freeUnusedChannels();
 
 	// The caller of `readBuffer` is a rate converter,
@@ -647,7 +646,6 @@ uint16 Audio32::play(int16 channelIndex, const ResourceId resourceId, const bool
 
 	if (_numActiveChannels == 1) {
 		_startedAtTick = now;
-		_mixer->pauseHandle(_handle, false);
 	}
 
 	return channel.duration;
@@ -678,7 +676,6 @@ bool Audio32::resume(const int16 channelIndex) {
 
 		_startedAtTick += now - _pausedAtTick;
 		_pausedAtTick = 0;
-		_mixer->pauseHandle(_handle, false);
 		return true;
 	} else if (channelIndex == kRobotChannel) {
 		for (int i = 0; i < _numActiveChannels; ++i) {
@@ -715,7 +712,6 @@ bool Audio32::pause(const int16 channelIndex) {
 	if (channelIndex == kAllChannels) {
 		if (_pausedAtTick == 0) {
 			_pausedAtTick = now;
-			_mixer->pauseHandle(_handle, true);
 			didPause = true;
 		}
 	} else if (channelIndex == kRobotChannel) {
@@ -768,9 +764,6 @@ int16 Audio32::stop(const int16 channelIndex) {
 	// NOTE: SSCI stops the DSP interrupt and frees the
 	// global decompression buffer here if there are no
 	// more active channels
-	if (_numActiveChannels == 0) {
-		_mixer->pauseHandle(_handle, true);
-	}
 
 	return oldNumChannels;
 }
@@ -886,17 +879,15 @@ reg_t Audio32::kernelPlay(const bool autoPlay, const int argc, const reg_t *cons
 #pragma mark Effects
 
 int16 Audio32::getVolume(const int16 channelIndex) const {
-	Common::StackLock lock(_mutex);
 	if (channelIndex < 0 || channelIndex >= _numActiveChannels) {
 		return _mixer->getChannelVolume(_handle) * kMaxVolume / Audio::Mixer::kMaxChannelVolume;
 	}
 
+	Common::StackLock lock(_mutex);
 	return getChannel(channelIndex).volume;
 }
 
 void Audio32::setVolume(const int16 channelIndex, int16 volume) {
-	Common::StackLock lock(_mutex);
-
 	volume = MIN((int16)kMaxVolume, volume);
 	if (channelIndex == kAllChannels) {
 		ConfMan.setInt("sfx_volume", volume * Audio::Mixer::kMaxChannelVolume / kMaxVolume);
@@ -904,6 +895,7 @@ void Audio32::setVolume(const int16 channelIndex, int16 volume) {
 		_mixer->setChannelVolume(_handle, volume * Audio::Mixer::kMaxChannelVolume / kMaxVolume);
 		g_engine->syncSoundSettings();
 	} else if (channelIndex != kNoExistingChannel) {
+		Common::StackLock lock(_mutex);
 		getChannel(channelIndex).volume = volume;
 	}
 }


Commit: 7f53a26d9e8b55a865efea2f912189b01ca56258
    https://github.com/scummvm/scummvm/commit/7f53a26d9e8b55a865efea2f912189b01ca56258
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-07-11T10:39:50-05:00

Commit Message:
SCI32: Split kPalCycle into subop functions

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 845e63a..143903b 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -549,6 +549,14 @@ reg_t kSetScroll(EngineState *s, int argc, reg_t *argv);
 
 reg_t kPalCycle(EngineState *s, int argc, reg_t *argv);
 reg_t kPaletteSetFade(EngineState *s, int argc, reg_t *argv);
+
+reg_t kPalCycle(EngineState *s, int argc, reg_t *argv);
+reg_t kPalCycleSetCycle(EngineState *s, int argc, reg_t *argv);
+reg_t kPalCycleDoCycle(EngineState *s, int argc, reg_t *argv);
+reg_t kPalCyclePause(EngineState *s, int argc, reg_t *argv);
+reg_t kPalCycleOn(EngineState *s, int argc, reg_t *argv);
+reg_t kPalCycleOff(EngineState *s, int argc, reg_t *argv);
+
 reg_t kPalVarySetVary(EngineState *s, int argc, reg_t *argv);
 reg_t kPalVarySetPercent(EngineState *s, int argc, reg_t *argv);
 reg_t kPalVaryGetPercent(EngineState *s, int argc, reg_t *argv);
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index 31a9938..0e1262b 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -335,6 +335,16 @@ static const SciKernelMapSubEntry kFileIO_subops[] = {
 #ifdef ENABLE_SCI32
 
 //    version,         subId, function-mapping,                    signature,              workarounds
+static const SciKernelMapSubEntry kPalCycle_subops[] = {
+	{ SIG_SCI32,           0, MAP_CALL(PalCycleSetCycle),          "iii(i)",               NULL },
+	{ SIG_SCI32,           1, MAP_CALL(PalCycleDoCycle),           "i(i)",                 NULL },
+	{ SIG_SCI32,           2, MAP_CALL(PalCyclePause),             "(i)",                  NULL },
+	{ SIG_SCI32,           3, MAP_CALL(PalCycleOn),                "(i)",                  NULL },
+	{ SIG_SCI32,           4, MAP_CALL(PalCycleOff),               "(i)",                  NULL },
+	SCI_SUBOPENTRY_TERMINATOR
+};
+
+//    version,         subId, function-mapping,                    signature,              workarounds
 static const SciKernelMapSubEntry kSave_subops[] = {
 	{ SIG_SCI32,           0, MAP_CALL(SaveGame),                  "[r0]i[r0](r0)",        NULL },
 	{ SIG_SCI32,           1, MAP_CALL(RestoreGame),               "[r0]i[r0]",            NULL },
@@ -762,7 +772,7 @@ static SciKernelMapEntry s_kernelMap[] = {
 	{ MAP_CALL(MakeSaveCatName),   SIG_EVERYWHERE,           "rr",                    NULL,            NULL },
 	{ MAP_CALL(MakeSaveFileName),  SIG_EVERYWHERE,           "rri",                   NULL,            NULL },
 	{ MAP_CALL(SetScroll),         SIG_EVERYWHERE,           "oiiiii(i)",             NULL,            NULL },
-	{ MAP_CALL(PalCycle),          SIG_EVERYWHERE,           "i(.*)",                 NULL,            NULL },
+	{ MAP_CALL(PalCycle),          SIG_EVERYWHERE,           "(.*)",                  kPalCycle_subops, NULL },
 
 	// SCI2 Empty functions
 
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index 019a069..f0c08d1 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -862,67 +862,57 @@ reg_t kPalVaryMergeStart(EngineState *s, int argc, reg_t *argv) {
 	return make_reg(0, g_sci->_gfxPalette32->getVaryPercent());
 }
 
-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)
+	if (!s)
+		return make_reg(0, getSciVersion());
+	error("not supposed to call this");
+}
 
-	switch (argv[0].toUint16()) {
-	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 kDoCycle: {
-		uint16 fromColor = argv[1].toUint16();
-		int16 speed = (argc == 2) ? 1 : argv[2].toSint16();
-		g_sci->_gfxPalette32->doCycle(fromColor, speed);
-		}
-		break;
-	case kCyclePause: {
-		if (argc == 1) {
-			g_sci->_gfxPalette32->cycleAllPause();
-		} else {
-			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);
-		}
-		break;
-		}
-	default:
-		// 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;
+reg_t kPalCycleSetCycle(EngineState *s, int argc, reg_t *argv) {
+	const uint16 fromColor = argv[0].toUint16();
+	const uint16 toColor = argv[1].toUint16();
+	const int16 direction = argv[2].toSint16();
+	const uint16 delay = argc > 3 ? argv[3].toUint16() : 0;
+
+	g_sci->_gfxPalette32->setCycle(fromColor, toColor, direction, delay);
+	return s->r_acc;
+}
+
+reg_t kPalCycleDoCycle(EngineState *s, int argc, reg_t *argv) {
+	const uint16 fromColor = argv[0].toUint16();
+	const int16 speed = argc > 1 ? argv[1].toSint16() : 1;
+
+	g_sci->_gfxPalette32->doCycle(fromColor, speed);
+	return s->r_acc;
+}
+
+reg_t kPalCyclePause(EngineState *s, int argc, reg_t *argv) {
+	if (argc == 0) {
+		g_sci->_gfxPalette32->cycleAllPause();
+	} else {
+		const uint16 fromColor = argv[0].toUint16();
+		g_sci->_gfxPalette32->cyclePause(fromColor);
 	}
+	return s->r_acc;
+}
 
+reg_t kPalCycleOn(EngineState *s, int argc, reg_t *argv) {
+	if (argc == 0) {
+		g_sci->_gfxPalette32->cycleAllOn();
+	} else {
+		const uint16 fromColor = argv[0].toUint16();
+		g_sci->_gfxPalette32->cycleOn(fromColor);
+	}
+	return s->r_acc;
+}
+
+reg_t kPalCycleOff(EngineState *s, int argc, reg_t *argv) {
+	if (argc == 0) {
+		g_sci->_gfxPalette32->cycleAllOff();
+	} else {
+		const uint16 fromColor = argv[0].toUint16();
+		g_sci->_gfxPalette32->cycleOff(fromColor);
+	}
 	return s->r_acc;
 }
 


Commit: 4cfc3876026f15aa394dfa45809c4a340eef60f0
    https://github.com/scummvm/scummvm/commit/4cfc3876026f15aa394dfa45809c4a340eef60f0
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-07-11T10:39:50-05:00

Commit Message:
SCI32: Split GfxPalette and GfxPalette32 + HunkPalette

Changed paths:
    engines/sci/console.cpp
    engines/sci/engine/kernel.h
    engines/sci/engine/kernel_tables.h
    engines/sci/engine/kgraphics32.cpp
    engines/sci/engine/savegame.cpp
    engines/sci/graphics/celobj32.cpp
    engines/sci/graphics/palette.h
    engines/sci/graphics/palette32.cpp
    engines/sci/graphics/palette32.h
    engines/sci/sci.cpp



diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index 2c74fe4..6898745 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -497,8 +497,10 @@ bool Console::cmdGetVersion(int argc, const char **argv) {
 	if (getSciVersion() <= SCI_VERSION_1_1) {
 		debugPrintf("kAnimate fastCast enabled: %s\n", g_sci->_gfxAnimate->isFastCastEnabled() ? "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");
+	if (getSciVersion() < SCI_VERSION_2) {
+		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");
@@ -1620,7 +1622,7 @@ bool Console::cmdParserNodes(int argc, const char **argv) {
 
 bool Console::cmdSetPalette(int argc, const char **argv) {
 	if (argc < 2) {
-		debugPrintf("Sets a palette resource\n");
+		debugPrintf("Sets a palette resource (SCI16)\n");
 		debugPrintf("Usage: %s <resourceId>\n", argv[0]);
 		debugPrintf("where <resourceId> is the number of the palette resource to set\n");
 		return true;
@@ -1628,6 +1630,13 @@ bool Console::cmdSetPalette(int argc, const char **argv) {
 
 	uint16 resourceId = atoi(argv[1]);
 
+#ifdef ENABLE_SCI32
+	if (getSciVersion() >= SCI_VERSION_2) {
+		debugPrintf("This SCI version does not support this command\n");
+		return true;
+	}
+#endif
+
 	_engine->_gfxPalette16->kernelSetFromResource(resourceId, true);
 	return true;
 }
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index 143903b..5ff4f93 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -547,7 +547,8 @@ reg_t kMakeSaveCatName(EngineState *s, int argc, reg_t *argv);
 reg_t kMakeSaveFileName(EngineState *s, int argc, reg_t *argv);
 reg_t kSetScroll(EngineState *s, int argc, reg_t *argv);
 
-reg_t kPalCycle(EngineState *s, int argc, reg_t *argv);
+reg_t kPaletteSetFromResource32(EngineState *s, int argc, reg_t *argv);
+reg_t kPaletteFindColor32(EngineState *s, int argc, reg_t *argv);
 reg_t kPaletteSetFade(EngineState *s, int argc, reg_t *argv);
 
 reg_t kPalCycle(EngineState *s, int argc, reg_t *argv);
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index 0e1262b..8a1176e 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -291,12 +291,13 @@ static const SciKernelMapSubEntry kPalVary_subops[] = {
 
 //    version,         subId, function-mapping,                    signature,              workarounds
 static const SciKernelMapSubEntry kPalette_subops[] = {
-	{ SIG_SCIALL,         1, MAP_CALL(PaletteSetFromResource),    "i(i)",                 NULL },
+	{ SIG_SCI16,          1, MAP_CALL(PaletteSetFromResource),    "i(i)",                 NULL },
 	{ SIG_SCI16,          2, MAP_CALL(PaletteSetFlag),            "iii",                  NULL },
 	{ SIG_SCI16,          3, MAP_CALL(PaletteUnsetFlag),          "iii",                  kPaletteUnsetFlag_workarounds },
 #ifdef ENABLE_SCI32
+	{ SIG_SCI32,          1, MAP_CALL(PaletteSetFromResource32),  "i(i)",                 NULL },
 	{ SIG_SCI32,          2, MAP_CALL(PaletteSetFade),            "iii",                  NULL },
-	{ SIG_SCI32,          3, MAP_CALL(PaletteFindColor),          "iii",                  NULL },
+	{ SIG_SCI32,          3, MAP_CALL(PaletteFindColor32),        "iii",                  NULL },
 #endif
 	{ SIG_SCI16,          4, MAP_CALL(PaletteSetIntensity),       "iii(i)",               NULL },
 	{ SIG_SCI16,          5, MAP_CALL(PaletteFindColor),          "iii",                  NULL },
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index f0c08d1..9cfe532 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -790,6 +790,19 @@ reg_t kMorphOn(EngineState *s, int argc, reg_t *argv) {
 	return s->r_acc;
 }
 
+reg_t kPaletteSetFromResource32(EngineState *s, int argc, reg_t *argv) {
+	const GuiResourceId paletteId = argv[0].toUint16();
+	g_sci->_gfxPalette32->loadPalette(paletteId);
+	return s->r_acc;
+}
+
+reg_t kPaletteFindColor32(EngineState *s, int argc, reg_t *argv) {
+	const uint8 r = argv[0].toUint16();
+	const uint8 g = argv[1].toUint16();
+	const uint8 b = argv[2].toUint16();
+	return make_reg(0, g_sci->_gfxPalette32->matchColor(r, g, b));
+}
+
 reg_t kPaletteSetFade(EngineState *s, int argc, reg_t *argv) {
 	uint16 fromColor = argv[0].toUint16();
 	uint16 toColor = argv[1].toUint16();
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index 0972aec..31fb848 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -398,8 +398,13 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) {
 	_segMan->saveLoadWithSerializer(s);
 
 	g_sci->_soundCmd->syncPlayList(s);
-	// NOTE: This will be GfxPalette32 for SCI32 engine games
-	g_sci->_gfxPalette16->saveLoadWithSerializer(s);
+
+#ifdef ENABLE_SCI32
+	if (getSciVersion() >= SCI_VERSION_2) {
+		g_sci->_gfxPalette32->saveLoadWithSerializer(s);
+	} else
+#endif
+		g_sci->_gfxPalette16->saveLoadWithSerializer(s);
 }
 
 void Vocabulary::saveLoadWithSerializer(Common::Serializer &s) {
@@ -767,7 +772,7 @@ void GfxPalette32::saveLoadWithSerializer(Common::Serializer &s) {
 	s.syncAsSint16LE(_varyFromColor);
 	s.syncAsSint16LE(_varyToColor);
 	s.syncAsUint16LE(_varyNumTimesPaused);
-	s.syncAsByte(_versionUpdated);
+	s.syncAsByte(_needsUpdate);
 	s.syncAsSint32LE(_varyTime);
 	s.syncAsUint32LE(_varyLastTick);
 
diff --git a/engines/sci/graphics/celobj32.cpp b/engines/sci/graphics/celobj32.cpp
index da41879..48de054 100644
--- a/engines/sci/graphics/celobj32.cpp
+++ b/engines/sci/graphics/celobj32.cpp
@@ -570,12 +570,7 @@ uint8 CelObj::readPixel(uint16 x, const uint16 y, bool mirrorX) const {
 
 void CelObj::submitPalette() const {
 	if (_hunkPaletteOffset) {
-		Palette palette;
-
-		byte *res = getResPointer();
-		// NOTE: In SCI engine this uses HunkPalette::Init.
-		// TODO: Use a better size value
-		g_sci->_gfxPalette32->createFromData(res + _hunkPaletteOffset, 999999, &palette);
+		HunkPalette palette(getResPointer() + _hunkPaletteOffset);
 		g_sci->_gfxPalette32->submit(palette);
 	}
 }
diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h
index 7335dc5..2178de8 100644
--- a/engines/sci/graphics/palette.h
+++ b/engines/sci/graphics/palette.h
@@ -51,7 +51,7 @@ public:
 	bool setAmiga();
 	void modifyAmigaPalette(byte *data);
 	void setEGA();
-	virtual void set(Palette *sciPal, bool force, bool forceRealMerge = false);
+	void set(Palette *sciPal, bool force, bool forceRealMerge = false);
 	bool insert(Palette *newPalette, Palette *destPalette);
 	bool merge(Palette *pFrom, bool force, bool forceRealMerge);
 	uint16 matchColor(byte r, byte g, byte b);
@@ -63,11 +63,11 @@ public:
 
 	void drewPicture(GuiResourceId pictureId);
 
-	virtual bool kernelSetFromResource(GuiResourceId resourceId, bool force);
+	bool kernelSetFromResource(GuiResourceId resourceId, bool force);
 	void kernelSetFlag(uint16 fromColor, uint16 toColor, uint16 flag);
 	void kernelUnsetFlag(uint16 fromColor, uint16 toColor, uint16 flag);
 	void kernelSetIntensity(uint16 fromColor, uint16 toColor, uint16 intensity, bool setPalette);
-	virtual int16 kernelFindColor(uint16 r, uint16 g, uint16 b);
+	int16 kernelFindColor(uint16 r, uint16 g, uint16 b);
 	bool kernelAnimate(byte fromColor, byte toColor, int speed);
 	void kernelAnimateSet();
 	reg_t kernelSave();
@@ -81,7 +81,7 @@ public:
 	int16 kernelPalVaryGetCurrentStep();
 	int16 kernelPalVaryChangeTarget(GuiResourceId resourceId);
 	void kernelPalVaryChangeTicks(uint16 ticks);
-	virtual void kernelPalVaryPause(bool pause);
+	void kernelPalVaryPause(bool pause);
 	void kernelPalVaryDeinit();
 	void palVaryUpdate();
 	void palVaryPrepareForTransition();
@@ -89,7 +89,7 @@ public:
 
 	Palette _sysPalette;
 
-	virtual void saveLoadWithSerializer(Common::Serializer &s);
+	void saveLoadWithSerializer(Common::Serializer &s);
 	void palVarySaveLoadPalette(Common::Serializer &s, Palette *palette);
 
 	byte findMacIconBarColor(byte r, byte g, byte b);
diff --git a/engines/sci/graphics/palette32.cpp b/engines/sci/graphics/palette32.cpp
index 0840e82..3a321bf 100644
--- a/engines/sci/graphics/palette32.cpp
+++ b/engines/sci/graphics/palette32.cpp
@@ -27,19 +27,109 @@
 #include "sci/sci.h"
 #include "sci/event.h"
 #include "sci/resource.h"
+#include "sci/util.h"
 #include "sci/graphics/palette32.h"
 #include "sci/graphics/remap32.h"
 #include "sci/graphics/screen.h"
 
 namespace Sci {
 
-GfxPalette32::GfxPalette32(ResourceManager *resMan, GfxScreen *screen)
-	: GfxPalette(resMan, screen),
+#pragma mark HunkPalette
+
+HunkPalette::HunkPalette(byte *rawPalette) :
+	_version(0),
+	// NOTE: The header size in palettes is garbage. In at least KQ7 2.00b and
+	// Phant1, the 999.pal sets this value to 0. In most other palettes it is
+	// set to 14, but the *actual* size of the header structure used in SSCI is
+	// 13, which is reflected by `kHunkPaletteHeaderSize`.
+	// _headerSize(rawPalette[0]),
+	_numPalettes(rawPalette[10]),
+	_data(nullptr) {
+	assert(_numPalettes == 0 || _numPalettes == 1);
+	if (_numPalettes) {
+		_data = rawPalette;
+		_version = getEntryHeader().version;
+	}
+}
+
+void HunkPalette::setVersion(const uint32 version) {
+	if (_numPalettes != _data[10]) {
+		error("Invalid HunkPalette");
+	}
+
+	if (_numPalettes) {
+		const EntryHeader header = getEntryHeader();
+		if (header.version != _version) {
+			error("Invalid HunkPalette");
+		}
+
+		WRITE_SCI11ENDIAN_UINT32(getPalPointer() + kEntryVersionOffset, version);
+		_version = version;
+	}
+}
+
+const HunkPalette::EntryHeader HunkPalette::getEntryHeader() const {
+	const byte *const data = getPalPointer();
+
+	EntryHeader header;
+	header.startColor = data[10];
+	header.numColors = READ_SCI11ENDIAN_UINT16(data + 14);
+	header.used = data[16];
+	header.sharedUsed = data[17];
+	header.version = READ_SCI11ENDIAN_UINT32(data + kEntryVersionOffset);
+
+	return header;
+}
+
+const Palette HunkPalette::toPalette() const {
+	Palette outPalette;
+
+	for (int16 i = 0; i < ARRAYSIZE(outPalette.colors); ++i) {
+		outPalette.colors[i].used = false;
+		outPalette.colors[i].r = 0;
+		outPalette.colors[i].g = 0;
+		outPalette.colors[i].b = 0;
+	}
+
+	if (_numPalettes) {
+		const EntryHeader header = getEntryHeader();
+		byte *data = getPalPointer() + kEntryHeaderSize;
+
+		int16 end = header.startColor + header.numColors;
+		assert(end <= 256);
+
+		if (header.sharedUsed) {
+			for (int16 i = header.startColor; i < end; ++i) {
+				outPalette.colors[i].used = header.used;
+				outPalette.colors[i].r = *data++;
+				outPalette.colors[i].g = *data++;
+				outPalette.colors[i].b = *data++;
+			}
+		} else {
+			for (int16 i = header.startColor; i < end; ++i) {
+				outPalette.colors[i].used = *data++;
+				outPalette.colors[i].r = *data++;
+				outPalette.colors[i].g = *data++;
+				outPalette.colors[i].b = *data++;
+			}
+		}
+	}
+
+	return outPalette;
+}
+
+
+#pragma mark -
+#pragma mark GfxPalette32
+
+GfxPalette32::GfxPalette32(ResourceManager *resMan)
+	: _resMan(resMan),
 	// Palette versioning
 	_version(1),
-	_versionUpdated(false),
-	_sourcePalette(_sysPalette),
-	_nextPalette(_sysPalette),
+	_needsUpdate(false),
+	_currentPalette(),
+	_sourcePalette(_currentPalette),
+	_nextPalette(_currentPalette),
 	// Clut
 	_clutTable(nullptr),
 	// Palette varying
@@ -59,13 +149,14 @@ GfxPalette32::GfxPalette32(ResourceManager *resMan, GfxScreen *screen)
 		for (int i = 0, len = ARRAYSIZE(_fadeTable); i < len; ++i) {
 			_fadeTable[i] = 100;
 		}
-		// NOTE: In SCI engine, the palette manager constructor loads
-		// the default palette, but in ScummVM this initialisation
-		// is performed by SciEngine::run; see r49523 for details
+
+		loadPalette(999);
 }
 
 GfxPalette32::~GfxPalette32() {
+#ifdef ENABLE_SCI3_GAMES
 	unloadClut();
+#endif
 	varyOff();
 	cycleAllOff();
 }
@@ -78,79 +169,64 @@ inline void mergePaletteInternal(Palette *const to, const Palette *const from) {
 	}
 }
 
-void GfxPalette32::submit(Palette &palette) {
-	// TODO: The resource manager in SCI32 retains raw data of palettes from
-	// the ResourceManager (ResourceMgr) through SegManager (MemoryMgr), and
-	// the version number for submitted palettes is set in the raw palette
-	// data in memory as an int at an offset
-	// `rawData + *rawData[0x0a] * 2 + 31`. However, ScummVM does not retain
-	// resource data like this, so this versioning code, while accurate to
-	// the original engine, does not do much.
-	// (Hopefully this was an optimisation mechanism in SCI engine and not a
-	// clever thing to keep the same palette submitted many times from
-	// overwriting other palette entries.)
-	if (palette.timestamp == _version) {
+void GfxPalette32::submit(const Palette &palette) {
+	const Palette oldSourcePalette(_sourcePalette);
+	mergePaletteInternal(&_sourcePalette, &palette);
+
+	if (!_needsUpdate && _sourcePalette != oldSourcePalette) {
+		++_version;
+		_needsUpdate = true;
+	}
+}
+
+void GfxPalette32::submit(HunkPalette &hunkPalette) {
+	if (hunkPalette.getVersion() == _version) {
 		return;
 	}
 
-	Palette oldSourcePalette(_sourcePalette);
+	const Palette oldSourcePalette(_sourcePalette);
+	const Palette palette = hunkPalette.toPalette();
 	mergePaletteInternal(&_sourcePalette, &palette);
 
-	if (!_versionUpdated && _sourcePalette != oldSourcePalette) {
+	if (!_needsUpdate && oldSourcePalette != _sourcePalette) {
 		++_version;
-		_versionUpdated = true;
+		_needsUpdate = true;
 	}
 
-	// Technically this information is supposed to be persisted through a
-	// HunkPalette object; right now it would just be lost once the temporary
-	// palette was destroyed.
-	palette.timestamp = _version;
+	hunkPalette.setVersion(_version);
 }
 
-bool GfxPalette32::kernelSetFromResource(GuiResourceId resourceId, bool force) {
-	// TODO: In SCI32, palettes that come from resources come in as
-	// HunkPalette objects, not SOLPalette objects. The HunkPalettes
-	// have some extra persistence stuff associated with them, such that
-	// when they are passed to GfxPalette32::submit, they would get the
-	// version number of GfxPalette32 assigned to them.
-	Palette palette;
+bool GfxPalette32::loadPalette(const GuiResourceId resourceId) {
+	Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false);
 
-	if (createPaletteFromResourceInternal(resourceId, &palette)) {
-		submit(palette);
-		return true;
+	if (!palResource) {
+		return false;
 	}
 
-	return false;
+	HunkPalette palette(palResource->data);
+	submit(palette);
+	return true;
 }
 
-// In SCI32 engine this method is SOLPalette::Match(Rgb24 *)
-// and is called as PaletteMgr.Current().Match(color)
-int16 GfxPalette32::kernelFindColor(uint16 r, uint16 g, uint16 b) {
-	// SQ6 SCI32 engine takes the 16-bit r, g, b arguments from the
-	// VM and puts them into al, ah, dl. For compatibility, make sure
-	// to discard any high bits here too
-	r = r & 0xFF;
-	g = g & 0xFF;
-	b = b & 0xFF;
+int16 GfxPalette32::matchColor(const uint8 r, const uint8 g, const uint8 b) {
 	int16 bestIndex = 0;
 	int bestDifference = 0xFFFFF;
 	int difference;
 
-	// SQ6 DOS really does check only the first 236 entries
-	for (int i = 0, channelDifference; i < 236; ++i) {
-		difference = _sysPalette.colors[i].r - r;
+	for (int i = 0, channelDifference; i < g_sci->_gfxRemap32->getStartColor(); ++i) {
+		difference = _currentPalette.colors[i].r - r;
 		difference *= difference;
 		if (bestDifference <= difference) {
 			continue;
 		}
 
-		channelDifference = _sysPalette.colors[i].g - g;
+		channelDifference = _currentPalette.colors[i].g - g;
 		difference += channelDifference * channelDifference;
 		if (bestDifference <= difference) {
 			continue;
 		}
 
-		channelDifference = _sysPalette.colors[i].b - b;
+		channelDifference = _currentPalette.colors[i].b - b;
 		difference += channelDifference * channelDifference;
 		if (bestDifference <= difference) {
 			continue;
@@ -162,51 +238,39 @@ int16 GfxPalette32::kernelFindColor(uint16 r, uint16 g, uint16 b) {
 	return bestIndex;
 }
 
-// TODO: set is overridden for the time being to send palettes coming from
-// various draw methods like GfxPicture::drawSci32Vga and GfxView::draw to
-// _nextPalette instead of _sysPalette. In the SCI32 engine, CelObj palettes
-// (which are stored as Hunk palettes) are submitted by GraphicsMgr::FrameOut
-// to PaletteMgr::Submit by way of calls to CelObj::SubmitPalette.
-// GfxPalette::set is very similar to GfxPalette32::submit, except that SCI32
-// does not do any fancy best-fit merging and so does not accept arguments
-// like `force` and `forceRealMerge`.
-void GfxPalette32::set(Palette *newPalette, bool force, bool forceRealMerge) {
-	submit(*newPalette);
-}
-
 bool GfxPalette32::updateForFrame() {
 	applyAll();
-	_versionUpdated = false;
-	return g_sci->_gfxRemap32->remapAllTables(_nextPalette != _sysPalette);
+	_needsUpdate = false;
+	return g_sci->_gfxRemap32->remapAllTables(_nextPalette != _currentPalette);
 }
 
 void GfxPalette32::updateFFrame() {
 	for (int i = 0; i < ARRAYSIZE(_nextPalette.colors); ++i) {
 		_nextPalette.colors[i] = _sourcePalette.colors[i];
 	}
-	_versionUpdated = false;
-	g_sci->_gfxRemap32->remapAllTables(_nextPalette != _sysPalette);
+	_needsUpdate = false;
+	g_sci->_gfxRemap32->remapAllTables(_nextPalette != _currentPalette);
 }
 
 void GfxPalette32::updateHardware() {
-	if (_sysPalette == _nextPalette) {
+	if (_currentPalette == _nextPalette) {
 		return;
 	}
 
 	byte bpal[3 * 256];
 
-	for (int i = 0; i < ARRAYSIZE(_sysPalette.colors); ++i) {
-		_sysPalette.colors[i] = _nextPalette.colors[i];
+	for (int i = 0; i < ARRAYSIZE(_currentPalette.colors); ++i) {
+		_currentPalette.colors[i] = _nextPalette.colors[i];
 
 		// NOTE: If the brightness option in the user configuration file is set,
 		// SCI engine adjusts palette brightnesses here by mapping RGB values to values
 		// in some hard-coded brightness tables. There is no reason on modern hardware
 		// to implement this, unless it is discovered that some game uses a non-standard
 		// brightness setting by default
-		if (_sysPalette.colors[i].used) {
-			bpal[i * 3    ] = _sysPalette.colors[i].r;
-			bpal[i * 3 + 1] = _sysPalette.colors[i].g;
-			bpal[i * 3 + 2] = _sysPalette.colors[i].b;
+		if (_currentPalette.colors[i].used) {
+			bpal[i * 3    ] = _currentPalette.colors[i].r;
+			bpal[i * 3 + 1] = _currentPalette.colors[i].g;
+			bpal[i * 3 + 2] = _currentPalette.colors[i].b;
 		}
 	}
 
@@ -223,6 +287,7 @@ void GfxPalette32::applyAll() {
 #pragma mark -
 #pragma mark Colour look-up
 
+#ifdef ENABLE_SCI3_GAMES
 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.
@@ -272,27 +337,20 @@ void GfxPalette32::unloadClut() {
 	delete[] _clutTable;
 	_clutTable = nullptr;
 }
+#endif
 
 #pragma mark -
 #pragma mark Varying
 
-inline bool GfxPalette32::createPaletteFromResourceInternal(const GuiResourceId paletteId, Palette *const out) const {
-	Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, paletteId), false);
+inline Palette GfxPalette32::getPaletteFromResourceInternal(const GuiResourceId resourceId) const {
+	Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false);
 
 	if (!palResource) {
-		return false;
+		error("Could not load vary target %d", resourceId);
 	}
 
-	createFromData(palResource->data, palResource->size, out);
-	return true;
-}
-
-inline Palette GfxPalette32::getPaletteFromResourceInternal(const GuiResourceId paletteId) const {
-	Palette palette;
-	if (!createPaletteFromResourceInternal(paletteId, &palette)) {
-		error("Could not load vary target %d", paletteId);
-	}
-	return palette;
+	HunkPalette rawPalette(palResource->data);
+	return rawPalette.toPalette();
 }
 
 inline void GfxPalette32::setVaryTimeInternal(const int16 percent, const int time) {
diff --git a/engines/sci/graphics/palette32.h b/engines/sci/graphics/palette32.h
index 7dda53e..6c773cc 100644
--- a/engines/sci/graphics/palette32.h
+++ b/engines/sci/graphics/palette32.h
@@ -26,6 +26,118 @@
 #include "sci/graphics/palette.h"
 
 namespace Sci {
+
+/**
+ * HunkPalette represents a raw palette resource
+ * read from disk.
+ */
+class HunkPalette {
+public:
+	HunkPalette(byte *rawPalette);
+
+	/**
+	 * Gets the version of the palette.
+	 */
+	uint32 getVersion() const { return _version; }
+
+	/**
+	 * Sets the version of the palette.
+	 */
+	void setVersion(const uint32 version);
+
+	/**
+	 * Converts the hunk palette to a standard
+	 * palette.
+	 */
+	const Palette toPalette() const;
+
+private:
+	enum {
+		/**
+		 * The size of the HunkPalette header.
+		 */
+		kHunkPaletteHeaderSize = 13,
+
+		/**
+		 * The size of a palette entry header.
+		 */
+		kEntryHeaderSize = 22,
+
+		/**
+		 * The offset of the hunk palette version
+		 * within the palette entry header.
+		 */
+		kEntryVersionOffset = 18
+	};
+
+	/**
+	 * The header for a palette inside the
+	 * HunkPalette.
+	 */
+	struct EntryHeader {
+		/**
+		 * The start color.
+		 */
+		uint8 startColor;
+
+		/**
+		 * The number of palette colors in this
+		 * entry.
+		 */
+		uint16 numColors;
+
+		/**
+		 * The default `used` flag.
+		 */
+		bool used;
+
+		/**
+		 * Whether or not all palette entries
+		 * share the same `used` value in
+		 * `defaultFlag`.
+		 */
+		bool sharedUsed;
+
+		/**
+		 * The palette version.
+		 */
+		uint32 version;
+	};
+
+	/**
+	 * The version number from the last time this
+	 * palette was submitted to GfxPalette32.
+	 */
+	uint32 _version;
+
+	/**
+	 * The number of palettes stored in the hunk
+	 * palette. In SCI32 games this is always 1.
+	 */
+	uint8 _numPalettes;
+
+	/**
+	 * The raw palette data for this hunk palette.
+	 */
+	byte *_data;
+
+	/**
+	 * Returns a struct that describes the palette
+	 * held by this HunkPalette. The entry header
+	 * is reconstructed on every call from the raw
+	 * palette data.
+	 */
+	const EntryHeader getEntryHeader() const;
+
+	/**
+	 * Returns a pointer to the palette data within
+	 * the hunk palette.
+	 */
+	byte *getPalPointer() const {
+		return _data + kHunkPaletteHeaderSize + (2 * _numPalettes);
+	}
+};
+
 enum PalCyclerDirection {
 	PalCycleBackward = 0,
 	PalCycleForward = 1
@@ -72,28 +184,29 @@ struct PalCycler {
 	uint16 numTimesPaused;
 };
 
-class GfxPalette32 : public GfxPalette {
+class GfxPalette32 {
 public:
-	GfxPalette32(ResourceManager *resMan, GfxScreen *screen);
+	GfxPalette32(ResourceManager *resMan);
 	~GfxPalette32();
 
 private:
-	// NOTE: currentPalette in SCI engine is called _sysPalette
-	// here.
+	ResourceManager *_resMan;
+
+	/**
+	 * The currently displayed palette.
+	 */
+	Palette _currentPalette;
 
 	/**
 	 * The palette revision version. Increments once per game
-	 * loop that changes the source palette. TODO: Possibly
-	 * other areas also change _version, double-check once it
-	 * is all implemented.
+	 * loop that changes the source palette.
 	 */
 	uint32 _version;
 
 	/**
-	 * Whether or not the palette manager version was updated
-	 * during this loop.
+	 * Whether or not the hardware palette needs updating.
 	 */
-	bool _versionUpdated;
+	bool _needsUpdate;
 
 	/**
 	 * The unmodified source palette loaded by kPalette. Additional
@@ -104,7 +217,7 @@ private:
 
 	/**
 	 * The palette to be used when the hardware is next updated.
-	 * On update, _nextPalette is transferred to _sysPalette.
+	 * On update, _nextPalette is transferred to _currentPalette.
 	 */
 	Palette _nextPalette;
 
@@ -112,20 +225,29 @@ private:
 	Palette getPaletteFromResourceInternal(const GuiResourceId paletteId) const;
 
 public:
-	virtual void saveLoadWithSerializer(Common::Serializer &s) override;
+	void saveLoadWithSerializer(Common::Serializer &s);
 	inline const Palette &getNextPalette() const { return _nextPalette; };
-	inline const Palette &getCurrentPalette() const { return _sysPalette; };
+	inline const Palette &getCurrentPalette() const { return _currentPalette; };
 
-	bool kernelSetFromResource(GuiResourceId resourceId, bool force) override;
-	int16 kernelFindColor(uint16 r, uint16 g, uint16 b) override;
-	void set(Palette *newPalette, bool force, bool forceRealMerge = false) override;
+	/**
+	 * Loads a palette into GfxPalette32 with the given resource
+	 * ID.
+	 */
+	bool loadPalette(const GuiResourceId resourceId);
+
+	/**
+	 * Finds the nearest color in the current palette matching the
+	 * given RGB value.
+	 */
+	int16 matchColor(const uint8 r, const uint8 g, const uint8 b);
 
 	/**
 	 * Submits a palette to display. Entries marked as “used” in the
 	 * submitted palette are merged into the existing entries of
 	 * _sourcePalette.
 	 */
-	void submit(Palette &palette);
+	void submit(const Palette &palette);
+	void submit(HunkPalette &palette);
 
 	bool updateForFrame();
 	void updateFFrame();
@@ -213,7 +335,7 @@ public:
 	void kernelPalVarySetTarget(const GuiResourceId paletteId);
 	void kernelPalVarySetStart(const GuiResourceId paletteId);
 	void kernelPalVaryMergeStart(const GuiResourceId paletteId);
-	virtual void kernelPalVaryPause(bool pause) override;
+	void kernelPalVaryPause(bool pause);
 
 	void setVary(const Palette *const targetPalette, const int16 percent, const int time, const int16 fromColor, const int16 toColor);
 	void setVaryPercent(const int16 percent, const int time, const int16 fromColor, const int16 fromColorAlternate);
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index cf03c50..f9481bb 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -167,9 +167,7 @@ SciEngine::~SciEngine() {
 	DebugMan.clearAllDebugChannels();
 
 #ifdef ENABLE_SCI32
-	// _gfxPalette32 is the same as _gfxPalette16
-	// and will be destroyed when _gfxPalette16 is
-	// destroyed
+	delete _gfxPalette32;
 	delete _gfxControls32;
 	delete _gfxPaint32;
 	delete _gfxText32;
@@ -717,8 +715,7 @@ void SciEngine::initGraphics() {
 
 #ifdef ENABLE_SCI32
 	if (getSciVersion() >= SCI_VERSION_2) {
-		_gfxPalette32 = new GfxPalette32(_resMan, _gfxScreen);
-		_gfxPalette16 = _gfxPalette32;
+		_gfxPalette32 = new GfxPalette32(_resMan);
 		_gfxRemap32 = new GfxRemap32();
 	} else {
 #endif
@@ -767,8 +764,10 @@ void SciEngine::initGraphics() {
 	}
 #endif
 
-	// Set default (EGA, amiga or resource 999) palette
-	_gfxPalette16->setDefault();
+	if (getSciVersion() < SCI_VERSION_2) {
+		// Set default (EGA, amiga or resource 999) palette
+		_gfxPalette16->setDefault();
+	}
 }
 
 void SciEngine::initStackBaseWithSelector(Selector selector) {


Commit: 6a13adb638395858882555c23f38451c3a0b55e1
    https://github.com/scummvm/scummvm/commit/6a13adb638395858882555c23f38451c3a0b55e1
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-07-11T10:39:50-05:00

Commit Message:
SCI32: Fix sign comparison warning

Changed paths:
    engines/sci/sound/audio32.h



diff --git a/engines/sci/sound/audio32.h b/engines/sci/sound/audio32.h
index 42211eb89..b0c1ba1 100644
--- a/engines/sci/sound/audio32.h
+++ b/engines/sci/sound/audio32.h
@@ -108,7 +108,7 @@ struct AudioChannel {
 	/**
 	 * The end volume of a fade.
 	 */
-	uint32 fadeTargetVolume;
+	int fadeTargetVolume;
 
 	/**
 	 * Whether or not the channel should be stopped and


Commit: 8fb55564a68078ab2e320b64c2fc63552316d8ae
    https://github.com/scummvm/scummvm/commit/8fb55564a68078ab2e320b64c2fc63552316d8ae
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-07-11T10:39:50-05:00

Commit Message:
SCI32: Fix bad output caused by missing palette copies

Sometimes, games accidentally use palette entries that are not
marked as used and expect them to be a particular colour, like the
Phantasmagoria title screen, or the white palette entry (always
255 in DOS/Win).

Changed paths:
    engines/sci/graphics/palette32.cpp



diff --git a/engines/sci/graphics/palette32.cpp b/engines/sci/graphics/palette32.cpp
index 3a321bf..a43ac27 100644
--- a/engines/sci/graphics/palette32.cpp
+++ b/engines/sci/graphics/palette32.cpp
@@ -259,7 +259,7 @@ void GfxPalette32::updateHardware() {
 
 	byte bpal[3 * 256];
 
-	for (int i = 0; i < ARRAYSIZE(_currentPalette.colors); ++i) {
+	for (int i = 0; i < ARRAYSIZE(_currentPalette.colors) - 1; ++i) {
 		_currentPalette.colors[i] = _nextPalette.colors[i];
 
 		// NOTE: If the brightness option in the user configuration file is set,
@@ -267,12 +267,22 @@ void GfxPalette32::updateHardware() {
 		// in some hard-coded brightness tables. There is no reason on modern hardware
 		// to implement this, unless it is discovered that some game uses a non-standard
 		// brightness setting by default
-		if (_currentPalette.colors[i].used) {
-			bpal[i * 3    ] = _currentPalette.colors[i].r;
-			bpal[i * 3 + 1] = _currentPalette.colors[i].g;
-			bpal[i * 3 + 2] = _currentPalette.colors[i].b;
-		}
-	}
+
+		// All color entries MUST be copied, not just "used" entries, otherwise
+		// uninitialised memory from bpal makes its way into the system palette.
+		// This would not normally be a problem, except that games sometimes use
+		// unused palette entries. e.g. Phant1 title screen references palette
+		// entries outside its own palette, so will render garbage colors where
+		// the game expects them to be black
+		bpal[i * 3    ] = _currentPalette.colors[i].r;
+		bpal[i * 3 + 1] = _currentPalette.colors[i].g;
+		bpal[i * 3 + 2] = _currentPalette.colors[i].b;
+	}
+
+	// The last color must always be white
+	bpal[255 * 3    ] = 255;
+	bpal[255 * 3 + 1] = 255;
+	bpal[255 * 3 + 2] = 255;
 
 	g_system->getPaletteManager()->setPalette(bpal, 0, 256);
 	g_sci->getEventManager()->updateScreen();


Commit: bc362e5b7cf5867946adc45c3a961050323e14b5
    https://github.com/scummvm/scummvm/commit/bc362e5b7cf5867946adc45c3a961050323e14b5
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-07-11T10:39:50-05:00

Commit Message:
SCI32: Minor cleanup of GfxPalette32

Changed paths:
    engines/sci/graphics/palette32.cpp
    engines/sci/graphics/palette32.h



diff --git a/engines/sci/graphics/palette32.cpp b/engines/sci/graphics/palette32.cpp
index a43ac27..4ee33bd 100644
--- a/engines/sci/graphics/palette32.cpp
+++ b/engines/sci/graphics/palette32.cpp
@@ -145,12 +145,12 @@ GfxPalette32::GfxPalette32(ResourceManager *resMan)
 	// Palette cycling
 	_cyclers(),
 	_cycleMap() {
-		_varyPercent = _varyTargetPercent;
-		for (int i = 0, len = ARRAYSIZE(_fadeTable); i < len; ++i) {
-			_fadeTable[i] = 100;
-		}
+	_varyPercent = _varyTargetPercent;
+	for (int i = 0, len = ARRAYSIZE(_fadeTable); i < len; ++i) {
+		_fadeTable[i] = 100;
+	}
 
-		loadPalette(999);
+	loadPalette(999);
 }
 
 GfxPalette32::~GfxPalette32() {
@@ -356,7 +356,7 @@ inline Palette GfxPalette32::getPaletteFromResourceInternal(const GuiResourceId
 	Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false);
 
 	if (!palResource) {
-		error("Could not load vary target %d", resourceId);
+		error("Could not load vary palette %d", resourceId);
 	}
 
 	HunkPalette rawPalette(palResource->data);
@@ -384,8 +384,6 @@ inline void GfxPalette32::setVaryTimeInternal(const int16 percent, const int tim
 	}
 }
 
-// TODO: This gets called *a lot* in at least the first scene
-// of SQ6. Optimisation would not be the worst idea in the world.
 void GfxPalette32::kernelPalVarySet(const GuiResourceId paletteId, const int16 percent, const int time, const int16 fromColor, const int16 toColor) {
 	Palette palette = getPaletteFromResourceInternal(paletteId);
 	setVary(&palette, percent, time, fromColor, toColor);
diff --git a/engines/sci/graphics/palette32.h b/engines/sci/graphics/palette32.h
index 6c773cc..d06541f 100644
--- a/engines/sci/graphics/palette32.h
+++ b/engines/sci/graphics/palette32.h
@@ -193,11 +193,6 @@ private:
 	ResourceManager *_resMan;
 
 	/**
-	 * The currently displayed palette.
-	 */
-	Palette _currentPalette;
-
-	/**
 	 * The palette revision version. Increments once per game
 	 * loop that changes the source palette.
 	 */
@@ -209,6 +204,11 @@ private:
 	bool _needsUpdate;
 
 	/**
+	 * The currently displayed palette.
+	 */
+	Palette _currentPalette;
+
+	/**
 	 * The unmodified source palette loaded by kPalette. Additional
 	 * palette entries may be mixed into the source palette by
 	 * CelObj objects, which contain their own palettes.


Commit: 60c36631425755cbb9d7b06637b129b0e9b4a9da
    https://github.com/scummvm/scummvm/commit/60c36631425755cbb9d7b06637b129b0e9b4a9da
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-07-11T10:39:50-05:00

Commit Message:
SCI32: Fix incorrect logic of cycler overflow

Changed paths:
    engines/sci/graphics/palette32.cpp



diff --git a/engines/sci/graphics/palette32.cpp b/engines/sci/graphics/palette32.cpp
index 4ee33bd..9d1cc65 100644
--- a/engines/sci/graphics/palette32.cpp
+++ b/engines/sci/graphics/palette32.cpp
@@ -651,18 +651,15 @@ void GfxPalette32::setCycle(const uint8 fromColor, const uint8 toColor, const in
 	// 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();
+		uint32 minUpdateDelta = 0xFFFFFFFF;
 
 		for (cyclerIndex = 0; cyclerIndex < numCyclers; ++cyclerIndex) {
 			PalCycler *candidate = _cyclers[cyclerIndex];
 
-			const int32 updateDelta = now - candidate->lastUpdateTick;
-			if (updateDelta >= maxUpdateDelta) {
-				maxUpdateDelta = updateDelta;
+			const uint32 updateDelta = now - candidate->lastUpdateTick;
+			if (updateDelta < minUpdateDelta) {
+				minUpdateDelta = updateDelta;
 				cycler = candidate;
 			}
 		}


Commit: e4588a713435a4606d5799132d602522151839fb
    https://github.com/scummvm/scummvm/commit/e4588a713435a4606d5799132d602522151839fb
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-07-11T10:39:50-05:00

Commit Message:
SCI32: Silence non-monitored channels while monitoring is active

Changed paths:
    engines/sci/sound/audio32.cpp



diff --git a/engines/sci/sound/audio32.cpp b/engines/sci/sound/audio32.cpp
index e7d0246..0cf8e3c 100644
--- a/engines/sci/sound/audio32.cpp
+++ b/engines/sci/sound/audio32.cpp
@@ -353,6 +353,16 @@ int Audio32::readBuffer(Audio::st_sample_t *buffer, const int numSamples) {
 				maxSamplesWritten = _numMonitoredSamples;
 			}
 		} else if (!channel.stream->endOfStream() || channel.loop) {
+			if (_monitoredChannelIndex != -1) {
+				// Audio that is not on the monitored channel is silent
+				// when the monitored channel is active, but the stream still
+				// needs to be read in order to ensure that sound effects sync
+				// up once the monitored channel is turned off. The easiest
+				// way to guarantee this is to just do the normal channel read,
+				// but set the channel volume to zero so nothing is mixed in
+				leftVolume = rightVolume = 0;
+			}
+
 			const int channelSamplesWritten = writeAudioInternal(channel.stream, channel.converter, buffer, numSamples, leftVolume, rightVolume, channel.loop);
 			if (channelSamplesWritten > maxSamplesWritten) {
 				maxSamplesWritten = channelSamplesWritten;


Commit: f171db965c2a927d8d526f56d777a70f6b89ed51
    https://github.com/scummvm/scummvm/commit/f171db965c2a927d8d526f56d777a70f6b89ed51
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-07-11T10:39:50-05:00

Commit Message:
SCI32: Guard against no split count

CID 1357229.

Changed paths:
    engines/sci/graphics/plane32.cpp



diff --git a/engines/sci/graphics/plane32.cpp b/engines/sci/graphics/plane32.cpp
index 175875c..87ab43b 100644
--- a/engines/sci/graphics/plane32.cpp
+++ b/engines/sci/graphics/plane32.cpp
@@ -595,8 +595,10 @@ void Plane::filterDownEraseRects(DrawList &drawList, RectList &eraseList, RectLi
 				Common::Rect outRects[4];
 				const Common::Rect &r2 = *higherEraseList[i];
 				int splitCount = splitRects(r2, r, outRects);
-				while (splitCount--) {
-					higherEraseList.add(outRects[splitCount]);
+				if (splitCount > 0) {
+					while (splitCount--) {
+						higherEraseList.add(outRects[splitCount]);
+					}
 				}
 				higherEraseList.erase_at(i);
 			}


Commit: 08821cf4e3cec6d8b65b4cb1fa49f466430eb330
    https://github.com/scummvm/scummvm/commit/08821cf4e3cec6d8b65b4cb1fa49f466430eb330
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-07-11T10:39:50-05:00

Commit Message:
SCI32: Give planes a default type

With the addition of the transparent pic type code, the _type
property would be read uninitialised by setType if _pictureId was
set to kPlanePic.

CID 1357230, 1357231.

Changed paths:
    engines/sci/graphics/plane32.cpp
    engines/sci/graphics/plane32.h



diff --git a/engines/sci/graphics/plane32.cpp b/engines/sci/graphics/plane32.cpp
index 87ab43b..aa629e4 100644
--- a/engines/sci/graphics/plane32.cpp
+++ b/engines/sci/graphics/plane32.cpp
@@ -47,6 +47,7 @@ uint16 Plane::_nextObjectId = 20000;
 Plane::Plane(const Common::Rect &gameRect, PlanePictureCodes pictureId) :
 _pictureId(pictureId),
 _mirrored(false),
+_type(kPlaneTypeColored),
 _back(0),
 _priorityChanged(0),
 _object(make_reg(0, _nextObjectId++)),
@@ -63,6 +64,7 @@ _gameRect(gameRect) {
 }
 
 Plane::Plane(reg_t object) :
+_type(kPlaneTypeColored),
 _priorityChanged(false),
 _object(object),
 _redrawAllCount(g_sci->_gfxFrameout->getScreenCount()),
@@ -93,6 +95,7 @@ _moved(0) {
 Plane::Plane(const Plane &other) :
 _pictureId(other._pictureId),
 _mirrored(other._mirrored),
+_type(other._type),
 _back(other._back),
 _object(other._object),
 _priority(other._priority),
diff --git a/engines/sci/graphics/plane32.h b/engines/sci/graphics/plane32.h
index a173926..3981a2b 100644
--- a/engines/sci/graphics/plane32.h
+++ b/engines/sci/graphics/plane32.h
@@ -150,6 +150,11 @@ private:
 
 public:
 	/**
+	 * The type of the plane.
+	 */
+	PlaneType _type;
+
+	/**
 	 * The color to use when erasing the plane. Only
 	 * applies to planes of type kPlaneTypeColored.
 	 */
@@ -186,8 +191,6 @@ public:
 	 */
 	int _redrawAllCount;
 
-	PlaneType _type;
-
 	/**
 	 * Flags indicating the state of the plane.
 	 * - `created` is set when the plane is first created,






More information about the Scummvm-git-logs mailing list