[Scummvm-git-logs] scummvm master -> 1d3be6bf55be922abf6be0d6529a442c8c8e64fe

athrxx noreply at scummvm.org
Sat Jul 11 16:46:46 UTC 2026


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

Summary:
8d29289f96 KYRA: (EOBII/FM-TOWNS) - fix colors in OpenGL mode
1d3be6bf55 KYRA: (EOBII/FM-TOWNS) - allow 32bit graphics modes


Commit: 8d29289f96f865999bc34c956ee934cb5faa78e6
    https://github.com/scummvm/scummvm/commit/8d29289f96f865999bc34c956ee934cb5faa78e6
Author: athrxx (athrxx at scummvm.org)
Date: 2026-07-11T18:45:31+02:00

Commit Message:
KYRA: (EOBII/FM-TOWNS) - fix colors in OpenGL mode

(color correctness depended on the pixel format provided by the backend)

Changed paths:
    engines/kyra/engine/scene_eob.cpp
    engines/kyra/graphics/screen.cpp
    engines/kyra/graphics/screen.h
    engines/kyra/graphics/screen_eob.cpp
    engines/kyra/graphics/screen_eob.h
    engines/kyra/graphics/screen_eob_towns.cpp
    engines/kyra/sequence/sequences_darkmoon.cpp


diff --git a/engines/kyra/engine/scene_eob.cpp b/engines/kyra/engine/scene_eob.cpp
index be1fcc80744..832c2231efa 100644
--- a/engines/kyra/engine/scene_eob.cpp
+++ b/engines/kyra/engine/scene_eob.cpp
@@ -206,11 +206,11 @@ Common::String EoBCoreEngine::initLevelData(int sub) {
 
 		if (_flags.platform == Common::kPlatformFMTowns) {
 			uint16 *src = (uint16*)_screen->getPalette(0).getData();
-			_screen->createFadeTable16bit(src, (uint16*)_greenFadingTable, 4, 75);
-			_screen->createFadeTable16bit(src, (uint16*)_blackFadingTable, 12, 200);
-			_screen->createFadeTable16bit(src, (uint16*)_blueFadingTable, 10, 85);
-			_screen->createFadeTable16bit(src, (uint16*)_lightBlueFadingTable, 11, 125);
-			_screen->createFadeTable16bit(src, (uint16*)_greyFadingTable, 0, 85);
+			_screen->createHiColorFadeTable(src, (uint16*)_greenFadingTable, 4, 75);
+			_screen->createHiColorFadeTable(src, (uint16*)_blackFadingTable, 12, 200);
+			_screen->createHiColorFadeTable(src, (uint16*)_blueFadingTable, 10, 85);
+			_screen->createHiColorFadeTable(src, (uint16*)_lightBlueFadingTable, 11, 125);
+			_screen->createHiColorFadeTable(src, (uint16*)_greyFadingTable, 0, 85);
 			_screen->setScreenPalette(_screen->getPalette(0));
 		} else if (_configRenderMode != Common::kRenderCGA && _flags.platform != Common::kPlatformAmiga && _flags.platform != Common::kPlatformSegaCD && !(_flags.gameID == GI_EOB1 && _flags.platform == Common::kPlatformPC98)) {
 			Palette backupPal(256);
@@ -218,13 +218,13 @@ Common::String EoBCoreEngine::initLevelData(int sub) {
 			_screen->getPalette(0).fill(224, 32, 0x3F);
 			uint8 *src = _screen->getPalette(0).getData();
 
-			_screen->createFadeTable(src, _greenFadingTable, 4, 75);
-			_screen->createFadeTable(src, _blackFadingTable, 12, 200);
-			_screen->createFadeTable(src, _blueFadingTable, 10, 85);
-			_screen->createFadeTable(src, _lightBlueFadingTable, 11, 125);
+			_screen->createColorFadeTable(src, _greenFadingTable, 4, 75);
+			_screen->createColorFadeTable(src, _blackFadingTable, 12, 200);
+			_screen->createColorFadeTable(src, _blueFadingTable, 10, 85);
+			_screen->createColorFadeTable(src, _lightBlueFadingTable, 11, 125);
 
 			_screen->getPalette(0).copy(backupPal, 224, 32, 224);
-			_screen->createFadeTable(src, _greyFadingTable, 12, 85);
+			_screen->createColorFadeTable(src, _greyFadingTable, 12, 85);
 			_screen->setFadeTable(_greyFadingTable);
 			if (_flags.gameID == GI_EOB2 && _configRenderMode == Common::kRenderEGA)
 				_screen->setScreenPalette(_screen->getPalette(0));
@@ -634,8 +634,8 @@ void EoBCoreEngine::drawSceneShapes(int start, int end, int drawFlags) {
 		if (_shpDmX2 <= _shpDmX1)
 			continue;
 
-		if (drawFlags & 0x01)
-			drawDecorations(t);
+		//if (drawFlags & 0x01)
+			//drawDecorations(t);
 
 		if ((drawFlags & 0x02) && _visibleBlocks[t]->drawObjects)
 			drawBlockItems(t);
diff --git a/engines/kyra/graphics/screen.cpp b/engines/kyra/graphics/screen.cpp
index aacdc0a02c9..0a51e1d7556 100644
--- a/engines/kyra/graphics/screen.cpp
+++ b/engines/kyra/graphics/screen.cpp
@@ -74,12 +74,13 @@ Screen::Screen(KyraEngine_v1 *vm, OSystem *system, const ScreenDim *dimTable, co
 	_textRenderBufferSize = 0;
 
 	_useHiColorScreen = _vm->gameFlags().useHiColorMode;
+	_outputPixelFormat = Graphics::PixelFormat::createFormatCLUT8();
 	_useShapeShading = true;
 	_screenPageSize = SCREEN_PAGE_SIZE;
-	_16bitPalette = nullptr;
-	_16bitConversionPalette = nullptr;
-	_16bitShadingLevel = 0;
-	_bytesPerPixel = 1;
+	_hiColorNativePalettes = nullptr;
+	_hiColorConversionPalette = nullptr;
+	_hiColorShadingLevel = 0;
+	_internalBytesPerPixel = 1;
 	_4bitPixelPacking = _useAmigaExtraColors = _isAmiga = _isSegaCD = _use16ColorMode = false;
 	_useSJIS = _useOverlays = _useHiResEGADithering = false;
 
@@ -112,8 +113,8 @@ Screen::~Screen() {
 	delete _screenPalette;
 	delete _internFadePalette;
 	delete[] _animBlockPtr;
-	delete[] _16bitPalette;
-	delete[] _16bitConversionPalette;
+	delete[] _hiColorNativePalettes;
+	delete[] _hiColorConversionPalette;
 
 	_sjisFontShared.reset();
 
@@ -337,7 +338,9 @@ Common::Error Screen::setResolution() {
 			}
 		}
 		initGraphics(width, height, tryModes);
-		if (_system->getScreenFormat().bytesPerPixel != 2)
+
+		_outputPixelFormat = _system->getScreenFormat();
+		if (_outputPixelFormat.bytesPerPixel < 2)
 			return Common::kUnsupportedColorMode;
 
 	} else {
@@ -350,25 +353,25 @@ Common::Error Screen::setResolution() {
 
 void Screen::enableHiColorMode(bool enabled) {
 	if (_useHiColorScreen && enabled) {
-		if (!_16bitPalette)
-			_16bitPalette = new uint16[1024];
-		memset(_16bitPalette, 0, 1024 * sizeof(uint16));
-		delete[] _16bitConversionPalette;
-		_16bitConversionPalette = nullptr;
-		_bytesPerPixel = 2;
+		if (!_hiColorNativePalettes)
+			_hiColorNativePalettes = new uint16[1024];
+		memset(_hiColorNativePalettes, 0, 1024 * sizeof(uint16));
+		delete[] _hiColorConversionPalette;
+		_hiColorConversionPalette = nullptr;
+		_internalBytesPerPixel = 2;
 	} else {
 		if (_useHiColorScreen) {
-			if (!_16bitConversionPalette)
-				_16bitConversionPalette = new uint16[256];
-			memset(_16bitConversionPalette, 0, 256 * sizeof(uint16));
+			if (!_hiColorConversionPalette)
+				_hiColorConversionPalette = new uint16[256];
+			memset(_hiColorConversionPalette, 0, 256 * sizeof(uint16));
 		}
 
-		delete[] _16bitPalette;
-		_16bitPalette = nullptr;
-		_bytesPerPixel = 1;
+		delete[] _hiColorNativePalettes;
+		_hiColorNativePalettes = nullptr;
+		_internalBytesPerPixel = 1;
 	}
 
-	resetPagePtrsAndBuffers(_isSegaCD ? SCREEN_W * _screenHeight : SCREEN_PAGE_SIZE * _bytesPerPixel);
+	resetPagePtrsAndBuffers(_isSegaCD ? SCREEN_W * _screenHeight : SCREEN_PAGE_SIZE * _internalBytesPerPixel);
 }
 
 int Screen::updateScreen() {
@@ -468,7 +471,7 @@ void Screen::updateDirtyRectsAmiga() {
 #define mScale2x(dst, dstPitch, src, srcPitch, w, h) \
 	if (!_useHiColorScreen) \
 		scale2x<uint8, uint16>(dst, dstPitch, src, srcPitch, w, h); \
-	else if (_bytesPerPixel == 2) \
+	else if (_internalBytesPerPixel == 2) \
 		scale2x<uint16, uint32>(dst, dstPitch, src, srcPitch, w, h); \
 	 else \
 		scale2x<uint8, uint32>(dst, dstPitch, src, srcPitch, w, h)
@@ -488,7 +491,7 @@ void Screen::updateDirtyRectsOvl() {
 		Common::List<Common::Rect>::iterator it;
 		for (it = _dirtyRects.begin(); it != _dirtyRects.end(); ++it) {
 			byte *dst = ovl0 + it->top * 1280 * dstBpp + (it->left << dstBpp);
-			const byte *src = page0 + it->top * SCREEN_W * _bytesPerPixel + it->left * _bytesPerPixel;
+			const byte *src = page0 + it->top * SCREEN_W * _internalBytesPerPixel + it->left * _internalBytesPerPixel;
 			mScale2x(dst, 640, src, SCREEN_W, it->width(), it->height());
 			mergeOverlay(it->left<<1, it->top<<1, it->width()<<1, it->height()<<1);
 			_system->copyRectToScreen(dst, _useHiColorScreen ? 1280 : 640, it->left << 1, it->top << 1, it->width() << 1, it->height() << 1);
@@ -511,7 +514,7 @@ void Screen::scale2x(uint8 *dst, int dstPitch, const uint8 *src, int srcPitch, i
 
 	while (h--) {
 		for (int x = 0; x < w; x++) {
-			scaleToType col = (sizeof(srcType) == 1 && sizeof(scaleToType) == 4) ? _16bitConversionPalette[*src1++] : *src1++;
+			scaleToType col = (sizeof(srcType) == 1 && sizeof(scaleToType) == 4) ? _hiColorConversionPalette[*src1++] : *src1++;
 			*dstL1++ = *dstL2++ = col | (col << (sizeof(scaleToType) << 2));
 		}
 		dstL1 += dstAdd; dstL2 += dstAdd;
@@ -526,7 +529,7 @@ template void Screen::scale2x<uint8, uint32>(uint8 *dst, int dstPitch, const uin
 template<typename pixelType>
 void Screen::mergeOverlayImpl(int x, int y, int w, int h) {
 	const uint8 *src = _sjisOverlayPtrs[1] + y * 640 + x;
-	uint16 *p16 = _16bitPalette ? _16bitPalette : _16bitConversionPalette;
+	uint16 *p16 = _hiColorNativePalettes ? _hiColorNativePalettes : _hiColorConversionPalette;
 	pixelType *dst = (pixelType*)(_sjisOverlayPtrs[0] + y * 640 * sizeof(pixelType) + x * sizeof(pixelType));
 	int add = 640 - w;
 
@@ -784,7 +787,7 @@ void Screen::copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc,
 int Screen::getPagePixel(int pageNum, int x, int y) {
 	assert(pageNum < SCREEN_PAGE_NUM);
 	assert(x >= 0 && x < SCREEN_W && y >= 0 && y < _screenHeight);
-	if (_bytesPerPixel == 1)
+	if (_internalBytesPerPixel == 1)
 		return _pagePtrs[pageNum][y * SCREEN_W + x];
 	else
 		return ((uint16*)_pagePtrs[pageNum])[y * SCREEN_W + x];
@@ -806,8 +809,8 @@ void Screen::setPagePixel(int pageNum, int x, int y, uint8 color) {
 		color &= 0x0F;
 	}
 
-	if (_bytesPerPixel == 2) {
-		((uint16*)_pagePtrs[pageNum])[y * SCREEN_W + x] = _16bitPalette[color];
+	if (_internalBytesPerPixel == 2) {
+		((uint16*)_pagePtrs[pageNum])[y * SCREEN_W + x] = _hiColorNativePalettes[color];
 	} else {
 		_pagePtrs[pageNum][y * SCREEN_W + x] = color;
 	}
@@ -826,12 +829,12 @@ void Screen::fadeToBlack(int delay, const UpdateFunctor *upFunc) {
 }
 
 void Screen::fadePalette(const Palette &pal, int delay, const UpdateFunctor *upFunc) {
-	if (_renderMode == Common::kRenderEGA || _bytesPerPixel == 2)
+	if (_renderMode == Common::kRenderEGA || _internalBytesPerPixel == 2)
 		setScreenPalette(pal);
 
 	updateScreen();
 
-	if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderEGA || _bytesPerPixel == 2)
+	if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderEGA || _internalBytesPerPixel == 2)
 		return;
 
 	int diff = 0, delayInc = 0;
@@ -961,22 +964,6 @@ void Screen::setScreenPalette(const Palette &pal) {
 	}
 
 	_paletteChanged = true;
-
-	if (_useHiColorScreen) {
-		if (_16bitPalette)
-			memcpy(_16bitPalette, pal.getData(), 512);
-
-		// Generate 16bit palette for the 8bit/16 bit conversion in scale2x()
-		if (_16bitConversionPalette) {
-			Graphics::PixelFormat pixelFormat = _system->getScreenFormat();
-			for (int i = 0; i < 256; ++i)
-				_16bitConversionPalette[i] = pixelFormat.RGBToColor(screenPal[i * 3], screenPal[i * 3 + 1], screenPal[i * 3 + 2]);
-			// The whole Surface has to be converted again after each palette change
-			_forceFullUpdate = true;
-		}
-		return;
-	}
-
 	_system->getPaletteManager()->setPalette(screenPal, 0, pal.getNumColors());
 }
 
@@ -1050,8 +1037,8 @@ void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPag
 		h = _screenHeight - y2;
 	}
 
-	const uint8 *src = getPagePtr(srcPage) + y1 * SCREEN_W * _bytesPerPixel + x1 * _bytesPerPixel;
-	uint8 *dst = getPagePtr(dstPage) + y2 * SCREEN_W * _bytesPerPixel + x2 * _bytesPerPixel;
+	const uint8 *src = getPagePtr(srcPage) + y1 * SCREEN_W * _internalBytesPerPixel + x1 * _internalBytesPerPixel;
+	uint8 *dst = getPagePtr(dstPage) + y2 * SCREEN_W * _internalBytesPerPixel + x2 * _internalBytesPerPixel;
 
 	if (src == dst)
 		return;
@@ -1063,14 +1050,14 @@ void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPag
 
 	if (flags & CR_NO_P_CHECK) {
 		while (h--) {
-			memmove(dst, src, w * _bytesPerPixel);
-			src += SCREEN_W * _bytesPerPixel;
-			dst += SCREEN_W * _bytesPerPixel;
+			memmove(dst, src, w * _internalBytesPerPixel);
+			src += SCREEN_W * _internalBytesPerPixel;
+			dst += SCREEN_W * _internalBytesPerPixel;
 		}
 	} else {
 		while (h--) {
 			for (int i = 0; i < w; ++i) {
-				if (_bytesPerPixel == 2) {
+				if (_internalBytesPerPixel == 2) {
 					uint px = *(const uint16*)&src[i << 1];
 					if (px)
 						*(uint16*)&dst[i << 1] = px;
@@ -1079,15 +1066,15 @@ void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPag
 						dst[i] = src[i];
 				}
 			}
-			src += SCREEN_W * _bytesPerPixel;
-			dst += SCREEN_W * _bytesPerPixel;
+			src += SCREEN_W * _internalBytesPerPixel;
+			dst += SCREEN_W * _internalBytesPerPixel;
 		}
 	}
 }
 
 void Screen::copyRegionToBuffer(int pageNum, int x, int y, int w, int h, uint8 *dest) {
 	if (y < 0) {
-		dest += (-y) * w * _bytesPerPixel;
+		dest += (-y) * w * _internalBytesPerPixel;
 		h += y;
 		y = 0;
 	} else if (y + h > _screenHeight) {
@@ -1096,7 +1083,7 @@ void Screen::copyRegionToBuffer(int pageNum, int x, int y, int w, int h, uint8 *
 
 	int pitch = w;
 	if (x < 0) {
-		dest += -x * _bytesPerPixel;
+		dest += -x * _internalBytesPerPixel;
 		w += x;
 		x = 0;
 	} else if (x + w > SCREEN_W) {
@@ -1109,14 +1096,14 @@ void Screen::copyRegionToBuffer(int pageNum, int x, int y, int w, int h, uint8 *
 	uint8 *pagePtr = getPagePtr(pageNum);
 
 	for (int i = y; i < y + h; ++i)
-		memcpy(dest + (i - y) * pitch * _bytesPerPixel, pagePtr + i * SCREEN_W * _bytesPerPixel + x * _bytesPerPixel, w * _bytesPerPixel);
+		memcpy(dest + (i - y) * pitch * _internalBytesPerPixel, pagePtr + i * SCREEN_W * _internalBytesPerPixel + x * _internalBytesPerPixel, w * _internalBytesPerPixel);
 }
 
 void Screen::copyPage(uint8 srcPage, uint8 dstPage) {
 	uint8 *src = getPagePtr(srcPage);
 	uint8 *dst = getPagePtr(dstPage);
 	if (src != dst)
-		memcpy(dst, src, SCREEN_W * _screenHeight * _bytesPerPixel);
+		memcpy(dst, src, SCREEN_W * _screenHeight * _internalBytesPerPixel);
 	copyOverlayRegion(0, 0, 0, 0, SCREEN_W, _screenHeight, srcPage, dstPage);
 
 	if (dstPage == 0 || dstPage == 1)
@@ -1125,7 +1112,7 @@ void Screen::copyPage(uint8 srcPage, uint8 dstPage) {
 
 void Screen::copyBlockToPage(int pageNum, int x, int y, int w, int h, const uint8 *src) {
 	if (y < 0) {
-		src += (-y) * w * _bytesPerPixel;
+		src += (-y) * w * _internalBytesPerPixel;
 		h += y;
 		y = 0;
 	} else if (y + h > _screenHeight) {
@@ -1134,7 +1121,7 @@ void Screen::copyBlockToPage(int pageNum, int x, int y, int w, int h, const uint
 
 	int pitch = w;
 	if (x < 0) {
-		src += -x * _bytesPerPixel;
+		src += -x * _internalBytesPerPixel;
 		w += x;
 		x = 0;
 	} else if (x + w > SCREEN_W) {
@@ -1144,7 +1131,7 @@ void Screen::copyBlockToPage(int pageNum, int x, int y, int w, int h, const uint
 	if (w < 0 || h < 0)
 		return;
 
-	uint8 *dst = getPagePtr(pageNum) + y * SCREEN_W * _bytesPerPixel + x * _bytesPerPixel;
+	uint8 *dst = getPagePtr(pageNum) + y * SCREEN_W * _internalBytesPerPixel + x * _internalBytesPerPixel;
 
 	if (pageNum == 0 || pageNum == 1)
 		addDirtyRect(x, y, w, h);
@@ -1152,9 +1139,9 @@ void Screen::copyBlockToPage(int pageNum, int x, int y, int w, int h, const uint
 	clearOverlayRect(pageNum, x, y, w, h);
 
 	while (h--) {
-		memcpy(dst, src, w * _bytesPerPixel);
-		dst += SCREEN_W * _bytesPerPixel;
-		src += pitch * _bytesPerPixel;
+		memcpy(dst, src, w * _internalBytesPerPixel);
+		dst += SCREEN_W * _internalBytesPerPixel;
+		src += pitch * _internalBytesPerPixel;
 	}
 }
 
@@ -1220,7 +1207,7 @@ void Screen::fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum,
 	if (pageNum == -1)
 		pageNum = _curPage;
 
-	uint8 *dst = getPagePtr(pageNum) + y1 * SCREEN_W * _bytesPerPixel + x1 * _bytesPerPixel;
+	uint8 *dst = getPagePtr(pageNum) + y1 * SCREEN_W * _internalBytesPerPixel + x1 * _internalBytesPerPixel;
 
 	if (pageNum == 0 || pageNum == 1)
 		addDirtyRect(x1, y1, x2-x1+1, y2-y1+1);
@@ -1234,8 +1221,8 @@ void Screen::fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum,
 		color &= 0x03;
 	} else if (_use16ColorMode || (_renderMode == Common::kRenderEGA && !_useHiResEGADithering)) {
 		color &= 0x0F;
-	} else if (_bytesPerPixel == 2)
-		color16 = shade16bitColor(_16bitPalette[color]);
+	} else if (_internalBytesPerPixel == 2)
+		color16 = shadeRGBColor(_hiColorNativePalettes[color]);
 
 	if (xored) {
 		// no 16 bit support for this (unneeded)
@@ -1246,14 +1233,14 @@ void Screen::fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum,
 		}
 	} else {
 		for (; y1 <= y2; ++y1) {
-			if (_bytesPerPixel == 2) {
+			if (_internalBytesPerPixel == 2) {
 				uint16 *ptr = (uint16*)dst;
 				for (int i = 0; i < x2 - x1 + 1; i++)
 					*ptr++ = color16;
 			} else {
 				memset(dst, color, x2 - x1 + 1);
 			}
-			dst += SCREEN_W * _bytesPerPixel;
+			dst += SCREEN_W * _internalBytesPerPixel;
 		}
 	}
 }
@@ -1310,7 +1297,7 @@ void Screen::drawClippedLine(int x1, int y1, int x2, int y2, int color) {
 }
 
 void Screen::drawLine(bool vertical, int x, int y, int length, int color) {
-	uint8 *ptr = getPagePtr(_curPage) + y * SCREEN_W * _bytesPerPixel + x * _bytesPerPixel;
+	uint8 *ptr = getPagePtr(_curPage) + y * SCREEN_W * _internalBytesPerPixel + x * _internalBytesPerPixel;
 
 	if (_4bitPixelPacking) {
 		color &= 0x0F;
@@ -1319,23 +1306,23 @@ void Screen::drawLine(bool vertical, int x, int y, int length, int color) {
 		color &= 0x03;
 	} else if (_use16ColorMode || (_renderMode == Common::kRenderEGA && !_useHiResEGADithering)) {
 		color &= 0x0F;
-	} else if (_bytesPerPixel == 2)
-		color = shade16bitColor(_16bitPalette[color]);
+	} else if (_internalBytesPerPixel == 2)
+		color = shadeRGBColor(_hiColorNativePalettes[color]);
 
 	if (vertical) {
 		assert((y + length) <= SCREEN_H);
 		int currLine = 0;
 		while (currLine < length) {
-			if (_bytesPerPixel == 2)
+			if (_internalBytesPerPixel == 2)
 				*(uint16*)ptr = color;
 			else
 				*ptr = color;
-			ptr += SCREEN_W * _bytesPerPixel;
+			ptr += SCREEN_W * _internalBytesPerPixel;
 			currLine++;
 		}
 	} else {
 		assert((x + length) <= SCREEN_W);
-		if (_bytesPerPixel == 2) {
+		if (_internalBytesPerPixel == 2) {
 			for (int i = 0; i < length; i++) {
 				*(uint16*)ptr = color;
 				ptr += 2;
@@ -1530,9 +1517,9 @@ int Screen::getNumberOfCharacters(const char *str) {
 
 void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2, int pitch) {
 	uint16 cmap16[2];
-	if (_16bitPalette) {
-		cmap16[0] = color2 ? shade16bitColor(_16bitPalette[color2]) : 0xFFFF;
-		cmap16[1] = _16bitPalette[color1];
+	if (_hiColorNativePalettes) {
+		cmap16[0] = color2 ? shadeRGBColor(_hiColorNativePalettes[color2]) : 0xFFFF;
+		cmap16[1] = _hiColorNativePalettes[color1];
 		setTextColor16bit(cmap16);
 	}
 
@@ -1644,7 +1631,7 @@ void Screen::drawChar(uint16 c, int x, int y, int pitch) {
 
 		fnt->drawChar(c, destPage, 640, bpp);
 	} else {
-		fnt->drawChar(c, getPagePtr(_curPage) + y * SCREEN_W * _bytesPerPixel + x * _bytesPerPixel, SCREEN_W, _bytesPerPixel);
+		fnt->drawChar(c, getPagePtr(_curPage) + y * SCREEN_W * _internalBytesPerPixel + x * _internalBytesPerPixel, SCREEN_W, _internalBytesPerPixel);
 	}
 
 	if (!_isSegaCD && (_curPage == 0 || _curPage == 1))
@@ -3126,16 +3113,15 @@ int16 Screen::encodeShapeAndCalculateSize(uint8 *from, uint8 *to, int size_to) {
 	return (to - toPtr);
 }
 
-uint16 Screen::shade16bitColor(uint16 col) {
-	uint8 r = (col & 0x1f);
-	uint8 g = (col & 0x3E0) >> 5;
-	uint8 b = (col & 0x7C00) >> 10;
+uint16 Screen::shadeRGBColor(uint16 col) {
+	uint8 r = 0, g = 0, b = 0;
+	_outputPixelFormat.colorToRGB(col, r, g, b);
 
-	r = (r > _16bitShadingLevel) ? r - _16bitShadingLevel : 0;
-	g = (g > _16bitShadingLevel) ? g - _16bitShadingLevel : 0;
-	b = (b > _16bitShadingLevel) ? b - _16bitShadingLevel : 0;
+	r = (r > _hiColorShadingLevel) ? r - _hiColorShadingLevel : 0;
+	g = (g > _hiColorShadingLevel) ? g - _hiColorShadingLevel : 0;
+	b = (b > _hiColorShadingLevel) ? b - _hiColorShadingLevel : 0;
 
-	return (b << 10) | (g << 5) | r;
+	return _outputPixelFormat.RGBToColor(r, g, b);
 }
 
 void Screen::hideMouse() {
@@ -3433,7 +3419,7 @@ bool Screen::loadPalette(const char *filename, Palette &pal) {
 
 	debugC(3, kDebugLevelScreen, "Screen::loadPalette('%s', %p)", filename, (const void *)&pal);
 
-	const int maxCols = _16bitPalette ? 256 : pal.getNumColors();
+	const int maxCols = _hiColorNativePalettes ? 256 : pal.getNumColors();
 	int numCols = 0;
 
 	if (_isAmiga) {
@@ -3449,10 +3435,10 @@ bool Screen::loadPalette(const char *filename, Palette &pal) {
 		numCols /= Palette::kVGABytesPerColor;
 		pal.loadVGAPalette(*stream, 0, numCols);
 	} else {
-		if (_bytesPerPixel == 2) {
+		if (_internalBytesPerPixel == 2) {
 			numCols = stream->size() / 2;
 			pal.loadHiColorPalette(*stream, 0, numCols);
-		} else if (!_16bitPalette) {
+		} else if (!_hiColorNativePalettes) {
 			numCols = stream->size() / Palette::kVGABytesPerColor;
 			pal.loadVGAPalette(*stream, 0, MIN(maxCols, numCols));
 		} else {
@@ -3636,7 +3622,7 @@ void Screen::crossFadeRegion(int x1, int y1, int x2, int y2, int w, int h, int s
 	hideMouse();
 
 	uint16 *wB = (uint16 *)_pagePtrs[14];
-	uint8 *hB = _pagePtrs[14] + 640 * _bytesPerPixel;
+	uint8 *hB = _pagePtrs[14] + 640 * _internalBytesPerPixel;
 
 	for (int i = 0; i < w; i++)
 		wB[i] = i;
@@ -3665,7 +3651,7 @@ void Screen::crossFadeRegion(int x1, int y1, int x2, int y2, int w, int h, int s
 			if (++iH >= h)
 				iH = 0;
 
-			if (_bytesPerPixel == 2)
+			if (_internalBytesPerPixel == 2)
 				((uint16*)d)[dY * 320 + dX] = ((uint16*)s)[sY * 320 + sX];
 			else
 				d[dY * 320 + dX] = s[sY * 320 + sX];
@@ -4110,15 +4096,8 @@ void Palette::loadVGAPalette(Common::ReadStream &stream, int startIndex, int col
 
 void Palette::loadHiColorPalette(Common::ReadStream &stream, int startIndex, int colors) {
 	uint16 *pos = (uint16*)(_palData + startIndex * 2);
-
-	Graphics::PixelFormat currentFormat = g_system->getScreenFormat();
-	Graphics::PixelFormat originalFormat(2, 5, 5, 5, 0, 5, 10, 0, 0);
-
-	for (int i = 0; i < colors; i++) {
-		uint8 r, g, b;
-		originalFormat.colorToRGB(stream.readUint16LE(), r, g, b);
-		*pos++ = currentFormat.RGBToColor(r, g, b);
-	}
+	for (int i = 0; i < colors; i++)
+		*pos++ = stream.readUint16LE();
 }
 
 void Palette::loadEGAPalette(Common::ReadStream &stream, int startIndex, int colors) {
diff --git a/engines/kyra/graphics/screen.h b/engines/kyra/graphics/screen.h
index 083d8b328bf..3e9dc38a2bd 100644
--- a/engines/kyra/graphics/screen.h
+++ b/engines/kyra/graphics/screen.h
@@ -31,6 +31,7 @@
 #include "common/stream.h"
 #include "common/ptr.h"
 #include "common/error.h"
+#include "graphics/pixelformat.h"
 
 class OSystem;
 
@@ -813,8 +814,8 @@ public:
 	// can well afford the 20 lines of extra code.
 	void crossFadeRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage);
 
-	uint16 *get16bitPalette() { return _16bitPalette; }
-	void set16bitShadingLevel(int lvl) { _16bitShadingLevel = lvl; }
+	uint16 *get16bitPalette() { return _hiColorNativePalettes; }
+	void set16bitShadingLevel(int lvl) { _hiColorShadingLevel = lvl; }
 
 protected:
 	void resetPagePtrsAndBuffers(int pageSize);
@@ -872,12 +873,13 @@ protected:
 	bool _useShapeShading;
 	bool _4bitPixelPacking;
 	bool _useHiResEGADithering;
+	Graphics::PixelFormat _outputPixelFormat;
 	bool _useHiColorScreen;
 	bool _isAmiga;
 	bool _useAmigaExtraColors;
 	bool _isSegaCD;
 	Common::RenderMode _renderMode;
-	int _bytesPerPixel;
+	int _internalBytesPerPixel;
 	int _screenPageSize;
 	const int _screenHeight;
 	int _yTransOffs;
@@ -886,11 +888,11 @@ protected:
 	Common::Array<Palette *> _palettes;
 	Palette *_internFadePalette;
 
-	uint16 shade16bitColor(uint16 col);
+	uint16 shadeRGBColor(uint16 col);
 
-	uint16 *_16bitPalette;
-	uint16 *_16bitConversionPalette;
-	uint8 _16bitShadingLevel;
+	uint16 *_hiColorNativePalettes;
+	uint16 *_hiColorConversionPalette;
+	uint8 _hiColorShadingLevel;
 
 	uint8 *_animBlockPtr;
 	int _animBlockSize;
diff --git a/engines/kyra/graphics/screen_eob.cpp b/engines/kyra/graphics/screen_eob.cpp
index c3a8c194db8..61784b1e638 100644
--- a/engines/kyra/graphics/screen_eob.cpp
+++ b/engines/kyra/graphics/screen_eob.cpp
@@ -86,7 +86,7 @@ Screen_EoB::Screen_EoB(EoBCoreEngine *vm, OSystem *system) : Screen(vm, system,
 	_gfxX = _gfxY = 0;
 	_gfxCol = 0;
 	_dsTempPage = 0;
-	_shpBuffer = _convertHiColorBuffer = 0;
+	_shpBuffer = _hiColorConvertBuffer = 0;
 	_dsDiv = 0;
 	_dsRem = 0;
 	_dsScaleTrans = 0;
@@ -113,7 +113,7 @@ Screen_EoB::Screen_EoB(EoBCoreEngine *vm, OSystem *system) : Screen(vm, system,
 Screen_EoB::~Screen_EoB() {
 	delete[] _dsTempPage;
 	delete[] _shpBuffer;
-	delete[] _convertHiColorBuffer;
+	delete[] _hiColorConvertBuffer;
 	delete[] _cgaScaleTable;
 	delete[] _egaDitheringTable;
 	delete[] _egaDitheringTempPage;
@@ -135,7 +135,7 @@ bool Screen_EoB::init() {
 
 		if (_vm->gameFlags().platform == Common::kPlatformFMTowns) {
 			_shpBuffer = new uint8[SCREEN_H * SCREEN_W];
-			_convertHiColorBuffer = new uint8[SCREEN_H * SCREEN_W];
+			_hiColorConvertBuffer = new uint8[SCREEN_H * SCREEN_W];
 			enableHiColorMode(true);
 			setFontStyles(FID_SJIS_FNT, Font::kStyleFat);
 			_fonts[FID_SJIS_LARGE_FNT] = new SJISFontLarge(_sjisFontShared);
@@ -172,7 +172,7 @@ bool Screen_EoB::init() {
 			sega_setTextBuffer(0, 0);
 		}
 
-		_useShapeShading = (_bytesPerPixel != 2 && !_isAmiga && !_isSegaCD && !_use16ColorMode && _renderMode != Common::kRenderCGA && _renderMode != Common::kRenderEGA) || _useHiResEGADithering;
+		_useShapeShading = (_internalBytesPerPixel != 2 && !_isAmiga && !_isSegaCD && !_use16ColorMode && _renderMode != Common::kRenderCGA && _renderMode != Common::kRenderEGA) || _useHiResEGADithering;
 
 		static const char *cpsExt[] = { "CPS", "EGA", "SHP", "BIN" };
 		int ci = 0;
@@ -229,14 +229,14 @@ void Screen_EoB::setMouseCursor(int x, int y, const byte *shape, const uint8 *ov
 
 	int mouseW = (shape[2] << 3);
 	int mouseH = (shape[3]);
-	int colorKey = (_renderMode == Common::kRenderCGA) ? 0 : (_bytesPerPixel == 2 ? _cursorColorKey16Bit : _cursorColorKey);
+	int colorKey = (_renderMode == Common::kRenderCGA) ? 0 : (_internalBytesPerPixel == 2 ? _cursorColorKey16Bit : _cursorColorKey);
 
 	int scaleFactor = _vm->gameFlags().useHiRes ? 2 : 1;
 	int bpp = _useHiColorScreen ? 2 : 1;
 
 	uint8 *cursor = new uint8[mouseW * scaleFactor * bpp * mouseH * scaleFactor];
 
-	if (_bytesPerPixel == 2) {
+	if (_internalBytesPerPixel == 2) {
 		for (int s = mouseW * scaleFactor * bpp * mouseH * scaleFactor; s; s -= 2)
 			*(uint16*)(cursor + s - 2) = colorKey;
 	} else {
@@ -289,7 +289,7 @@ void Screen_EoB::setMouseCursor(int x, int y, const byte *shape, const uint8 *ov
 
 	// Convert color key to 16 bit after drawing the mouse cursor.
 	// The cursor has been converted to 16 bit in scale2x().
-	colorKey = _16bitConversionPalette ? _16bitConversionPalette[colorKey] : colorKey;
+	colorKey = _hiColorConversionPalette ? _hiColorConversionPalette[colorKey] : colorKey;
 	Graphics::PixelFormat pixelFormat = _system->getScreenFormat();
 
 	CursorMan.replaceCursor(cursor, mouseW * scaleFactor, mouseH * scaleFactor, x * scaleFactor, y * scaleFactor, colorKey, &pixelFormat);
@@ -505,7 +505,7 @@ void Screen_EoB::loadEoBBitmap(const char *file, const uint8 *cgaMapping, int te
 	if (convertToPage == -1)
 		return;
 
-	if (_16bitPalette)
+	if (_hiColorNativePalettes)
 		convertToHiColor(destPage);
 
 	if (convertToPage == 2 && _renderMode == Common::kRenderCGA) {
@@ -551,9 +551,17 @@ void Screen_EoB::convertPage(int srcPage, int dstPage, const uint8 *cgaMapping)
 }
 
 void Screen_EoB::setScreenPalette(const Palette &pal) {
-	if (_bytesPerPixel == 2) {
+	if (_internalBytesPerPixel == 2) {
+		assert(_hiColorNativePalettes);
 		for (int i = 0; i < 4; i++)
-			createFadeTable16bit((const uint16*)(pal.getData()), &_16bitPalette[i * 256], 0, i * 85);
+			createHiColorFadeTable((const uint16 *)(pal.getData()), &_hiColorNativePalettes[i << 8], 0, i * 85);
+	} else if (_outputPixelFormat.bytesPerPixel > 1) {
+		assert(_hiColorConversionPalette);
+		_screenPalette->copy(pal);
+		for (int i = 0; i < pal.getNumColors(); ++i)
+			_hiColorConversionPalette[i] = _outputPixelFormat.RGBToColor(pal[i * 3] * 0xFF / 0x3F, pal[i * 3 + 1] * 0xFF / 0x3F, pal[i * 3 + 2] * 0xFF / 0x3F);
+		// The whole Surface has to be converted again after each palette change
+		_forceFullUpdate = true;
 	} else if (_useHiResEGADithering && pal.getNumColors() != 16) {
 		generateEGADitheringTable(pal);
 	} else if (_isSegaCD || (_renderMode == Common::kRenderEGA && pal.getNumColors() == 16)) {
@@ -590,7 +598,7 @@ uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool enco
 	if (_use16ColorMode || (_renderMode == Common::kRenderEGA && !_useHiResEGADithering))
 		encode8bit = false;
 
-	if (_bytesPerPixel == 2 && encode8bit) {
+	if (_internalBytesPerPixel == 2 && encode8bit) {
 		shapesize = h * (w << 3) + 4;
 		shp = new uint8[shapesize]();
 		uint8 *dst = shp;
@@ -812,18 +820,18 @@ void Screen_EoB::drawT1Shape(uint8 pageNum, const byte *t1data, int x, int y, in
 		addDirtyRect(rX, rY, rW, rH);
 
 	int dH = rH;
-	uint8 *dstL = getPagePtr(pageNum) + rY * _bytesPerPixel * SCREEN_W;
+	uint8 *dstL = getPagePtr(pageNum) + rY * _internalBytesPerPixel * SCREEN_W;
 	src += dY * width;
 
 	while (dH--) {
 		const uint8 *src2 = src + dX;
-		uint8 *dst = dstL + rX * _bytesPerPixel;
+		uint8 *dst = dstL + rX * _internalBytesPerPixel;
 
-		for (int i = 0; i < rW; i++, src2++, dst += _bytesPerPixel)
+		for (int i = 0; i < rW; i++, src2++, dst += _internalBytesPerPixel)
 			if (*src2)
 				drawShapeSetPixel(dst, *src2);
 
-		dstL += SCREEN_W * _bytesPerPixel;
+		dstL += SCREEN_W * _internalBytesPerPixel;
 		src += width;
 	}
 }
@@ -852,7 +860,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,
 	}
 	va_end(args);
 
-	dst += (_dsX1 << (2 + _bytesPerPixel));
+	dst += (_dsX1 << (2 + _internalBytesPerPixel));
 	int16 dX = x - (_dsX1 << 3);
 	int16 dY = y;
 	int16 dW = _dsX2 - _dsX1;
@@ -924,7 +932,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,
 			marginRight = w2 - marginLeft - width;
 		}
 
-		dst += (dY * SCREEN_W * _bytesPerPixel + dX * _bytesPerPixel);
+		dst += (dY * SCREEN_W * _internalBytesPerPixel + dX * _internalBytesPerPixel);
 		uint8 *dstL = dst;
 
 		if (pageNum == 0 || pageNum == 1)
@@ -972,7 +980,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,
 				}
 			}
 
-			dst -= xpos * _bytesPerPixel;
+			dst -= xpos * _internalBytesPerPixel;
 			xpos += width;
 
 			while (xpos > 0) {
@@ -982,15 +990,15 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,
 
 				if (m) {
 					drawShapeSetPixel(dst, c);
-					dst += _bytesPerPixel;
+					dst += _internalBytesPerPixel;
 					xpos--;
 				} else if (pixelsPerByte) {
 					uint8 len = (flags & 1) ? src[1] : src[0];
-					dst += len * _bytesPerPixel;
+					dst += len * _internalBytesPerPixel;
 					xpos -= len;
 					src += pixelStep;
 				} else {
-					dst += _bytesPerPixel;
+					dst += _internalBytesPerPixel;
 					xpos--;
 				}
 			}
@@ -1020,7 +1028,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,
 				} while (xpos > 0);
 			}
 
-			dstL += SCREEN_W * _bytesPerPixel;
+			dstL += SCREEN_W * _internalBytesPerPixel;
 			dst = dstL;
 			if (flags & 1)
 				src = src2 + 1;
@@ -1088,7 +1096,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,
 		if (d < width)
 			width = d;
 
-		dst += (dY * SCREEN_W * _bytesPerPixel + dX * _bytesPerPixel);
+		dst += (dY * SCREEN_W * _internalBytesPerPixel + dX * _internalBytesPerPixel);
 
 		if (pageNum == 0 || pageNum == 1)
 			addDirtyRect(rX, rY, rW, rH);
@@ -1137,11 +1145,11 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,
 				uint8 col = (pixelsPerByte == 2) ? pal[(in >> shift) & pixelPackingMask] : (*dst & ((trans >> shift) & (pixelPackingMask))) | pal[(in >> shift) & pixelPackingMask];
 				if (col || pixelsPerByte == 4)
 					drawShapeSetPixel(dst, col);
-				dst += _bytesPerPixel;
+				dst += _internalBytesPerPixel;
 				shift = ((shift - (pixelStep * pixelPacking)) & 7);
 			}
 			src += lineSrcStep;
-			dst += (pitch * _bytesPerPixel);
+			dst += (pitch * _internalBytesPerPixel);
 		}
 	}
 }
@@ -1220,7 +1228,7 @@ const uint8 *Screen_EoB::generateShapeOverlay(const uint8 *shp, const uint8 *fad
 	if (*shp != 2)
 		return 0;
 
-	if (_bytesPerPixel == 2) {
+	if (_internalBytesPerPixel == 2) {
 		setFadeTable(fadingTable);
 		setShapeFadingLevel(1);
 		return 0;
@@ -1307,7 +1315,7 @@ void Screen_EoB::drawExplosion(int scale, int radius, int numElements, int stepS
 				if (py > ymax)
 					py = ymax;
 				if (posWithinRect(px, py, rX1, rY1, rX2, rY2)) {
-					if (_bytesPerPixel == 2)
+					if (_internalBytesPerPixel == 2)
 						setPagePixel16bit(0, px, py, ptr6[i]);
 					else
 						setPagePixel(0, px, py, ptr6[i]);
@@ -1464,7 +1472,7 @@ void Screen_EoB::drawVortex(int numElements, int radius, int stepSize, int, int
 			for (int ii = numElements - 1; ii >= 0; ii--) {
 				int16 px = CLIP((xCoords[ii] >> 6) + cx, 0, SCREEN_W - 1);
 				int16 py = CLIP((yCoords[ii] >> 6) + cy, 0, SCREEN_H - 1);
-				if (_bytesPerPixel == 2)
+				if (_internalBytesPerPixel == 2)
 					setPagePixel16bit(0, px, py, pixBackup[ii]);
 				else
 					setPagePixel(0, px, py, pixBackup[ii]);
@@ -1609,11 +1617,11 @@ int Screen_EoB::getRectSize(int w, int h) {
 
 void Screen_EoB::setFadeTable(const uint8 *table) {
 	_dsShapeFadingTable = table;
-	if (_bytesPerPixel == 2)
-		memcpy(&_16bitPalette[0x100], table, 512);
+	if (_internalBytesPerPixel == 2)
+		memcpy(&_hiColorNativePalettes[0x100], table, 512);
 }
 
-void Screen_EoB::createFadeTable(const uint8 *palData, uint8 *dst, uint8 rootColor, uint8 weight) {
+void Screen_EoB::createColorFadeTable(const uint8 *palData, uint8 *dst, uint8 rootColor, uint8 weight) {
 	if (!palData)
 		return;
 
@@ -1627,7 +1635,7 @@ void Screen_EoB::createFadeTable(const uint8 *palData, uint8 *dst, uint8 rootCol
 	*dst++ = 0;
 	weight >>= 1;
 
-	for (uint8 i = 1; i; i++) {
+	for (int i = 1; i < 256; ++i) {
 		uint16 tmp = (uint16)((*src - r) * weight) << 1;
 		tr = *src++ - ((tmp >> 8) & 0xFF);
 		tmp = (uint16)((*src - g) * weight) << 1;
@@ -1639,7 +1647,7 @@ void Screen_EoB::createFadeTable(const uint8 *palData, uint8 *dst, uint8 rootCol
 		uint16 v = 0xFFFF;
 		uint8 col = rootColor;
 
-		for (uint8 ii = 1; ii; ii++) {
+		for (int ii = 1; ii < 256; ++ii) {
 			int a = *d++ - tr;
 			int t = a * a;
 			a = *d++ - tg;
@@ -1656,26 +1664,24 @@ void Screen_EoB::createFadeTable(const uint8 *palData, uint8 *dst, uint8 rootCol
 	}
 }
 
-void Screen_EoB::createFadeTable16bit(const uint16 *palData, uint16 *dst, uint16 rootColor, uint8 weight) {
-	rootColor = palData[rootColor];
-	uint8 r8 = (rootColor & 0x1f);
-	uint8 g8 = (rootColor & 0x3E0) >> 5;
-	uint8 b8 = (rootColor & 0x7C00) >> 10;
+void Screen_EoB::createHiColorFadeTable(const uint16 *palData, uint16 *dst, uint8 rootColor, uint8 weight) {
+	const Graphics::PixelFormat originalFormat(2, 5, 5, 5, 0, 5, 10, 0, 0);
+	uint8 r = 0, b = 0, g = 0;
+	originalFormat.colorToRGB(palData[rootColor], r, g, b);
 
-	int root_r = r8 << 4;
-	int root_g = g8 << 4;
-	int root_b = b8 << 4;
+	int root_r = r << 1;
+	int root_g = g << 1;
+	int root_b = b << 1;
 
-	*dst++ = palData[0];
+	originalFormat.colorToRGB(palData[0], r, g, b);
+	*dst++ = _outputPixelFormat.RGBToColor(r, g, b);
 
-	for (uint8 i = 1; i; i++) {
-		r8 = (palData[i] & 0x1f);
-		g8 = (palData[i] & 0x3E0) >> 5;
-		b8 = (palData[i] & 0x7C00) >> 10;
+	for (int i = 1; i < 256; ++i) {
+		originalFormat.colorToRGB(palData[i], r, g, b);
 
-		int red = r8 << 4;
-		int green = g8 << 4;
-		int blue = b8 << 4;
+		int red = r << 1;
+		int green = g << 1;
+		int blue = b << 1;
 
 		if (red > root_r) {
 			red -= weight;
@@ -1707,11 +1713,11 @@ void Screen_EoB::createFadeTable16bit(const uint16 *palData, uint16 *dst, uint16
 				blue = root_b;
 		}
 
-		r8 = red >> 4;
-		g8 = green >> 4;
-		b8 = blue >> 4;
+		r = red >> 1;
+		g = green >> 1;
+		b = blue >> 1;
 
-		*dst++ = (b8 << 10) | (g8 << 5) | r8;
+		*dst++ = _outputPixelFormat.RGBToColor(r, g, b);
 	}
 }
 
@@ -1824,8 +1830,8 @@ void Screen_EoB::ditherRect(const uint8 *src, uint8 *dst, int dstPitch, int srcW
 }
 
 void Screen_EoB::drawShapeSetPixel(uint8 *dst, uint8 col) {
-	if (_bytesPerPixel == 2) {
-		*(uint16*)dst = _16bitPalette[(_dsShapeFadingLevel << 8) + col];
+	if (_internalBytesPerPixel == 2) {
+		*(uint16*)dst = _hiColorNativePalettes[(_dsShapeFadingLevel << 8) + col];
 		return;
 	} else if (_useShapeShading) {
 		if (_dsBackgroundFading) {
@@ -1904,7 +1910,7 @@ bool Screen_EoB::posWithinRect(int posX, int posY, int x1, int y1, int x2, int y
 void Screen_EoB::setPagePixel16bit(int pageNum, int x, int y, uint16 color) {
 	assert(pageNum < SCREEN_PAGE_NUM);
 	assert(x >= 0 && x < SCREEN_W && y >= 0 && y < SCREEN_H);
-	assert(_bytesPerPixel == 2);
+	assert(_internalBytesPerPixel == 2);
 
 	if (pageNum == 0 || pageNum == 1)
 		addDirtyRect(x, y, 1, 1);
diff --git a/engines/kyra/graphics/screen_eob.h b/engines/kyra/graphics/screen_eob.h
index d5f242b0d96..149fa3b50c1 100644
--- a/engines/kyra/graphics/screen_eob.h
+++ b/engines/kyra/graphics/screen_eob.h
@@ -102,8 +102,8 @@ public:
 	int getRectSize(int w, int h) override;
 
 	void setFadeTable(const uint8 *table);
-	void createFadeTable(const uint8 *palData, uint8 *dst, uint8 rootColor, uint8 weight);
-	void createFadeTable16bit(const uint16 *palData, uint16 *dst, uint16 rootColor, uint8 weight);
+	void createColorFadeTable(const uint8 *palData, uint8 *dst, uint8 rootColor, uint8 weight);
+	void createHiColorFadeTable(const uint16 *palData, uint16 *dst, uint8 rootColor, uint8 weight);
 
 	const uint16 *getCGADitheringTable(int index);
 	const uint8 *getEGADitheringTable();
@@ -189,7 +189,7 @@ private:
 
 	uint8 *_dsTempPage;
 	uint8 *_shpBuffer;
-	uint8 *_convertHiColorBuffer;
+	uint8 *_hiColorConvertBuffer;
 
 	uint16 *_cgaDitheringTables[2];
 	const uint8 *_cgaMappingDefault;
diff --git a/engines/kyra/graphics/screen_eob_towns.cpp b/engines/kyra/graphics/screen_eob_towns.cpp
index a69616c1b93..56cd06e00df 100644
--- a/engines/kyra/graphics/screen_eob_towns.cpp
+++ b/engines/kyra/graphics/screen_eob_towns.cpp
@@ -62,37 +62,37 @@ void Screen_EoB::decodeSHP(const uint8 *data, int dstPage) {
 }
 
 void Screen_EoB::convertToHiColor(int page) {
-	if (!_16bitPalette)
+	if (!_hiColorNativePalettes)
 		return;
 	uint16 *dst = (uint16 *)getPagePtr(page);
-	memcpy(_convertHiColorBuffer, dst, SCREEN_H * SCREEN_W);
-	uint8 *src = _convertHiColorBuffer;
+	memcpy(_hiColorConvertBuffer, dst, SCREEN_H * SCREEN_W);
+	const uint8 *src = _hiColorConvertBuffer;
 	for (int s = SCREEN_H * SCREEN_W; s; --s)
-		*dst++ = _16bitPalette[*src++];
+		*dst++ = _hiColorNativePalettes[*src++];
 }
 
 void Screen_EoB::shadeRect(int x1, int y1, int x2, int y2, int shadingLevel) {
-	if (!_16bitPalette)
+	if (!_hiColorNativePalettes)
 		return;
 
-	int l = _16bitShadingLevel;
-	_16bitShadingLevel = shadingLevel;
+	int l = _hiColorShadingLevel;
+	_hiColorShadingLevel = shadingLevel;
 
 	if (_curPage == 0 || _curPage == 1)
 		addDirtyRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
 
-	uint16 *dst = (uint16*)(getPagePtr(_curPage) + y1 * SCREEN_W * _bytesPerPixel + x1 * _bytesPerPixel);
+	uint16 *dst = (uint16*)(getPagePtr(_curPage) + y1 * SCREEN_W * _internalBytesPerPixel + x1 * _internalBytesPerPixel);
 
 	for (; y1 < y2; ++y1) {
 		uint16 *ptr = dst;
 		for (int i = 0; i < x2 - x1; i++) {
-			*ptr = shade16bitColor(*ptr);
+			*ptr = shadeRGBColor(*ptr);
 			ptr++;
 		}
 		dst += SCREEN_W;
 	}
 
-	_16bitShadingLevel = l;
+	_hiColorShadingLevel = l;
 }
 
 SJISFontLarge::SJISFontLarge(Common::SharedPtr<Graphics::FontSJIS> &font) : SJISFont(font, 0, false, false, 0) {
diff --git a/engines/kyra/sequence/sequences_darkmoon.cpp b/engines/kyra/sequence/sequences_darkmoon.cpp
index 7690bd9f92c..64a2b7975e2 100644
--- a/engines/kyra/sequence/sequences_darkmoon.cpp
+++ b/engines/kyra/sequence/sequences_darkmoon.cpp
@@ -1844,7 +1844,7 @@ void DarkmoonSequenceHelper::init(DarkmoonSequenceHelper::Mode mode) {
 		if (_vm->_flags.platform != Common::kPlatformAmiga && _vm->_configRenderMode != Common::kRenderCGA && _vm->_configRenderMode != Common::kRenderEGA) {
 			uint8 *pal = _vm->resource()->fileData("PALETTE1.PAL", 0);
 			for (int i = 0; i < 7; i++)
-				_screen->createFadeTable(pal, _fadingTables[i], 18, (i + 1) * 36);
+				_screen->createColorFadeTable(pal, _fadingTables[i], 18, (i + 1) * 36);
 			delete[] pal;
 		}
 	}


Commit: 1d3be6bf55be922abf6be0d6529a442c8c8e64fe
    https://github.com/scummvm/scummvm/commit/1d3be6bf55be922abf6be0d6529a442c8c8e64fe
Author: athrxx (athrxx at scummvm.org)
Date: 2026-07-11T18:45:32+02:00

Commit Message:
KYRA: (EOBII/FM-TOWNS) - allow 32bit graphics modes

Instead of trying to enforce a 16 bit mode the game will now run in the
backend's default mode, as long as this is either a 16 or a 32 bit mode.

Changed paths:
    engines/kyra/engine/darkmoon.cpp
    engines/kyra/engine/eobcommon.cpp
    engines/kyra/engine/items_eob.cpp
    engines/kyra/engine/kyra_rpg.cpp
    engines/kyra/engine/kyra_rpg.h
    engines/kyra/engine/scene_eob.cpp
    engines/kyra/engine/scene_rpg.cpp
    engines/kyra/graphics/screen.cpp
    engines/kyra/graphics/screen.h
    engines/kyra/graphics/screen_eob.cpp
    engines/kyra/graphics/screen_eob.h
    engines/kyra/graphics/screen_eob_towns.cpp


diff --git a/engines/kyra/engine/darkmoon.cpp b/engines/kyra/engine/darkmoon.cpp
index 77db9472b8e..89f7bb13583 100644
--- a/engines/kyra/engine/darkmoon.cpp
+++ b/engines/kyra/engine/darkmoon.cpp
@@ -258,6 +258,8 @@ uint8 *DarkMoonEngine::loadFMTownsShape(Common::SeekableReadStream *stream) {
 void DarkMoonEngine::generateMonsterPalettes(const char *file, int16 monsterIndex) {
 	if (_flags.platform == Common::kPlatformAmiga)
 		return;
+	// EOB II FM-TOWNS version will also never arrive here, see DarkMoonEngine::loadMonsterShapes().
+	// So there is no need to worry about how the following code could ever work in hicolor mode.
 
 	int cp = _screen->setCurPage(2);
 	_screen->loadShapeSetBitmap(file, 3, 3);
diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp
index fd7386a17ec..cff470ec13f 100644
--- a/engines/kyra/engine/eobcommon.cpp
+++ b/engines/kyra/engine/eobcommon.cpp
@@ -523,13 +523,14 @@ Common::Error EoBCoreEngine::init() {
 	memset(&_wllShapeMap[13], -1, 5);
 
 	_wllVcnOffset = (_flags.platform == Common::kPlatformFMTowns) ? 0 : 16;
-	int bpp = (_flags.platform == Common::kPlatformFMTowns) ? 2 : 1;
-
-	_greenFadingTable = new uint8[256 * bpp];
-	_blueFadingTable = new uint8[256 * bpp];
-	_lightBlueFadingTable = new uint8[256 * bpp];
-	_blackFadingTable = new uint8[256 * bpp];
-	_greyFadingTable = new uint8[256 * bpp];
+	int bpp = _screen->bytesPerPixel();
+	setVcnFormat(bpp);
+
+	_greenFadingTable = new uint8[256 * bpp]();
+	_blueFadingTable = new uint8[256 * bpp]();
+	_lightBlueFadingTable = new uint8[256 * bpp]();
+	_blackFadingTable = new uint8[256 * bpp]();
+	_greyFadingTable = new uint8[256 * bpp]();
 
 	_monsters = new EoBMonsterInPlay[30]();
 
diff --git a/engines/kyra/engine/items_eob.cpp b/engines/kyra/engine/items_eob.cpp
index 9795558822c..65c2f6bc019 100644
--- a/engines/kyra/engine/items_eob.cpp
+++ b/engines/kyra/engine/items_eob.cpp
@@ -773,7 +773,7 @@ void EoBCoreEngine::explodeObject(EoBFlyingObject *fo, int block, Item item) {
 		fo->enable = 2;
 
 	_screen->fillRect(0, 0, 176, 120, 0, 2);
-	uint8 col = _screen->getPagePixel(2, 0, 0);
+	int col = _screen->getPagePixel(2, 0, 0);
 	drawSceneShapes(_expObjectShpStart[dm]);
 
 	setLevelShapesDim(tl, x1, x2, 5);
diff --git a/engines/kyra/engine/kyra_rpg.cpp b/engines/kyra/engine/kyra_rpg.cpp
index 785822ddd6b..7d2f5ea4d02 100644
--- a/engines/kyra/engine/kyra_rpg.cpp
+++ b/engines/kyra/engine/kyra_rpg.cpp
@@ -50,9 +50,9 @@ KyraRpgEngine::KyraRpgEngine(OSystem *system, const GameFlags &flags) : KyraEngi
 	_vcnShift = 0;
 	_vcnColTable = 0;
 	_vcnShiftVal = 0;
-	_vcnBpp = flags.useHiColorMode ? 2 : 1;
-	_vcnSrcBitsPerPixel = (flags.platform == Common::kPlatformAmiga) ? 5 : (_vcnBpp == 2 ? 8 : 4);
-	_vcnDrawLine = 0;
+	_vcnBpp = 1;
+	_vcnSrcBitsPerPixel = (_flags.platform == Common::kPlatformAmiga) ? 5 : (_flags.platform == Common::kPlatformFMTowns ? 8 : 4);
+	_vcnDrawLine = nullptr;
 	_vmpVisOffs = (flags.platform == Common::kPlatformSegaCD) ? _vmpOffsetsSegaCD : _vmpOffsetsDefault;
 
 	_vmpPtr = 0;
@@ -193,8 +193,7 @@ Common::Error KyraRpgEngine::init() {
 	_wllWallFlags = new uint8[256]();
 
 	_blockDrawingBuffer = new uint16[1320]();
-	int windowBufferSize = _flags.useHiColorMode ? 42240 : 21120;
-	_sceneWindowBuffer = new uint8[windowBufferSize]();
+	_sceneWindowBuffer = nullptr;
 
 	_lvlShapeTop = new int16[18]();
 	_lvlShapeBottom = new int16[18]();
@@ -204,15 +203,7 @@ Common::Error KyraRpgEngine::init() {
 	for (int i = 0; i < 128; i++)
 		_vcnColTable[i] = i & 0x0F;
 
-	if (_vcnBpp == 2)
-		_vcnDrawLine = new VcnLineDrawingMethods(new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_fw_hiCol), new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_bw_hiCol),
-			new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_fw_trans_hiCol), new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_bw_trans_hiCol));
-	else if (_flags.platform == Common::kPlatformAmiga || (_flags.gameID == GI_EOB1 && _flags.use16ColorMode))
-		_vcnDrawLine = new VcnLineDrawingMethods(new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_fw_planar), new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_bw_planar),
-			new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_fw_trans_planar), new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_bw_trans_planar));
-	else
-		_vcnDrawLine = new VcnLineDrawingMethods(new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_fw_4bit), new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_bw_4bit),
-			new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_fw_trans_4bit), new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_bw_trans_4bit));
+	setVcnFormat(1);
 
 	_doorShapes = new uint8*[6]();
 
diff --git a/engines/kyra/engine/kyra_rpg.h b/engines/kyra/engine/kyra_rpg.h
index ab3bdb87dd4..b049dd6383e 100644
--- a/engines/kyra/engine/kyra_rpg.h
+++ b/engines/kyra/engine/kyra_rpg.h
@@ -315,15 +315,16 @@ protected:
 	bool checkSceneUpdateNeed(int block);
 	uint16 calcNewBlockPosition(uint16 curBlock, uint16 direction);
 
+	void setVcnFormat(int outputBPP);
 	void drawVcnBlocks();
 	void vcnDraw_fw_4bit(uint8 *&dst, const uint8 *&src);
 	void vcnDraw_bw_4bit(uint8 *&dst, const uint8 *&src);
 	void vcnDraw_fw_trans_4bit(uint8 *&dst, const uint8 *&src);
 	void vcnDraw_bw_trans_4bit(uint8 *&dst, const uint8 *&src);
-	void vcnDraw_fw_hiCol(uint8 *&dst, const uint8 *&src);
-	void vcnDraw_bw_hiCol(uint8 *&dst, const uint8 *&src);
-	void vcnDraw_fw_trans_hiCol(uint8 *&dst, const uint8 *&src);
-	void vcnDraw_bw_trans_hiCol(uint8 *&dst, const uint8 *&src);
+	template<typename T> void vcnDraw_fw_hiCol(uint8 *&dst, const uint8 *&src);
+	template<typename T> void vcnDraw_bw_hiCol(uint8 *&dst, const uint8 *&src);
+	template<typename T> void vcnDraw_fw_trans_hiCol(uint8 *&dst, const uint8 *&src);
+	template<typename T> void vcnDraw_bw_trans_hiCol(uint8 *&dst, const uint8 *&src);
 	void vcnDraw_fw_planar(uint8 *&dst, const uint8 *&src);
 	void vcnDraw_bw_planar(uint8 *&dst, const uint8 *&src);
 	void vcnDraw_fw_trans_planar(uint8 *&dst, const uint8 *&src);
diff --git a/engines/kyra/engine/scene_eob.cpp b/engines/kyra/engine/scene_eob.cpp
index 832c2231efa..fe87c29e5dd 100644
--- a/engines/kyra/engine/scene_eob.cpp
+++ b/engines/kyra/engine/scene_eob.cpp
@@ -205,24 +205,22 @@ Common::String EoBCoreEngine::initLevelData(int sub) {
 		setLevelPalettes(_currentLevel);
 
 		if (_flags.platform == Common::kPlatformFMTowns) {
-			uint16 *src = (uint16*)_screen->getPalette(0).getData();
-			_screen->createHiColorFadeTable(src, (uint16*)_greenFadingTable, 4, 75);
-			_screen->createHiColorFadeTable(src, (uint16*)_blackFadingTable, 12, 200);
-			_screen->createHiColorFadeTable(src, (uint16*)_blueFadingTable, 10, 85);
-			_screen->createHiColorFadeTable(src, (uint16*)_lightBlueFadingTable, 11, 125);
-			_screen->createHiColorFadeTable(src, (uint16*)_greyFadingTable, 0, 85);
+			const uint16 *src = reinterpret_cast<const uint16 *>(_screen->getPalette(0).getData());
+			_screen->createHiColorFadeTable(src, _greenFadingTable, 4, 75);
+			_screen->createHiColorFadeTable(src, _blackFadingTable, 12, 200);
+			_screen->createHiColorFadeTable(src, _blueFadingTable, 10, 85);
+			_screen->createHiColorFadeTable(src, _lightBlueFadingTable, 11, 125);
+			_screen->createHiColorFadeTable(src, _greyFadingTable, 0, 85);
 			_screen->setScreenPalette(_screen->getPalette(0));
 		} else if (_configRenderMode != Common::kRenderCGA && _flags.platform != Common::kPlatformAmiga && _flags.platform != Common::kPlatformSegaCD && !(_flags.gameID == GI_EOB1 && _flags.platform == Common::kPlatformPC98)) {
 			Palette backupPal(256);
 			backupPal.copy(_screen->getPalette(0), 224, 32, 224);
 			_screen->getPalette(0).fill(224, 32, 0x3F);
 			uint8 *src = _screen->getPalette(0).getData();
-
 			_screen->createColorFadeTable(src, _greenFadingTable, 4, 75);
 			_screen->createColorFadeTable(src, _blackFadingTable, 12, 200);
 			_screen->createColorFadeTable(src, _blueFadingTable, 10, 85);
 			_screen->createColorFadeTable(src, _lightBlueFadingTable, 11, 125);
-
 			_screen->getPalette(0).copy(backupPal, 224, 32, 224);
 			_screen->createColorFadeTable(src, _greyFadingTable, 12, 85);
 			_screen->setFadeTable(_greyFadingTable);
@@ -634,8 +632,8 @@ void EoBCoreEngine::drawSceneShapes(int start, int end, int drawFlags) {
 		if (_shpDmX2 <= _shpDmX1)
 			continue;
 
-		//if (drawFlags & 0x01)
-			//drawDecorations(t);
+		if (drawFlags & 0x01)
+			drawDecorations(t);
 
 		if ((drawFlags & 0x02) && _visibleBlocks[t]->drawObjects)
 			drawBlockItems(t);
diff --git a/engines/kyra/engine/scene_rpg.cpp b/engines/kyra/engine/scene_rpg.cpp
index 5a99bd09f04..58437e132eb 100644
--- a/engines/kyra/engine/scene_rpg.cpp
+++ b/engines/kyra/engine/scene_rpg.cpp
@@ -344,6 +344,28 @@ uint16 KyraRpgEngine::calcNewBlockPosition(uint16 curBlock, uint16 direction) {
 	return (curBlock + blockPosTable[direction]) & 0x3FF;
 }
 
+void KyraRpgEngine::setVcnFormat(int outputBPP) {
+	_vcnBpp = outputBPP;
+
+	delete[] _sceneWindowBuffer;
+	_sceneWindowBuffer = new uint8[22 * 15 * 8 * 8 * _vcnBpp]();
+
+	delete _vcnDrawLine;
+
+	if (_vcnBpp == 4)
+		_vcnDrawLine = new VcnLineDrawingMethods(new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_fw_hiCol<uint32>), new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_bw_hiCol<uint32>),
+			new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_fw_trans_hiCol<uint32>), new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_bw_trans_hiCol<uint32>));
+	else if (_vcnBpp == 2)
+		_vcnDrawLine = new VcnLineDrawingMethods(new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_fw_hiCol<uint16>), new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_bw_hiCol<uint16>),
+			new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_fw_trans_hiCol<uint16>), new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_bw_trans_hiCol<uint16>));
+	else if (_flags.platform == Common::kPlatformAmiga || (_flags.gameID == GI_EOB1 && _flags.use16ColorMode))
+		_vcnDrawLine = new VcnLineDrawingMethods(new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_fw_planar), new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_bw_planar),
+			new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_fw_trans_planar), new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_bw_trans_planar));
+	else
+		_vcnDrawLine = new VcnLineDrawingMethods(new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_fw_4bit), new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_bw_4bit),
+			new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_fw_trans_4bit), new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_bw_trans_4bit));
+}
+
 void KyraRpgEngine::drawVcnBlocks() {
 	uint8 *d = _sceneWindowBuffer;
 	uint16 *bdb = _blockDrawingBuffer;
@@ -433,7 +455,7 @@ void KyraRpgEngine::vcnDraw_fw_4bit(uint8 *&dst, const uint8 *&src) {
 
 void KyraRpgEngine::vcnDraw_bw_4bit(uint8 *&dst, const uint8 *&src) {
 	src += 3;
-	for (int blockX = 0; blockX < 4 * _vcnBpp; blockX++) {
+	for (int blockX = 0; blockX < 4; blockX++) {
 		uint8 bl = *src--;
 		*dst++ = _vcnColTable[((bl & 0x0F) + _wllVcnOffset2) | _vcnShiftVal];
 		*dst++ = _vcnColTable[((bl >> 4) + _wllVcnOffset2) | _vcnShiftVal];
@@ -442,7 +464,7 @@ void KyraRpgEngine::vcnDraw_bw_4bit(uint8 *&dst, const uint8 *&src) {
 }
 
 void KyraRpgEngine::vcnDraw_fw_trans_4bit(uint8 *&dst, const uint8 *&src) {
-	for (int blockX = 0; blockX < _vcnSrcBitsPerPixel; blockX++) {
+	for (int blockX = 0; blockX < 4; blockX++) {
 		uint8 bl = *src++;
 		uint8 mask = _vcnTransitionMask ? *_vcnMaskTbl++ : 0;
 		uint8 h = _vcnColTable[((bl >> 4) + _wllVcnRmdOffset) | _vcnShiftVal];
@@ -465,7 +487,7 @@ void KyraRpgEngine::vcnDraw_fw_trans_4bit(uint8 *&dst, const uint8 *&src) {
 void KyraRpgEngine::vcnDraw_bw_trans_4bit(uint8 *&dst, const uint8 *&src) {
 	src += 3;
 	_vcnMaskTbl += 3;
-	for (int blockX = 0; blockX < _vcnSrcBitsPerPixel; blockX++) {
+	for (int blockX = 0; blockX < 4; blockX++) {
 		uint8 bl = *src--;
 		uint8 mask = _vcnTransitionMask ? *_vcnMaskTbl-- : 0;
 		uint8 h = _vcnColTable[((bl & 0x0F) + _wllVcnRmdOffset) | _vcnShiftVal];
@@ -487,46 +509,59 @@ void KyraRpgEngine::vcnDraw_bw_trans_4bit(uint8 *&dst, const uint8 *&src) {
 	_vcnMaskTbl += 5;
 }
 
-void KyraRpgEngine::vcnDraw_fw_hiCol(uint8 *&dst, const uint8 *&src) {
-	const uint16 *hiColorPal = screen()->get16bitPalette();
-	for (int blockX = 0; blockX < 8; blockX++) {
-		*(uint16*)dst = hiColorPal[*src++];
-		dst += 2;
-	}
+template<typename T> void KyraRpgEngine::vcnDraw_fw_hiCol(uint8 *&dst, const uint8 *&src) {
+	const T *hiColorPal = reinterpret_cast<const T*>(screen()->getHiColorPalette());
+	T *d = reinterpret_cast<T*>(dst);
+	for (int blockX = 0; blockX < _vcnSrcBitsPerPixel; blockX++)
+		*d++ = hiColorPal[*src++];
+	dst = reinterpret_cast<uint8*>(d);
 }
 
-void KyraRpgEngine::vcnDraw_bw_hiCol(uint8 *&dst, const uint8 *&src) {
+template<typename T> void KyraRpgEngine::vcnDraw_bw_hiCol(uint8 *&dst, const uint8 *&src) {
 	src += 7;
-	const uint16 *hiColorPal = screen()->get16bitPalette();
-	for (int blockX = 0; blockX < 4 * _vcnBpp; blockX++) {
-		*(uint16*)dst = hiColorPal[*src--];
-		dst += 2;
-	}
+	const T *hiColorPal = reinterpret_cast<const T*>(screen()->getHiColorPalette());
+	T *d = reinterpret_cast<T*>(dst);
+	for (int blockX = 0; blockX < _vcnSrcBitsPerPixel; blockX++)
+		*d++ = hiColorPal[*src--];
 	src += 9;
+	dst = reinterpret_cast<uint8*>(d);
 }
 
-void KyraRpgEngine::vcnDraw_fw_trans_hiCol(uint8 *&dst, const uint8 *&src) {
-	const uint16 *hiColorPal = screen()->get16bitPalette();
+template<typename T> void KyraRpgEngine::vcnDraw_fw_trans_hiCol(uint8 *&dst, const uint8 *&src) {
+	const T *hiColorPal = reinterpret_cast<const T*>(screen()->getHiColorPalette());
+	T *d = reinterpret_cast<T*>(dst);
 	for (int blockX = 0; blockX < _vcnSrcBitsPerPixel; blockX++) {
 		uint8 bl = *src++;
 		if (bl)
-			*(uint16*)dst = hiColorPal[bl];
-		dst += 2;
+			*d = hiColorPal[bl];
+		d++;
 	}
+	dst = reinterpret_cast<uint8*>(d);
 }
 
-void KyraRpgEngine::vcnDraw_bw_trans_hiCol(uint8 *&dst, const uint8 *&src) {
+template<typename T> void KyraRpgEngine::vcnDraw_bw_trans_hiCol(uint8 *&dst, const uint8 *&src) {
 	src += 7;
-	const uint16 *hiColorPal = screen()->get16bitPalette();
+	const T *hiColorPal = reinterpret_cast<const T*>(screen()->getHiColorPalette());
+	T *d = reinterpret_cast<T*>(dst);
 	for (int blockX = 0; blockX < _vcnSrcBitsPerPixel; blockX++) {
 		uint8 bl = *src--;
 		if (bl)
-			*(uint16*)dst = hiColorPal[bl];
-		dst += 2;
+			*d = hiColorPal[bl];
+		d++;
 	}
 	src += 9;
+	dst = reinterpret_cast<uint8*>(d);
 }
 
+template void KyraRpgEngine::vcnDraw_fw_hiCol<uint16>(uint8 *&dst, const uint8 *&src);
+template void KyraRpgEngine::vcnDraw_fw_hiCol<uint32>(uint8 *&dst, const uint8 *&src);
+template void KyraRpgEngine::vcnDraw_bw_hiCol<uint16>(uint8 *&dst, const uint8 *&src);
+template void KyraRpgEngine::vcnDraw_bw_hiCol<uint32>(uint8 *&dst, const uint8 *&src);
+template void KyraRpgEngine::vcnDraw_fw_trans_hiCol<uint16>(uint8 *&dst, const uint8 *&src);
+template void KyraRpgEngine::vcnDraw_fw_trans_hiCol<uint32>(uint8 *&dst, const uint8 *&src);
+template void KyraRpgEngine::vcnDraw_bw_trans_hiCol<uint16>(uint8 *&dst, const uint8 *&src);
+template void KyraRpgEngine::vcnDraw_bw_trans_hiCol<uint32>(uint8 *&dst, const uint8 *&src);
+
 void KyraRpgEngine::vcnDraw_fw_planar(uint8 *&dst, const uint8 *&src) {
 	for (int blockX = 0; blockX < 8; blockX++) {
 		uint8 col = 0;
diff --git a/engines/kyra/graphics/screen.cpp b/engines/kyra/graphics/screen.cpp
index 0a51e1d7556..fcc1315c813 100644
--- a/engines/kyra/graphics/screen.cpp
+++ b/engines/kyra/graphics/screen.cpp
@@ -23,6 +23,7 @@
 #include "kyra/kyra_v1.h"
 #include "kyra/resource/resource.h"
 
+#include "common/algorithm.h"
 #include "common/endian.h"
 #include "common/memstream.h"
 #include "common/system.h"
@@ -66,6 +67,11 @@ Screen::Screen(KyraEngine_v1 *vm, OSystem *system, const ScreenDim *dimTable, co
 	memset(_pageMapping, 0, sizeof(_pageMapping));
 	memset(_sjisOverlayPtrs, 0, sizeof(_sjisOverlayPtrs));
 
+	_mergeOverlayProc = nullptr;
+	_scale2xProc = nullptr;
+	_getPagePixelProc = nullptr;
+	_setPagePixelProc = nullptr;
+
 	_renderMode = Common::kRenderDefault;
 	_sjisMixedFontMode = false;
 
@@ -73,7 +79,6 @@ Screen::Screen(KyraEngine_v1 *vm, OSystem *system, const ScreenDim *dimTable, co
 	_animBlockPtr = _textRenderBuffer = nullptr;
 	_textRenderBufferSize = 0;
 
-	_useHiColorScreen = _vm->gameFlags().useHiColorMode;
 	_outputPixelFormat = Graphics::PixelFormat::createFormatCLUT8();
 	_useShapeShading = true;
 	_screenPageSize = SCREEN_PAGE_SIZE;
@@ -113,8 +118,8 @@ Screen::~Screen() {
 	delete _screenPalette;
 	delete _internFadePalette;
 	delete[] _animBlockPtr;
-	delete[] _hiColorNativePalettes;
-	delete[] _hiColorConversionPalette;
+	delete[] reinterpret_cast<uint8*>(_hiColorNativePalettes);
+	delete[] reinterpret_cast<uint8*>(_hiColorConversionPalette);
 
 	_sjisFontShared.reset();
 
@@ -128,6 +133,48 @@ Screen::~Screen() {
 	}
 }
 
+template void Screen::mergeOverlayImpl<uint8>(int x, int y, int w, int h);
+template void Screen::mergeOverlayImpl<uint16>(int x, int y, int w, int h);
+template void Screen::mergeOverlayImpl<uint32>(int x, int y, int w, int h);
+template void Screen::setPagePixelImpl<uint8>(int pageNum, int x, int y, uint8 color);
+template void Screen::setPagePixelImpl<uint16>(int pageNum, int x, int y, uint8 color);
+template void Screen::setPagePixelImpl<uint32>(int pageNum, int x, int y, uint8 color);
+template int Screen::getPagePixelImpl<uint8>(int pageNum, int x, int y);
+template int Screen::getPagePixelImpl<uint16>(int pageNum, int x, int y);
+template int Screen::getPagePixelImpl<uint32>(int pageNum, int x, int y);
+template void Screen::scale2x<uint8, uint8>(uint8 *dst, int dstPitch, const uint8 *src, int srcPitch, int w, int h);
+template void Screen::scale2x<uint16, uint16>(uint8 *dst, int dstPitch, const uint8 *src, int srcPitch, int w, int h);
+template void Screen::scale2x<uint32, uint32>(uint8 *dst, int dstPitch, const uint8 *src, int srcPitch, int w, int h);
+template void Screen::scale2x<uint8, uint16>(uint8 *dst, int dstPitch, const uint8 *src, int srcPitch, int w, int h);
+template void Screen::scale2x<uint8, uint32>(uint8 *dst, int dstPitch, const uint8 *src, int srcPitch, int w, int h);
+
+const Screen::MergeOverlayFunc Screen::_mergeOverlayProcs[] = {
+	&Screen::mergeOverlayImpl<uint8>,
+	&Screen::mergeOverlayImpl<uint16>,
+	&Screen::mergeOverlayImpl<uint32>};
+
+const Screen::Scale2xFunc Screen::_scale2xProcs[] = {
+	&Screen::scale2x<uint8, uint8>,
+	&Screen::scale2x<uint8, uint16>,
+	&Screen::scale2x<uint8, uint32>,
+	&Screen::scale2x<uint16, uint16>,
+	nullptr,
+	nullptr,
+	&Screen::scale2x<uint32, uint32>,
+};
+
+const Screen::GetPagePixelProc Screen::_getPagePixelProcs[] = {
+	&Screen::getPagePixelImpl<uint8>,
+	&Screen::getPagePixelImpl<uint16>,
+	&Screen::getPagePixelImpl<uint32>
+};
+
+const Screen::SetPagePixelProc Screen::_setPagePixelProcs[] = {
+	&Screen::setPagePixelImpl<uint8>,
+	&Screen::setPagePixelImpl<uint16>,
+	&Screen::setPagePixelImpl<uint32>
+};
+
 bool Screen::init() {
 	_debugEnabled = false;
 	_useOverlays = false;
@@ -180,13 +227,13 @@ bool Screen::init() {
 		_sjisMixedFontMode = !_use16ColorMode;
 
 		if (!_sjisOverlayPtrs[0]) {
-			// We alway assume 2 bytes per pixel here when the backend is in hicolor mode, since this is the surface that is passed to the backend.
+			// We use the number of bytes per pixel here when the backend is in hicolor mode, since this is the surface that is passed to the backend.
 			// We do this regardsless of the paramater sent to enableHiColorMode() so as not to have to change the backend color mode.
-			// Conversions from 8bit to 16bit have to take place when copying data to this surface here.
-			int bpp = _useHiColorScreen ? 2 : 1;
-			_sjisOverlayPtrs[0] = new uint8[SCREEN_OVL_SJIS_SIZE * bpp];
+			// Conversions from 8bit to the actual bpp have to take place when copying data to this surface here.
+			assert(_outputPixelFormat.bytesPerPixel > 0);
+			_sjisOverlayPtrs[0] = new uint8[SCREEN_OVL_SJIS_SIZE * _outputPixelFormat.bytesPerPixel];
 			assert(_sjisOverlayPtrs[0]);
-			memset(_sjisOverlayPtrs[0], _sjisInvisibleColor, SCREEN_OVL_SJIS_SIZE * bpp);
+			memset(_sjisOverlayPtrs[0], _sjisInvisibleColor, SCREEN_OVL_SJIS_SIZE * _outputPixelFormat.bytesPerPixel);
 		}
 
 		for (int i = 1; i < SCREEN_OVLS_NUM; ++i) {
@@ -209,6 +256,9 @@ bool Screen::init() {
 			else if (_vm->gameFlags().platform != Common::kPlatformPC98 || _vm->game() != GI_EOB2)
 				_fonts[FID_SJIS_FNT] = new SJISFont(_sjisFontShared, _sjisInvisibleColor, false, _vm->game() != GI_LOL && _vm->game() != GI_EOB2, _vm->game() == GI_LOL ? 1 : 0);
 		}
+
+		assert((_outputPixelFormat.bytesPerPixel >> 1) < ARRAYSIZE(_mergeOverlayProcs));
+		_mergeOverlayProc = _mergeOverlayProcs[_outputPixelFormat.bytesPerPixel >> 1];
 	}
 
 	_curPage = 0;
@@ -272,7 +322,7 @@ bool Screen::init() {
 	_overdrawMargin = (_vm->game() == GI_EOB2 && _vm->gameFlags().lang == Common::ZH_TWN);
 	for (int i = 0; i < ARRAYSIZE(_textColorsMap); ++i)
 		_textColorsMap[i] = i;
-	_textColorsMap16bit[0] = _textColorsMap16bit[1] = 0;
+	_textColorsMapHiCol[0] = _textColorsMapHiCol[1] = 0;
 	_animBlockPtr = nullptr;
 	_animBlockSize = 0;
 	_mouseLockCount = 1;
@@ -303,7 +353,7 @@ bool Screen::enableScreenDebug(bool enable) {
 
 Common::Error Screen::setResolution() {
 	byte palette[3 * 256];
-	if (!_useHiColorScreen)
+	if (!_vm->gameFlags().useHiColorMode)
 		_system->getPaletteManager()->grabPalette(palette, 0, 256);
 
 	int width = 320, height = 200;
@@ -325,22 +375,10 @@ Common::Error Screen::setResolution() {
 	if (_vm->gameFlags().platform == Common::kPlatformSegaCD)
 		height = 224;
 
-	if (_useHiColorScreen) {
-		Graphics::PixelFormat px(2, 5, 5, 5, 0, 10, 5, 0, 0);
-		Common::List<Graphics::PixelFormat> tryModes = _system->getSupportedFormats();
-		for (Common::List<Graphics::PixelFormat>::iterator g = tryModes.begin(); g != tryModes.end(); ++g) {
-			if (g->bytesPerPixel != 2 || g->aBits()) {
-				g = tryModes.reverse_erase(g);
-			} else if (*g == px) {
-				tryModes.clear();
-				tryModes.push_back(px);
-				break;
-			}
-		}
-		initGraphics(width, height, tryModes);
-
+	if (_vm->gameFlags().useHiColorMode) {
+		initGraphics(width, height, nullptr);
 		_outputPixelFormat = _system->getScreenFormat();
-		if (_outputPixelFormat.bytesPerPixel < 2)
+		if (_outputPixelFormat.bytesPerPixel != 2 && _outputPixelFormat.bytesPerPixel != 4)
 			return Common::kUnsupportedColorMode;
 
 	} else {
@@ -352,26 +390,32 @@ Common::Error Screen::setResolution() {
 }
 
 void Screen::enableHiColorMode(bool enabled) {
-	if (_useHiColorScreen && enabled) {
+	if (_outputPixelFormat.bytesPerPixel > 1 && enabled) {
 		if (!_hiColorNativePalettes)
-			_hiColorNativePalettes = new uint16[1024];
-		memset(_hiColorNativePalettes, 0, 1024 * sizeof(uint16));
-		delete[] _hiColorConversionPalette;
+			_hiColorNativePalettes = new uint8[_outputPixelFormat.bytesPerPixel * 1024]();
+		delete[] reinterpret_cast<uint8*>(_hiColorConversionPalette);
 		_hiColorConversionPalette = nullptr;
-		_internalBytesPerPixel = 2;
+		_internalBytesPerPixel = _outputPixelFormat.bytesPerPixel;
 	} else {
-		if (_useHiColorScreen) {
+		if (_outputPixelFormat.bytesPerPixel > 1) {
 			if (!_hiColorConversionPalette)
-				_hiColorConversionPalette = new uint16[256];
-			memset(_hiColorConversionPalette, 0, 256 * sizeof(uint16));
+				_hiColorConversionPalette = new uint8[_outputPixelFormat.bytesPerPixel * 256]();
 		}
 
-		delete[] _hiColorNativePalettes;
+		delete[] reinterpret_cast<uint8*>(_hiColorNativePalettes);
 		_hiColorNativePalettes = nullptr;
 		_internalBytesPerPixel = 1;
 	}
 
 	resetPagePtrsAndBuffers(_isSegaCD ? SCREEN_W * _screenHeight : SCREEN_PAGE_SIZE * _internalBytesPerPixel);
+
+	int num = _outputPixelFormat.bytesPerPixel >> 1;
+	assert((_internalBytesPerPixel & ~1) + num < ARRAYSIZE(_scale2xProcs));
+	_scale2xProc = _scale2xProcs[(_internalBytesPerPixel & ~1) + num];
+	assert(num < ARRAYSIZE(_getPagePixelProcs));
+	_getPagePixelProc = _getPagePixelProcs[num];
+	assert(num < ARRAYSIZE(_setPagePixelProcs));
+	_setPagePixelProc = _setPagePixelProcs[num];
 }
 
 int Screen::updateScreen() {
@@ -468,33 +512,25 @@ void Screen::updateDirtyRectsAmiga() {
 	_dirtyRects.clear();
 }
 
-#define mScale2x(dst, dstPitch, src, srcPitch, w, h) \
-	if (!_useHiColorScreen) \
-		scale2x<uint8, uint16>(dst, dstPitch, src, srcPitch, w, h); \
-	else if (_internalBytesPerPixel == 2) \
-		scale2x<uint16, uint32>(dst, dstPitch, src, srcPitch, w, h); \
-	 else \
-		scale2x<uint8, uint32>(dst, dstPitch, src, srcPitch, w, h)
-
 void Screen::updateDirtyRectsOvl() {
+	assert(_scale2xProc);
 	if (_forceFullUpdate) {
 		const byte *src = getCPagePtr(0);
-		byte *dst = _sjisOverlayPtrs[0];
-		mScale2x(dst, 640, src, SCREEN_W, SCREEN_W, SCREEN_H);
+		uint8 *dst = _sjisOverlayPtrs[0];
+		(this->*_scale2xProc)(dst, 640, src, SCREEN_W, SCREEN_W, SCREEN_H);
 		mergeOverlay(0, 0, 640, 400);
-		_system->copyRectToScreen(dst, _useHiColorScreen ? 1280 : 640, 0, 0, 640, 400);
+		_system->copyRectToScreen(dst, 640 * _outputPixelFormat.bytesPerPixel, 0, 0, 640, 400);
 	} else {
-		const byte *page0 = getCPagePtr(0);
-		byte *ovl0 = _sjisOverlayPtrs[0];
-		int dstBpp = _useHiColorScreen ? 2 : 1;
+		const uint8 *page0 = getCPagePtr(0);
+		uint8 *ovl0 = _sjisOverlayPtrs[0];
 
 		Common::List<Common::Rect>::iterator it;
 		for (it = _dirtyRects.begin(); it != _dirtyRects.end(); ++it) {
-			byte *dst = ovl0 + it->top * 1280 * dstBpp + (it->left << dstBpp);
-			const byte *src = page0 + it->top * SCREEN_W * _internalBytesPerPixel + it->left * _internalBytesPerPixel;
-			mScale2x(dst, 640, src, SCREEN_W, it->width(), it->height());
+			uint8 *dst = ovl0 + it->top * 2 * 640 * _outputPixelFormat.bytesPerPixel + it->left * 2 * _outputPixelFormat.bytesPerPixel;
+			const uint8 *src = page0 + it->top * SCREEN_W * _internalBytesPerPixel + it->left * _internalBytesPerPixel;
+			(this->*_scale2xProc)(dst, 640, src, SCREEN_W, it->width(), it->height());
 			mergeOverlay(it->left<<1, it->top<<1, it->width()<<1, it->height()<<1);
-			_system->copyRectToScreen(dst, _useHiColorScreen ? 1280 : 640, it->left << 1, it->top << 1, it->width() << 1, it->height() << 1);
+			_system->copyRectToScreen(dst, 640 * _outputPixelFormat.bytesPerPixel, it->left << 1, it->top << 1, it->width() << 1, it->height() << 1);
 		}
 	}
 
@@ -502,42 +538,39 @@ void Screen::updateDirtyRectsOvl() {
 	_dirtyRects.clear();
 }
 
-#undef mScale2x
-
-template<typename srcType, typename scaleToType>
+template<typename srcPixelType, typename dstPixelType>
 void Screen::scale2x(uint8 *dst, int dstPitch, const uint8 *src, int srcPitch, int w, int h) {
-	int dstAdd = dstPitch - w;
+	int dstAdd = (dstPitch - w) << 1;
 	int srcAdd = srcPitch - w;
-	scaleToType *dstL1 = (scaleToType*)dst;
-	scaleToType *dstL2 = (scaleToType*)(dst + dstPitch * (sizeof(scaleToType) >> 1));
-	const srcType *src1 = (const srcType*)src;
+	dstPixelType *dstL11= reinterpret_cast<dstPixelType*>(dst);
+	dstPixelType *dstL12 = dstL11 + 1;
+	dstPixelType *dstL21 = dstL11 + dstPitch;
+	dstPixelType *dstL22 = dstL12 + dstPitch;
+	const dstPixelType *p = reinterpret_cast<const dstPixelType *>(_hiColorNativePalettes ? _hiColorNativePalettes : _hiColorConversionPalette);
+	const srcPixelType *src1 = reinterpret_cast<const srcPixelType*>(src);
 
 	while (h--) {
 		for (int x = 0; x < w; x++) {
-			scaleToType col = (sizeof(srcType) == 1 && sizeof(scaleToType) == 4) ? _hiColorConversionPalette[*src1++] : *src1++;
-			*dstL1++ = *dstL2++ = col | (col << (sizeof(scaleToType) << 2));
+			*dstL11 = *dstL12 = *dstL21 = *dstL22 = (sizeof(srcPixelType) == sizeof(dstPixelType)) ? *src1++ : p[*src1++];
+			dstL11 += 2; dstL12 += 2; dstL21 += 2; dstL22 += 2;
 		}
-		dstL1 += dstAdd; dstL2 += dstAdd;
+		dstL11 += dstAdd; dstL12 += dstAdd; dstL21 += dstAdd; dstL22 += dstAdd;
 		src1 += srcAdd;
 	}
 }
 
-template void Screen::scale2x<uint8, uint16>(uint8 *dst, int dstPitch, const uint8 *src, int srcPitch, int w, int h);
-template void Screen::scale2x<uint16, uint32>(uint8 *dst, int dstPitch, const uint8 *src, int srcPitch, int w, int h);
-template void Screen::scale2x<uint8, uint32>(uint8 *dst, int dstPitch, const uint8 *src, int srcPitch, int w, int h);
-
 template<typename pixelType>
 void Screen::mergeOverlayImpl(int x, int y, int w, int h) {
 	const uint8 *src = _sjisOverlayPtrs[1] + y * 640 + x;
-	uint16 *p16 = _hiColorNativePalettes ? _hiColorNativePalettes : _hiColorConversionPalette;
-	pixelType *dst = (pixelType*)(_sjisOverlayPtrs[0] + y * 640 * sizeof(pixelType) + x * sizeof(pixelType));
+	const pixelType *p = reinterpret_cast<const pixelType*>(_hiColorNativePalettes ? _hiColorNativePalettes : _hiColorConversionPalette);
+	pixelType *dst = reinterpret_cast<pixelType*>(_sjisOverlayPtrs[0] + y * 640 * sizeof(pixelType) + x * sizeof(pixelType));
 	int add = 640 - w;
 
 	while (h--) {
 		for (x = 0; x < w; ++x) {
 			uint8 col = *src++;
 			if (col != _sjisInvisibleColor)
-				*dst = (sizeof(pixelType) == 2) ? p16[col] : col;
+				*dst = (sizeof(pixelType) == 1) ? col : p[col];
 			dst++;
 		}
 		dst += add;
@@ -545,9 +578,6 @@ void Screen::mergeOverlayImpl(int x, int y, int w, int h) {
 	}
 }
 
-template void Screen::mergeOverlayImpl<uint8>(int x, int y, int w, int h);
-template void Screen::mergeOverlayImpl<uint16>(int x, int y, int w, int h);
-
 const ScreenDim *Screen::getScreenDim(int dim) const {
 	assert(dim < _dimTableCount);
 	return _customDimTable[dim] ? _customDimTable[dim] : &_dimTable[dim];
@@ -784,35 +814,35 @@ void Screen::copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc,
 	}
 }
 
-int Screen::getPagePixel(int pageNum, int x, int y) {
+template <typename T> int Screen::getPagePixelImpl(int pageNum, int x, int y) {
 	assert(pageNum < SCREEN_PAGE_NUM);
 	assert(x >= 0 && x < SCREEN_W && y >= 0 && y < _screenHeight);
-	if (_internalBytesPerPixel == 1)
+	if (sizeof(T) == 1)
 		return _pagePtrs[pageNum][y * SCREEN_W + x];
 	else
-		return ((uint16*)_pagePtrs[pageNum])[y * SCREEN_W + x];
+		return static_cast<int>(reinterpret_cast<T*>(_pagePtrs[pageNum])[y * SCREEN_W + x]);
 }
 
-void Screen::setPagePixel(int pageNum, int x, int y, uint8 color) {
+template<typename T>
+void Screen::setPagePixelImpl(int pageNum, int x, int y, uint8 color) {
 	assert(pageNum < SCREEN_PAGE_NUM);
 	assert(x >= 0 && x < SCREEN_W && y >= 0 && y < _screenHeight);
 
 	if (pageNum == 0 || pageNum == 1)
 		addDirtyRect(x, y, 1, 1);
 
-	if (_4bitPixelPacking) {
-		color &= 0x0F;
-		color |= (color << 4);
-	} else if (_renderMode == Common::kRenderCGA) {
-		color &= 0x03;
-	} else if (_use16ColorMode || (_renderMode == Common::kRenderEGA && !_useHiResEGADithering)) {
-		color &= 0x0F;
-	}
-
-	if (_internalBytesPerPixel == 2) {
-		((uint16*)_pagePtrs[pageNum])[y * SCREEN_W + x] = _hiColorNativePalettes[color];
-	} else {
+	if (sizeof(T) == 1) {
+		if (_4bitPixelPacking) {
+			color &= 0x0F;
+			color |= (color << 4);
+		} else if (_renderMode == Common::kRenderCGA) {
+			color &= 0x03;
+		} else if (_use16ColorMode || (_renderMode == Common::kRenderEGA && !_useHiResEGADithering)) {
+			color &= 0x0F;
+		}
 		_pagePtrs[pageNum][y * SCREEN_W + x] = color;
+	} else {
+		reinterpret_cast<T*>(_pagePtrs[pageNum])[y * SCREEN_W + x] = reinterpret_cast<T*>(_hiColorNativePalettes)[color];
 	}
 }
 
@@ -829,12 +859,12 @@ void Screen::fadeToBlack(int delay, const UpdateFunctor *upFunc) {
 }
 
 void Screen::fadePalette(const Palette &pal, int delay, const UpdateFunctor *upFunc) {
-	if (_renderMode == Common::kRenderEGA || _internalBytesPerPixel == 2)
+	if (_renderMode == Common::kRenderEGA || _internalBytesPerPixel > 1)
 		setScreenPalette(pal);
 
 	updateScreen();
 
-	if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderEGA || _internalBytesPerPixel == 2)
+	if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderEGA || _internalBytesPerPixel > 1)
 		return;
 
 	int diff = 0, delayInc = 0;
@@ -848,7 +878,7 @@ void Screen::fadePalette(const Palette &pal, int delay, const UpdateFunctor *upF
 
 		if (upFunc && upFunc->isValid())
 			(*upFunc)();
-		else if (_useHiColorScreen)
+		else if (_outputPixelFormat.bytesPerPixel > 1)
 			updateScreen();
 		else
 			updateBackendScreen(true);
@@ -1055,19 +1085,35 @@ void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPag
 			dst += SCREEN_W * _internalBytesPerPixel;
 		}
 	} else {
-		while (h--) {
-			for (int i = 0; i < w; ++i) {
-				if (_internalBytesPerPixel == 2) {
-					uint px = *(const uint16*)&src[i << 1];
+		if (_internalBytesPerPixel == 4) {
+			while (h--) {
+				for (int i = 0; i < w; ++i) {
+					uint32 px = reinterpret_cast<const uint32*>(src)[i];
 					if (px)
-						*(uint16*)&dst[i << 1] = px;
-				} else {
+						reinterpret_cast<uint32*>(dst)[i] = px;
+				}
+				src += SCREEN_W * _internalBytesPerPixel;
+				dst += SCREEN_W * _internalBytesPerPixel;
+			}
+		} else if (_internalBytesPerPixel == 2) {
+			while (h--) {
+				for (int i = 0; i < w; ++i) {
+					uint16 px = reinterpret_cast<const uint16*>(src)[i];
+					if (px)
+						reinterpret_cast<uint16*>(dst)[i] = px;
+				}
+				src += SCREEN_W * _internalBytesPerPixel;
+				dst += SCREEN_W * _internalBytesPerPixel;
+			}
+		} else {
+			while (h--) {
+				for (int i = 0; i < w; ++i) {
 					if (src[i])
 						dst[i] = src[i];
 				}
+				src += SCREEN_W * _internalBytesPerPixel;
+				dst += SCREEN_W * _internalBytesPerPixel;
 			}
-			src += SCREEN_W * _internalBytesPerPixel;
-			dst += SCREEN_W * _internalBytesPerPixel;
 		}
 	}
 }
@@ -1203,7 +1249,7 @@ void Screen::shuffleScreen(int sx, int sy, int w, int h, int srcPage, int dstPag
 
 void Screen::fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum, bool xored) {
 	assert(x2 < SCREEN_W && y2 < _screenHeight);
-	uint16 color16 = 0;
+	uint32 hcolor = 0;
 	if (pageNum == -1)
 		pageNum = _curPage;
 
@@ -1221,8 +1267,8 @@ void Screen::fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum,
 		color &= 0x03;
 	} else if (_use16ColorMode || (_renderMode == Common::kRenderEGA && !_useHiResEGADithering)) {
 		color &= 0x0F;
-	} else if (_internalBytesPerPixel == 2)
-		color16 = shadeRGBColor(_hiColorNativePalettes[color]);
+	} else if (_internalBytesPerPixel > 1)
+		hcolor = shadeRGBColor(_internalBytesPerPixel == 4 ? reinterpret_cast<const uint32*>(_hiColorNativePalettes)[color] : reinterpret_cast<const uint16*>(_hiColorNativePalettes)[color]);
 
 	if (xored) {
 		// no 16 bit support for this (unneeded)
@@ -1233,10 +1279,14 @@ void Screen::fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum,
 		}
 	} else {
 		for (; y1 <= y2; ++y1) {
-			if (_internalBytesPerPixel == 2) {
-				uint16 *ptr = (uint16*)dst;
+			if (_internalBytesPerPixel == 4) {
+				uint32 *ptr = reinterpret_cast<uint32*>(dst);
 				for (int i = 0; i < x2 - x1 + 1; i++)
-					*ptr++ = color16;
+					*ptr++ = hcolor;
+			} else if (_internalBytesPerPixel == 2) {
+				uint16 *ptr = reinterpret_cast<uint16*>(dst);
+				for (int i = 0; i < x2 - x1 + 1; i++)
+					*ptr++ = static_cast<uint16>(hcolor);
 			} else {
 				memset(dst, color, x2 - x1 + 1);
 			}
@@ -1306,27 +1356,41 @@ void Screen::drawLine(bool vertical, int x, int y, int length, int color) {
 		color &= 0x03;
 	} else if (_use16ColorMode || (_renderMode == Common::kRenderEGA && !_useHiResEGADithering)) {
 		color &= 0x0F;
-	} else if (_internalBytesPerPixel == 2)
-		color = shadeRGBColor(_hiColorNativePalettes[color]);
+	} else if (_internalBytesPerPixel > 1)
+		color = static_cast<int>(shadeRGBColor(_internalBytesPerPixel == 4 ? reinterpret_cast<const uint32*>(_hiColorNativePalettes)[color] : reinterpret_cast<const uint16*>(_hiColorNativePalettes)[color]));
 
 	if (vertical) {
 		assert((y + length) <= SCREEN_H);
 		int currLine = 0;
-		while (currLine < length) {
-			if (_internalBytesPerPixel == 2)
-				*(uint16*)ptr = color;
-			else
+		if (_internalBytesPerPixel == 4) {
+			uint32 *p = reinterpret_cast<uint32*>(ptr);
+			while (currLine < length) {
+				*p = color;
+				p += SCREEN_W;
+				currLine++;
+			}
+		} else if (_internalBytesPerPixel == 2) {
+			uint16 *p = reinterpret_cast<uint16*>(ptr);
+			while (currLine < length) {
+				*p = static_cast<uint16>(color);
+				p += SCREEN_W;
+				currLine++;
+			}
+		} else {
+			while (currLine < length) {
 				*ptr = color;
-			ptr += SCREEN_W * _internalBytesPerPixel;
-			currLine++;
+				ptr += SCREEN_W;
+				currLine++;
+			}
 		}
 	} else {
 		assert((x + length) <= SCREEN_W);
-		if (_internalBytesPerPixel == 2) {
-			for (int i = 0; i < length; i++) {
-				*(uint16*)ptr = color;
-				ptr += 2;
-			}
+		if (_internalBytesPerPixel == 4) {
+			uint32 *p = reinterpret_cast<uint32*>(ptr);
+			Common::fill<uint32*, uint32>(p, &p[length], color);
+		} else if (_internalBytesPerPixel == 2) {
+			uint16 *p = reinterpret_cast<uint16*>(ptr);
+			Common::fill<uint16*, uint32>(p, &p[length], color);
 		} else {
 			memset(ptr, color, length);
 		}
@@ -1355,15 +1419,15 @@ void Screen::setTextColor(const uint8 *cmap8, int a, int b) {
 	}
 }
 
-void Screen::setTextColor16bit(const uint16 *cmap16) {
-	assert(cmap16);
-	_textColorsMap16bit[0] = cmap16[0];
-	_textColorsMap16bit[1] = cmap16[1];
+void Screen::setTextColorHiCol(const uint32 *cmap) {
+	assert(cmap);
+	_textColorsMapHiCol[0] = cmap[0];
+	_textColorsMapHiCol[1] = cmap[1];
 	// We need to update the color tables of all fonts, we
 	// setup so far here.
 	for (int i = 0; i < FID_NUM; ++i) {
 		if (_fonts[i])
-			_fonts[i]->set16bitColorMap(_textColorsMap16bit);
+			_fonts[i]->setHiColorMap(_textColorsMapHiCol);
 	}
 }
 
@@ -1516,11 +1580,16 @@ int Screen::getNumberOfCharacters(const char *str) {
 }
 
 void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2, int pitch) {
-	uint16 cmap16[2];
+	uint32 cmapHiCol[2];
 	if (_hiColorNativePalettes) {
-		cmap16[0] = color2 ? shadeRGBColor(_hiColorNativePalettes[color2]) : 0xFFFF;
-		cmap16[1] = _hiColorNativePalettes[color1];
-		setTextColor16bit(cmap16);
+		if (_internalBytesPerPixel == 4) {
+			cmapHiCol[0] = color2 ? shadeRGBColor(reinterpret_cast<uint32*>(_hiColorNativePalettes)[color2]) : 0xFFFFFFFF;
+			cmapHiCol[1] = reinterpret_cast<uint32*>(_hiColorNativePalettes)[color1];
+		} else {
+			cmapHiCol[0] = color2 ? shadeRGBColor(reinterpret_cast<uint16*>(_hiColorNativePalettes)[color2]) : 0xFFFF;
+			cmapHiCol[1] = reinterpret_cast<uint16*>(_hiColorNativePalettes)[color1];
+		}
+		setTextColorHiCol(cmapHiCol);
 	}
 
 	uint8 cmap8[2];
@@ -1626,7 +1695,7 @@ void Screen::drawChar(uint16 c, int x, int y, int pitch) {
 			return;
 		}
 
-		int bpp = (_currentFont == Screen::FID_SJIS_LARGE_FNT) ? 2 : 1;
+		int bpp = (_currentFont == Screen::FID_SJIS_LARGE_FNT) ? _outputPixelFormat.bytesPerPixel : 1;
 		destPage += (y * 2) * 640 * bpp + (x * 2 * bpp);
 
 		fnt->drawChar(c, destPage, 640, bpp);
@@ -3113,7 +3182,7 @@ int16 Screen::encodeShapeAndCalculateSize(uint8 *from, uint8 *to, int size_to) {
 	return (to - toPtr);
 }
 
-uint16 Screen::shadeRGBColor(uint16 col) {
+uint32 Screen::shadeRGBColor(uint32 col) {
 	uint8 r = 0, g = 0, b = 0;
 	_outputPixelFormat.colorToRGB(col, r, g, b);
 
@@ -3182,7 +3251,7 @@ void Screen::setMouseCursor(int x, int y, const byte *shape) {
 
 	if (_vm->gameFlags().useHiRes) {
 		xOffset = mouseWidth;
-		scale2x<uint8, uint16>(getPagePtr(8) + mouseWidth, SCREEN_W, getPagePtr(8), SCREEN_W, mouseWidth, mouseHeight);
+		scale2x<uint8, uint8>(getPagePtr(8) + mouseWidth, SCREEN_W, getPagePtr(8), SCREEN_W, mouseWidth, mouseHeight);
 		postProcessCursor(getPagePtr(8) + mouseWidth, mouseWidth, mouseHeight, SCREEN_W);
 	} else {
 		postProcessCursor(getPagePtr(8), mouseWidth, mouseHeight, SCREEN_W);
@@ -3435,7 +3504,7 @@ bool Screen::loadPalette(const char *filename, Palette &pal) {
 		numCols /= Palette::kVGABytesPerColor;
 		pal.loadVGAPalette(*stream, 0, numCols);
 	} else {
-		if (_internalBytesPerPixel == 2) {
+		if (_internalBytesPerPixel > 1) {
 			numCols = stream->size() / 2;
 			pal.loadHiColorPalette(*stream, 0, numCols);
 		} else if (!_hiColorNativePalettes) {
@@ -3541,20 +3610,22 @@ void Screen::addDirtyRect(int x, int y, int w, int h) {
 // overlay functions
 
 byte *Screen::getOverlayPtr(int page) {
-	if (page == 0 || page == 1)
+	page &= ~1;
+
+	if (page == 0)
 		return _sjisOverlayPtrs[1];
-	else if (page == 2 || page == 3)
+	else if (page == 2)
 		return _sjisOverlayPtrs[2];
 
 	if (_vm->game() == GI_KYRA2) {
-		if (page == 12 || page == 13)
+		if (page == 12)
 			return _sjisOverlayPtrs[3];
 	} else if (_vm->game() == GI_LOL) {
-		if (page == 4 || page == 5)
+		if (page == 4)
 			return _sjisOverlayPtrs[3];
-		if (page == 6 || page == 7)
+		if (page == 6)
 			return _sjisOverlayPtrs[4];
-		if (page == 12 || page == 13)
+		if (page == 12)
 			return _sjisOverlayPtrs[5];
 	}
 
@@ -3651,8 +3722,10 @@ void Screen::crossFadeRegion(int x1, int y1, int x2, int y2, int w, int h, int s
 			if (++iH >= h)
 				iH = 0;
 
-			if (_internalBytesPerPixel == 2)
-				((uint16*)d)[dY * 320 + dX] = ((uint16*)s)[sY * 320 + sX];
+			if (_internalBytesPerPixel == 4)
+				reinterpret_cast<uint32*>(d)[dY * 320 + dX] = reinterpret_cast<uint32*>(s)[sY * 320 + sX];
+			else if (_internalBytesPerPixel == 2)
+				reinterpret_cast<uint16*>(d)[dY * 320 + dX] = reinterpret_cast<uint16*>(s)[sY * 320 + sX];
 			else
 				d[dY * 320 + dX] = s[sY * 320 + sX];
 			addDirtyRect(dX, dY, 1, 1);
diff --git a/engines/kyra/graphics/screen.h b/engines/kyra/graphics/screen.h
index 3e9dc38a2bd..27b0f12cca7 100644
--- a/engines/kyra/graphics/screen.h
+++ b/engines/kyra/graphics/screen.h
@@ -122,7 +122,7 @@ public:
 	/**
 	* Sets a text 16bit palette map. Only used in in EOB II FM-Towns. The map contains 2 entries.
 	*/
-	virtual void set16bitColorMap(const uint16 *src) {}
+	virtual void setHiColorMap(const uint32 *src) {}
 
 	enum FontStyle {
 		kStyleNone			=	0,
@@ -678,8 +678,14 @@ public:
 
 	void clearPage(int pageNum);
 
-	int getPagePixel(int pageNum, int x, int y);
-	void setPagePixel(int pageNum, int x, int y, uint8 color);
+	int getPagePixel(int pageNum, int x, int y) {
+		assert(_getPagePixelProc);
+		return (this->*_getPagePixelProc)(pageNum, x, y);
+	}
+	void setPagePixel(int pageNum, int x, int y, uint8 color) {
+		assert(_setPagePixelProc);
+		(this->*_setPagePixelProc)(pageNum, x, y, color);
+	}
 
 	const uint8 *getCPagePtr(int pageNum) const;
 	uint8 *getPageRect(int pageNum, int x, int y, int w, int h);
@@ -731,7 +737,7 @@ public:
 
 	virtual void setTextColorMap(const uint8 *cmap) = 0;
 	void setTextColor(const uint8 *cmap, int a, int b);
-	void setTextColor16bit(const uint16 *cmap16);
+	void setTextColorHiCol(const uint32 *cmap);
 	int setFontStyles(FontId fontId, int styles);
 
 	const ScreenDim *getScreenDim(int dim) const;
@@ -814,7 +820,7 @@ public:
 	// can well afford the 20 lines of extra code.
 	void crossFadeRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage);
 
-	uint16 *get16bitPalette() { return _hiColorNativePalettes; }
+	const void *getHiColorPalette() const { return _hiColorNativePalettes; }
 	void set16bitShadingLevel(int lvl) { _hiColorShadingLevel = lvl; }
 
 protected:
@@ -824,13 +830,11 @@ protected:
 	void updateDirtyRectsAmiga();
 	void updateDirtyRectsOvl();
 
-	template<typename srcType, typename scaleToType> void scale2x(uint8 *dst, int dstPitch, const uint8 *src, int srcPitch, int w, int h);
+	template<typename srcPixelType, typename dstPixelType> void scale2x(uint8 *dst, int dstPitch, const uint8 *src, int srcPitch, int w, int h);
 	template<typename pixelType> void mergeOverlayImpl(int x, int y, int w, int h);
 	virtual void mergeOverlay(int x, int y, int w, int h) {
-		if (_useHiColorScreen)
-			mergeOverlayImpl<uint16>(x, y, w, h);
-		else
-			mergeOverlayImpl<uint8>(x, y, w, h);
+		assert(_mergeOverlayProc);
+		(this->*_mergeOverlayProc)(x, y, w, h);
 	}
 
 	// overlay specific
@@ -848,6 +852,23 @@ protected:
 	template<bool noXor> static void wrapped_decodeFrameDelta(uint8 *dst, const uint8 *src);
 	template<bool noXor> static void wrapped_decodeFrameDeltaPage(uint8 *dst, const uint8 *src, const int pitch);
 
+	typedef void (Screen::*MergeOverlayFunc)(int, int, int, int);
+	MergeOverlayFunc _mergeOverlayProc;
+	static const MergeOverlayFunc _mergeOverlayProcs[];
+	typedef void (Screen::*Scale2xFunc)(uint8*, int, const uint8*, int, int, int);
+	Scale2xFunc _scale2xProc;
+	static const Scale2xFunc _scale2xProcs[];
+
+	template<typename T> int getPagePixelImpl(int pageNum, int x, int y);
+	template<typename T> void setPagePixelImpl(int pageNum, int x, int y, uint8 color);
+
+	typedef int (Screen::*GetPagePixelProc)(int, int, int);
+	GetPagePixelProc _getPagePixelProc;
+	static const GetPagePixelProc _getPagePixelProcs[];
+	typedef void (Screen::*SetPagePixelProc)(int, int, int, uint8);
+	SetPagePixelProc _setPagePixelProc;
+	static const SetPagePixelProc _setPagePixelProcs[];
+
 	uint8 *_pagePtrs[16];
 	const uint8 *_pagePtrsBuff;
 	uint8 *_sjisOverlayPtrs[SCREEN_OVLS_NUM];
@@ -859,7 +880,7 @@ protected:
 
 	Font *_fonts[FID_NUM];
 	uint8 _textColorsMap[16];
-	uint16 _textColorsMap16bit[2];
+	uint32 _textColorsMapHiCol[2];
 
 	uint8 *_textRenderBuffer;
 	int _textRenderBufferSize;
@@ -874,7 +895,6 @@ protected:
 	bool _4bitPixelPacking;
 	bool _useHiResEGADithering;
 	Graphics::PixelFormat _outputPixelFormat;
-	bool _useHiColorScreen;
 	bool _isAmiga;
 	bool _useAmigaExtraColors;
 	bool _isSegaCD;
@@ -888,10 +908,10 @@ protected:
 	Common::Array<Palette *> _palettes;
 	Palette *_internFadePalette;
 
-	uint16 shadeRGBColor(uint16 col);
+	uint32 shadeRGBColor(uint32 col);
 
-	uint16 *_hiColorNativePalettes;
-	uint16 *_hiColorConversionPalette;
+	void *_hiColorNativePalettes;
+	void *_hiColorConversionPalette;
 	uint8 _hiColorShadingLevel;
 
 	uint8 *_animBlockPtr;
diff --git a/engines/kyra/graphics/screen_eob.cpp b/engines/kyra/graphics/screen_eob.cpp
index 61784b1e638..78824c9e5b4 100644
--- a/engines/kyra/graphics/screen_eob.cpp
+++ b/engines/kyra/graphics/screen_eob.cpp
@@ -77,7 +77,7 @@ struct eob2ChineseLZInStream {
 };
 }
 
-Screen_EoB::Screen_EoB(EoBCoreEngine *vm, OSystem *system) : Screen(vm, system, vm->gameFlags().lang == Common::Language::ZH_TWN ? _screenDimTableZH : _screenDimTableIntl, _screenDimTableCount), _cursorColorKey16Bit(0x8000) {
+Screen_EoB::Screen_EoB(EoBCoreEngine *vm, OSystem *system) : Screen(vm, system, vm->gameFlags().lang == Common::Language::ZH_TWN ? _screenDimTableZH : _screenDimTableIntl, _screenDimTableCount), _hiColorCursorColorKey(0x8000) {
 	_dsBackgroundFading = false;
 	_dsShapeFadingLevel = 0;
 	_dsBackgroundFadingXOffs = 0;
@@ -172,7 +172,7 @@ bool Screen_EoB::init() {
 			sega_setTextBuffer(0, 0);
 		}
 
-		_useShapeShading = (_internalBytesPerPixel != 2 && !_isAmiga && !_isSegaCD && !_use16ColorMode && _renderMode != Common::kRenderCGA && _renderMode != Common::kRenderEGA) || _useHiResEGADithering;
+		_useShapeShading = (_internalBytesPerPixel == 1 && !_isAmiga && !_isSegaCD && !_use16ColorMode && _renderMode != Common::kRenderCGA && _renderMode != Common::kRenderEGA) || _useHiResEGADithering;
 
 		static const char *cpsExt[] = { "CPS", "EGA", "SHP", "BIN" };
 		int ci = 0;
@@ -229,19 +229,22 @@ void Screen_EoB::setMouseCursor(int x, int y, const byte *shape, const uint8 *ov
 
 	int mouseW = (shape[2] << 3);
 	int mouseH = (shape[3]);
-	int colorKey = (_renderMode == Common::kRenderCGA) ? 0 : (_internalBytesPerPixel == 2 ? _cursorColorKey16Bit : _cursorColorKey);
+	int colorKey = (_renderMode == Common::kRenderCGA) ? 0 : (_internalBytesPerPixel > 1 ? _hiColorCursorColorKey : _cursorColorKey);
+	if (_internalBytesPerPixel == 4)
+		colorKey <<= 16;
 
 	int scaleFactor = _vm->gameFlags().useHiRes ? 2 : 1;
-	int bpp = _useHiColorScreen ? 2 : 1;
-
-	uint8 *cursor = new uint8[mouseW * scaleFactor * bpp * mouseH * scaleFactor];
-
-	if (_internalBytesPerPixel == 2) {
-		for (int s = mouseW * scaleFactor * bpp * mouseH * scaleFactor; s; s -= 2)
-			*(uint16*)(cursor + s - 2) = colorKey;
+	uint8 *cursor = new uint8[mouseW * scaleFactor * _outputPixelFormat.bytesPerPixel * mouseH * scaleFactor];
+
+	if (_internalBytesPerPixel == 4) {
+		uint32 *c = reinterpret_cast<uint32*>(cursor);
+		Common::fill<uint32*, uint32>(c, c + mouseW * scaleFactor * mouseH * scaleFactor, colorKey);
+	}  else if (_internalBytesPerPixel == 2) {
+		uint16 *c = reinterpret_cast<uint16*>(cursor);
+		Common::fill<uint16*, uint16>(c, c + mouseW * scaleFactor * mouseH * scaleFactor, colorKey);
 	} else {
 		// We don't use fillRect here to make sure that the color key 0xFF doesn't get converted into EGA color
-		memset(cursor, colorKey, mouseW * scaleFactor * bpp * mouseH * scaleFactor);
+		memset(cursor, colorKey, mouseW * scaleFactor * _outputPixelFormat.bytesPerPixel * mouseH * scaleFactor);
 	}
 
 	copyBlockToPage(6, 0, 0, mouseW * scaleFactor, mouseH * scaleFactor, cursor);
@@ -250,10 +253,12 @@ void Screen_EoB::setMouseCursor(int x, int y, const byte *shape, const uint8 *ov
 
 	if (_useHiResEGADithering)
 		ditherRect(getCPagePtr(6), cursor, mouseW * scaleFactor, mouseW, mouseH, colorKey);
-	else if (_useHiColorScreen)
-		scale2x<uint16, uint32>(cursor, mouseW * scaleFactor, getCPagePtr(6), SCREEN_W, mouseW, mouseH);
+	else if (_outputPixelFormat.bytesPerPixel == 4)
+		scale2x<uint32, uint32>(cursor, mouseW * scaleFactor, getCPagePtr(6), SCREEN_W, mouseW, mouseH);
+	else if (_outputPixelFormat.bytesPerPixel == 2)
+		scale2x<uint16, uint16>(cursor, mouseW * scaleFactor, getCPagePtr(6), SCREEN_W, mouseW, mouseH);
 	else if (_vm->gameFlags().useHiRes)
-		scale2x<uint8, uint16>(cursor, mouseW * scaleFactor, getCPagePtr(6), SCREEN_W, mouseW, mouseH);
+		scale2x<uint8, uint8>(cursor, mouseW * scaleFactor, getCPagePtr(6), SCREEN_W, mouseW, mouseH);
 	else
 		copyRegionToBuffer(6, 0, 0, mouseW, mouseH, cursor);
 
@@ -289,7 +294,12 @@ void Screen_EoB::setMouseCursor(int x, int y, const byte *shape, const uint8 *ov
 
 	// Convert color key to 16 bit after drawing the mouse cursor.
 	// The cursor has been converted to 16 bit in scale2x().
-	colorKey = _hiColorConversionPalette ? _hiColorConversionPalette[colorKey] : colorKey;
+	if (_hiColorConversionPalette) {
+		if (_outputPixelFormat.bytesPerPixel == 4)
+			colorKey = reinterpret_cast<uint32 *>(_hiColorConversionPalette)[colorKey];
+		else
+			colorKey = reinterpret_cast<uint16 *>(_hiColorConversionPalette)[colorKey];
+	}
 	Graphics::PixelFormat pixelFormat = _system->getScreenFormat();
 
 	CursorMan.replaceCursor(cursor, mouseW * scaleFactor, mouseH * scaleFactor, x * scaleFactor, y * scaleFactor, colorKey, &pixelFormat);
@@ -311,7 +321,7 @@ void Screen_EoB::loadFileDataToPage(Common::SeekableReadStream *s, int pageNum,
 void Screen_EoB::printShadedText(const char *string, int x, int y, int col1, int col2, int shadowCol, int pitch) {
 	if (_isSegaCD && shadowCol) {
 		printText(string, x + 1, y + 1, shadowCol, 0, pitch);
-	} else if (!_isSegaCD && !_use16ColorMode && !_useHiColorScreen && (_fonts[_currentFont]->getType() == Font::kASCII || _fonts[_currentFont]->getType() == Font::kBIG5)) {
+	} else if (!_isSegaCD && !_use16ColorMode && _outputPixelFormat.bytesPerPixel == 1 && (_fonts[_currentFont]->getType() == Font::kASCII || _fonts[_currentFont]->getType() == Font::kBIG5)) {
 		printText(string, x - 1, y, shadowCol, col2);
 		printText(string, x, y + 1, shadowCol, 0);
 		printText(string, x - 1, y + 1, shadowCol, 0);
@@ -551,15 +561,22 @@ void Screen_EoB::convertPage(int srcPage, int dstPage, const uint8 *cgaMapping)
 }
 
 void Screen_EoB::setScreenPalette(const Palette &pal) {
-	if (_internalBytesPerPixel == 2) {
+	if (_internalBytesPerPixel > 1) {
 		assert(_hiColorNativePalettes);
 		for (int i = 0; i < 4; i++)
-			createHiColorFadeTable((const uint16 *)(pal.getData()), &_hiColorNativePalettes[i << 8], 0, i * 85);
+			createHiColorFadeTable(reinterpret_cast<const uint16*>(pal.getData()), reinterpret_cast<uint8*>(_hiColorNativePalettes) + (i << 8) * _internalBytesPerPixel, 0, i * 85);
 	} else if (_outputPixelFormat.bytesPerPixel > 1) {
 		assert(_hiColorConversionPalette);
 		_screenPalette->copy(pal);
-		for (int i = 0; i < pal.getNumColors(); ++i)
-			_hiColorConversionPalette[i] = _outputPixelFormat.RGBToColor(pal[i * 3] * 0xFF / 0x3F, pal[i * 3 + 1] * 0xFF / 0x3F, pal[i * 3 + 2] * 0xFF / 0x3F);
+		if (_outputPixelFormat.bytesPerPixel == 4) {
+			uint32 *p = reinterpret_cast<uint32*>(_hiColorConversionPalette);
+			for (int i = 0; i < pal.getNumColors(); ++i)
+				p[i] = _outputPixelFormat.RGBToColor(pal[i * 3] * 0xFF / 0x3F, pal[i * 3 + 1] * 0xFF / 0x3F, pal[i * 3 + 2] * 0xFF / 0x3F);
+		} else {
+			uint16 *p = reinterpret_cast<uint16*>(_hiColorConversionPalette);
+			for (int i = 0; i < pal.getNumColors(); ++i)
+				p[i] = _outputPixelFormat.RGBToColor(pal[i * 3] * 0xFF / 0x3F, pal[i * 3 + 1] * 0xFF / 0x3F, pal[i * 3 + 2] * 0xFF / 0x3F);
+		}
 		// The whole Surface has to be converted again after each palette change
 		_forceFullUpdate = true;
 	} else if (_useHiResEGADithering && pal.getNumColors() != 16) {
@@ -598,7 +615,7 @@ uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool enco
 	if (_use16ColorMode || (_renderMode == Common::kRenderEGA && !_useHiResEGADithering))
 		encode8bit = false;
 
-	if (_internalBytesPerPixel == 2 && encode8bit) {
+	if (_internalBytesPerPixel > 1 && encode8bit) {
 		shapesize = h * (w << 3) + 4;
 		shp = new uint8[shapesize]();
 		uint8 *dst = shp;
@@ -860,7 +877,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,
 	}
 	va_end(args);
 
-	dst += (_dsX1 << (2 + _internalBytesPerPixel));
+	dst += ((_dsX1 << 3) * _internalBytesPerPixel);
 	int16 dX = x - (_dsX1 << 3);
 	int16 dY = y;
 	int16 dW = _dsX2 - _dsX1;
@@ -1228,7 +1245,7 @@ const uint8 *Screen_EoB::generateShapeOverlay(const uint8 *shp, const uint8 *fad
 	if (*shp != 2)
 		return 0;
 
-	if (_internalBytesPerPixel == 2) {
+	if (_internalBytesPerPixel > 1) {
 		setFadeTable(fadingTable);
 		setShapeFadingLevel(1);
 		return 0;
@@ -1285,9 +1302,9 @@ void Screen_EoB::drawExplosion(int scale, int radius, int numElements, int stepS
 	int16 *ptr3 = (int16 *)&_dsTempPage[300];
 	int16 *ptr4 = (int16 *)&_dsTempPage[600];
 	int16 *ptr5 = (int16 *)&_dsTempPage[900];
-	int16 *ptr6 = (int16 *)&_dsTempPage[1200];
-	int16 *ptr7 = (int16 *)&_dsTempPage[1500];
-	int16 *ptr8 = (int16 *)&_dsTempPage[1800];
+	int32 *ptr6 = (int32 *)&_dsTempPage[1200];
+	int16 *ptr7 = (int16 *)&_dsTempPage[1800];
+	int16 *ptr8 = (int16 *)&_dsTempPage[2100];
 
 	if (numElements > 150)
 		numElements = 150;
@@ -1315,8 +1332,8 @@ void Screen_EoB::drawExplosion(int scale, int radius, int numElements, int stepS
 				if (py > ymax)
 					py = ymax;
 				if (posWithinRect(px, py, rX1, rY1, rX2, rY2)) {
-					if (_internalBytesPerPixel == 2)
-						setPagePixel16bit(0, px, py, ptr6[i]);
+					if (_internalBytesPerPixel > 1)
+						setPagePixelHiCol(0, px, py, ptr6[i]);
 					else
 						setPagePixel(0, px, py, ptr6[i]);
 				}
@@ -1364,7 +1381,7 @@ void Screen_EoB::drawExplosion(int scale, int radius, int numElements, int stepS
 			}
 
 			assert((ptr8[i] >> 8) < colorTableSize);
-			int pxVal2 = colorTable[ptr8[i] >> 8];
+			uint8 pxVal2 = colorTable[ptr8[i] >> 8];
 			if (pxVal2) {
 				l = 1;
 				if (pxVal1 == _gfxCol && posWithinRect(px, py, rX1, rY1, rX2, rY2))
@@ -1396,10 +1413,10 @@ void Screen_EoB::drawVortex(int numElements, int radius, int stepSize, int, int
 	int16 *yCoords = (int16 *)&_dsTempPage[300];
 	int16 *xMod = (int16 *)&_dsTempPage[600];
 	int16 *yMod = (int16 *)&_dsTempPage[900];
-	int16 *pixBackup = (int16 *)&_dsTempPage[1200];
-	int16 *colTableStep = (int16 *)&_dsTempPage[1500];
-	int16 *colTableIndex = (int16 *)&_dsTempPage[1800];
-	int16 *pixDelay = (int16 *)&_dsTempPage[2100];
+	int32 *pixBackup = (int32 *)&_dsTempPage[1200];
+	int16 *colTableStep = (int16 *)&_dsTempPage[1800];
+	int16 *colTableIndex = (int16 *)&_dsTempPage[2100];
+	int16 *pixDelay = (int16 *)&_dsTempPage[2400];
 
 	hideMouse();
 	int cp = _curPage;
@@ -1472,8 +1489,8 @@ void Screen_EoB::drawVortex(int numElements, int radius, int stepSize, int, int
 			for (int ii = numElements - 1; ii >= 0; ii--) {
 				int16 px = CLIP((xCoords[ii] >> 6) + cx, 0, SCREEN_W - 1);
 				int16 py = CLIP((yCoords[ii] >> 6) + cy, 0, SCREEN_H - 1);
-				if (_internalBytesPerPixel == 2)
-					setPagePixel16bit(0, px, py, pixBackup[ii]);
+				if (_internalBytesPerPixel > 1)
+					setPagePixelHiCol(0, px, py, pixBackup[ii]);
 				else
 					setPagePixel(0, px, py, pixBackup[ii]);
 
@@ -1519,7 +1536,7 @@ void Screen_EoB::drawVortex(int numElements, int radius, int stepSize, int, int
 			int16 px = CLIP((xCoords[ii] >> 6) + cx, 0, SCREEN_W - 1);
 			int16 py = CLIP((yCoords[ii] >> 6) + cy, 0, SCREEN_H - 1);
 
-			uint8 tc1 = ((disorder >> 2) <= d) ? getPagePixel(2, px, py) : 0;
+			int tc1 = ((disorder >> 2) <= d) ? getPagePixel(2, px, py) : 0;
 			pixBackup[ii] = getPagePixel(0, px, py);
 			uint8 tblIndex = CLIP(colTableIndex[ii] >> 8, 0, colorTableSize - 1);
 			uint8 tc2 = colorTable[tblIndex];
@@ -1617,8 +1634,8 @@ int Screen_EoB::getRectSize(int w, int h) {
 
 void Screen_EoB::setFadeTable(const uint8 *table) {
 	_dsShapeFadingTable = table;
-	if (_internalBytesPerPixel == 2)
-		memcpy(&_hiColorNativePalettes[0x100], table, 512);
+	if (_internalBytesPerPixel > 1)
+		memcpy(reinterpret_cast<uint8 *>(_hiColorNativePalettes) + (_internalBytesPerPixel << 8), table, _internalBytesPerPixel << 8);
 }
 
 void Screen_EoB::createColorFadeTable(const uint8 *palData, uint8 *dst, uint8 rootColor, uint8 weight) {
@@ -1664,7 +1681,7 @@ void Screen_EoB::createColorFadeTable(const uint8 *palData, uint8 *dst, uint8 ro
 	}
 }
 
-void Screen_EoB::createHiColorFadeTable(const uint16 *palData, uint16 *dst, uint8 rootColor, uint8 weight) {
+void Screen_EoB::createHiColorFadeTable(const uint16 *palData, void *dst, uint8 rootColor, uint8 weight) {
 	const Graphics::PixelFormat originalFormat(2, 5, 5, 5, 0, 5, 10, 0, 0);
 	uint8 r = 0, b = 0, g = 0;
 	originalFormat.colorToRGB(palData[rootColor], r, g, b);
@@ -1673,8 +1690,15 @@ void Screen_EoB::createHiColorFadeTable(const uint16 *palData, uint16 *dst, uint
 	int root_g = g << 1;
 	int root_b = b << 1;
 
+	uint32 *d32 = reinterpret_cast<uint32*>(dst);
+	uint16 *d16 = reinterpret_cast<uint16*>(dst);
+
 	originalFormat.colorToRGB(palData[0], r, g, b);
-	*dst++ = _outputPixelFormat.RGBToColor(r, g, b);
+
+	if (_outputPixelFormat.bytesPerPixel == 2)
+		*d16++ = _outputPixelFormat.RGBToColor(r, g, b);
+	else
+		*d32++ = _outputPixelFormat.RGBToColor(r, g, b);
 
 	for (int i = 1; i < 256; ++i) {
 		originalFormat.colorToRGB(palData[i], r, g, b);
@@ -1717,18 +1741,25 @@ void Screen_EoB::createHiColorFadeTable(const uint16 *palData, uint16 *dst, uint
 		g = green >> 1;
 		b = blue >> 1;
 
-		*dst++ = _outputPixelFormat.RGBToColor(r, g, b);
+		if (_outputPixelFormat.bytesPerPixel == 2)
+			*d16++ = _outputPixelFormat.RGBToColor(r, g, b);
+		else
+			*d32++ = _outputPixelFormat.RGBToColor(r, g, b);
 	}
 }
 
-const uint16 *Screen_EoB::getCGADitheringTable(int index) {
+const uint16 *Screen_EoB::getCGADitheringTable(int index) const {
 	return !(index & ~1) ? _cgaDitheringTables[index] : 0;
 }
 
-const uint8 *Screen_EoB::getEGADitheringTable() {
+const uint8 *Screen_EoB::getEGADitheringTable() const {
 	return _egaDitheringTable;
 }
 
+int Screen_EoB::bytesPerPixel() const {
+	return _outputPixelFormat.bytesPerPixel;
+}
+
 bool Screen_EoB::loadFont(FontId fontId, const char *filename) {
 	Font *&fnt = _fonts[fontId];
 	int temp = 0;
@@ -1830,8 +1861,11 @@ void Screen_EoB::ditherRect(const uint8 *src, uint8 *dst, int dstPitch, int srcW
 }
 
 void Screen_EoB::drawShapeSetPixel(uint8 *dst, uint8 col) {
-	if (_internalBytesPerPixel == 2) {
-		*(uint16*)dst = _hiColorNativePalettes[(_dsShapeFadingLevel << 8) + col];
+	if (_internalBytesPerPixel == 4) {
+		*reinterpret_cast<uint32*>(dst) = reinterpret_cast<const uint32*>(_hiColorNativePalettes)[(_dsShapeFadingLevel << 8) + col];
+		return;
+	} else if (_internalBytesPerPixel == 2) {
+		*reinterpret_cast<uint16*>(dst) = reinterpret_cast<const uint16*>(_hiColorNativePalettes)[(_dsShapeFadingLevel << 8) + col];
 		return;
 	} else if (_useShapeShading) {
 		if (_dsBackgroundFading) {
@@ -1907,15 +1941,18 @@ bool Screen_EoB::posWithinRect(int posX, int posY, int x1, int y1, int x2, int y
 	return true;
 }
 
-void Screen_EoB::setPagePixel16bit(int pageNum, int x, int y, uint16 color) {
+void Screen_EoB::setPagePixelHiCol(int pageNum, int x, int y, int color) {
 	assert(pageNum < SCREEN_PAGE_NUM);
 	assert(x >= 0 && x < SCREEN_W && y >= 0 && y < SCREEN_H);
-	assert(_internalBytesPerPixel == 2);
+	assert(_internalBytesPerPixel > 1);
 
 	if (pageNum == 0 || pageNum == 1)
 		addDirtyRect(x, y, 1, 1);
 
-	((uint16*)_pagePtrs[pageNum])[y * SCREEN_W + x] = color;
+	if (_internalBytesPerPixel == 4)
+		reinterpret_cast<uint32*>(_pagePtrs[pageNum])[y * SCREEN_W + x] = color;
+	else
+		reinterpret_cast<uint16*>(_pagePtrs[pageNum])[y * SCREEN_W + x] = color;
 }
 
 void Screen_EoB::generateEGADitheringTable(const Palette &pal) {
@@ -2015,7 +2052,7 @@ const uint8 Screen_EoB::_egaMatchTable[] = {
 uint16 *OldDOSFont::_cgaDitheringTable = 0;
 int OldDOSFont::_numRef = 0;
 
-OldDOSFont::OldDOSFont(Common::RenderMode mode, uint8 shadowColor, bool remapCharacters) : _renderMode(mode), _shadowColor(shadowColor), _remapCharacters(remapCharacters), _numGlyphsMax(128), _useOverlay(false), _scaleV(1), _colorMap8bit(0), _colorMap16bit(0) {
+OldDOSFont::OldDOSFont(Common::RenderMode mode, uint8 shadowColor, bool remapCharacters) : _renderMode(mode), _shadowColor(shadowColor), _remapCharacters(remapCharacters), _numGlyphsMax(128), _useOverlay(false), _scaleV(1), _colorMap8bit(nullptr), _hiColorMap(nullptr) {
 	_data = 0;
 	_width = _height = _numGlyphs = 0;
 	_bitmapOffsets = 0;
@@ -2108,8 +2145,8 @@ void OldDOSFont::setColorMap(const uint8 *src) {
 }
 
 void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch, int bpp) const {
-	uint16 color1 = _colorMap8bit[1];
-	uint16 color2 = _colorMap8bit[0];
+	uint32 color1 = _colorMap8bit[1];
+	uint32 color2 = _colorMap8bit[0];
 
 	if (_style == kStyleLeftShadow) {
 		byte *dst2 = dst;
@@ -2121,9 +2158,9 @@ void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch, int bpp) const {
 		}
 	}
 
-	if (bpp == 2) {
-		color1 = _colorMap16bit[1];
-		color2 = _colorMap16bit[0];
+	if (bpp > 1) {
+		color1 = _hiColorMap[1];
+		color2 = _hiColorMap[0];
 	}
 
 	for (int i = 0; i < _scaleV; ++i) {
@@ -2208,14 +2245,19 @@ void OldDOSFont::drawCharIntern(uint16 c, byte *dst, int pitch, int bpp, int col
 					}
 
 					if (s & i) {
-						if (bpp == 2)
-							*(uint16*)dst = col1;
+						if (bpp == 4)
+							*reinterpret_cast<uint32*>(dst) = col1;
+						else if (bpp == 2)
+							*reinterpret_cast<uint16*>(dst) = col1;
 						else if (col1)
 							*dst = col1;
 					} else {
-						if (bpp == 2) {
-							if (col2 != 0xFFFF)
-								*(uint16*)dst = col2;
+						if (bpp == 4) {
+							if (col2)
+								*reinterpret_cast<uint32*>(dst) = col2;
+						} else if (bpp == 2) {
+							if (col2)
+								*reinterpret_cast<uint16*>(dst) = col2;
 						} else if (col2) {
 							*dst = col2;
 						}
diff --git a/engines/kyra/graphics/screen_eob.h b/engines/kyra/graphics/screen_eob.h
index 149fa3b50c1..5bd95090a7e 100644
--- a/engines/kyra/graphics/screen_eob.h
+++ b/engines/kyra/graphics/screen_eob.h
@@ -103,10 +103,11 @@ public:
 
 	void setFadeTable(const uint8 *table);
 	void createColorFadeTable(const uint8 *palData, uint8 *dst, uint8 rootColor, uint8 weight);
-	void createHiColorFadeTable(const uint16 *palData, uint16 *dst, uint8 rootColor, uint8 weight);
+	void createHiColorFadeTable(const uint16 *palData, void *dst, uint8 rootColor, uint8 weight);
 
-	const uint16 *getCGADitheringTable(int index);
-	const uint8 *getEGADitheringTable();
+	const uint16 *getCGADitheringTable(int index) const;
+	const uint8 *getEGADitheringTable() const;
+	int bytesPerPixel() const;
 
 	bool loadFont(FontId fontId, const char *filename) override;
 
@@ -170,7 +171,7 @@ private:
 	void scaleShapeProcessLine4Bit(uint8 *&dst, const uint8 *&src);
 	bool posWithinRect(int posX, int posY, int x1, int y1, int x2, int y2);
 
-	void setPagePixel16bit(int pageNum, int x, int y, uint16 color);
+	void setPagePixelHiCol(int pageNum, int x, int y, int color);
 
 	void generateEGADitheringTable(const Palette &pal);
 	void generateCGADitheringTables(const uint8 *mappingData);
@@ -178,7 +179,7 @@ private:
 	int _dsDiv, _dsRem, _dsScaleTrans;
 	uint8 *_cgaScaleTable;
 	int16 _gfxX, _gfxY;
-	uint16 _gfxCol;
+	int _gfxCol;
 	const uint8 *_gfxMaxY;
 
 	int16 _dsX1, _dsX2, _dsY1, _dsY2;
@@ -199,7 +200,7 @@ private:
 
 	Common::String _cpsFilePattern;
 
-	const uint16 _cursorColorKey16Bit;
+	const uint16 _hiColorCursorColorKey;
 
 	static const uint8 _egaMatchTable[];
 	static const ScreenDim _screenDimTableIntl[];
@@ -273,7 +274,7 @@ public:
 	bool usesOverlay() const override { return _useOverlay; }
 	int getCharWidth(uint16 c) const override;
 	void setColorMap(const uint8 *src) override;
-	void set16bitColorMap(const uint16 *src) override { _colorMap16bit = src; }
+	void setHiColorMap(const uint32 *src) override { _hiColorMap = src; }
 	void setStyles(int styles) override { _style = styles; }
 	void drawChar(uint16 c, byte *dst, int pitch, int bpp) const override;
 
@@ -296,7 +297,7 @@ private:
 	void drawCharIntern(uint16 c, byte *dst, int pitch, int bpp, int col1, int col2) const;
 	virtual uint16 convert(uint16 c) const;
 	Common::RenderMode _renderMode;
-	const uint16 *_colorMap16bit;
+	const uint32 *_hiColorMap;
 	bool _remapCharacters;
 
 	static uint16 *_cgaDitheringTable;
diff --git a/engines/kyra/graphics/screen_eob_towns.cpp b/engines/kyra/graphics/screen_eob_towns.cpp
index 56cd06e00df..bdf1d142e41 100644
--- a/engines/kyra/graphics/screen_eob_towns.cpp
+++ b/engines/kyra/graphics/screen_eob_towns.cpp
@@ -64,11 +64,19 @@ void Screen_EoB::decodeSHP(const uint8 *data, int dstPage) {
 void Screen_EoB::convertToHiColor(int page) {
 	if (!_hiColorNativePalettes)
 		return;
-	uint16 *dst = (uint16 *)getPagePtr(page);
-	memcpy(_hiColorConvertBuffer, dst, SCREEN_H * SCREEN_W);
+	memcpy(_hiColorConvertBuffer, getCPagePtr(page), SCREEN_H * SCREEN_W);
 	const uint8 *src = _hiColorConvertBuffer;
-	for (int s = SCREEN_H * SCREEN_W; s; --s)
-		*dst++ = _hiColorNativePalettes[*src++];
+	if (_internalBytesPerPixel == 4) {
+		uint32 *dst = reinterpret_cast<uint32*>(getPagePtr(page));
+		const uint32 *p = reinterpret_cast<const uint32*>(_hiColorNativePalettes);
+		for (int s = SCREEN_H * SCREEN_W; s; --s)
+			*dst++ = p[*src++];
+	} else {
+		uint16 *dst = reinterpret_cast<uint16*>(getPagePtr(page));
+		const uint16 *p = reinterpret_cast<const uint16*>(_hiColorNativePalettes);
+		for (int s = SCREEN_H * SCREEN_W; s; --s)
+			*dst++ = p[*src++];
+	}
 }
 
 void Screen_EoB::shadeRect(int x1, int y1, int x2, int y2, int shadingLevel) {
@@ -81,15 +89,26 @@ void Screen_EoB::shadeRect(int x1, int y1, int x2, int y2, int shadingLevel) {
 	if (_curPage == 0 || _curPage == 1)
 		addDirtyRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
 
-	uint16 *dst = (uint16*)(getPagePtr(_curPage) + y1 * SCREEN_W * _internalBytesPerPixel + x1 * _internalBytesPerPixel);
-
-	for (; y1 < y2; ++y1) {
-		uint16 *ptr = dst;
-		for (int i = 0; i < x2 - x1; i++) {
-			*ptr = shadeRGBColor(*ptr);
-			ptr++;
+	if (_internalBytesPerPixel == 4) {
+		uint32 *dst = &(reinterpret_cast<uint32*>(getPagePtr(_curPage))[y1 * SCREEN_W + x1]);
+		for (; y1 < y2; ++y1) {
+			uint32 *ptr = dst;
+			for (int i = 0; i < x2 - x1; i++) {
+				*ptr = shadeRGBColor(*ptr);
+				ptr++;
+			}
+			dst += SCREEN_W;
+		}
+	} else {
+		uint16 *dst = &(reinterpret_cast<uint16 *>(getPagePtr(_curPage))[y1 * SCREEN_W + x1]);
+		for (; y1 < y2; ++y1) {
+			uint16 *ptr = dst;
+			for (int i = 0; i < x2 - x1; i++) {
+				*ptr = shadeRGBColor(*ptr);
+				ptr++;
+			}
+			dst += SCREEN_W;
 		}
-		dst += SCREEN_W;
 	}
 
 	_hiColorShadingLevel = l;




More information about the Scummvm-git-logs mailing list