[Scummvm-git-logs] scummvm master -> 97fbe867cb9121863e4ba07443c3852651b7fced

athrxx noreply at scummvm.org
Sat Jul 9 23:04:56 UTC 2022


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

Summary:
bd1f3ff984 COMMON: add CGA Composite render mode
97fbe867cb SCUMM: (MMv1/ZAKv1) - add support for CGA, CGA Composite and Hercules modes


Commit: bd1f3ff9845eb42c0df98d8d6d5da9460a6accd7
    https://github.com/scummvm/scummvm/commit/bd1f3ff9845eb42c0df98d8d6d5da9460a6accd7
Author: athrxx (athrxx at scummvm.org)
Date: 2022-07-10T01:04:38+02:00

Commit Message:
COMMON: add CGA Composite render mode

(for SCUMM v1)

Changed paths:
    common/gui_options.cpp
    common/gui_options.h
    common/rendermode.cpp
    common/rendermode.h


diff --git a/common/gui_options.cpp b/common/gui_options.cpp
index 23a1253f660..39d41275776 100644
--- a/common/gui_options.cpp
+++ b/common/gui_options.cpp
@@ -63,12 +63,13 @@ const struct GameOpt {
 	{ GUIO_RENDERHERCGREEN,		"hercGreen" },
 	{ GUIO_RENDERHERCAMBER,		"hercAmber" },
 	{ GUIO_RENDERCGA,			"cga" },
+	{ GUIO_RENDERCGACOMP,		"cgacomp" },
 	{ GUIO_RENDEREGA,			"ega" },
 	{ GUIO_RENDERVGA,			"vga" },
 	{ GUIO_RENDERAMIGA,			"amiga" },
 	{ GUIO_RENDERFMTOWNS,		"fmtowns" },
 	{ GUIO_RENDERPC9821,		"pc9821" },
-	{ GUIO_RENDERPC9801,		 "pc9801" },
+	{ GUIO_RENDERPC9801,		"pc9801" },
 	{ GUIO_RENDERAPPLE2GS,		"2gs" },
 	{ GUIO_RENDERATARIST,		"atari" },
 	{ GUIO_RENDERMACINTOSH,		"macintosh" },
@@ -145,7 +146,7 @@ const String getGameGUIOptionsDescription(const String &options) {
 	String res;
 
 	for (int i = 0; g_gameOptions[i].desc; i++)
-		if (options.contains(g_gameOptions[i].option[0]))
+		if (options.contains(g_gameOptions[i].option[0])) 
 			res += String(g_gameOptions[i].desc) + " ";
 
 	res.trim();
diff --git a/common/gui_options.h b/common/gui_options.h
index 8c531084cec..c56a5439bd4 100644
--- a/common/gui_options.h
+++ b/common/gui_options.h
@@ -59,6 +59,7 @@
 #define GUIO_RENDERATARIST		"\x22"
 #define GUIO_RENDERMACINTOSH	"\x23"
 #define GUIO_RENDERMACINTOSHBW	"\x28"	// Setting this to 0x28 is not ideal, but there is no free slot left. Maybe we need to migrate to 3-digit numbers...
+#define GUIO_RENDERCGACOMP		"\x29"
 
 #define GUIO_LINKSPEECHTOSFX "\x24"
 #define GUIO_LINKMUSICTOSFX  "\x25"
diff --git a/common/rendermode.cpp b/common/rendermode.cpp
index a9815459664..630e0b78e95 100644
--- a/common/rendermode.cpp
+++ b/common/rendermode.cpp
@@ -34,6 +34,7 @@ const RenderModeDescription g_renderModes[] = {
 	{ "hercGreen", _s("Hercules Green"), kRenderHercG },
 	{ "hercAmber", _s("Hercules Amber"), kRenderHercA },
 	{ "cga", "CGA", kRenderCGA },
+	{ "cgaComp", "CGA Composite", kRenderCGAComp },
 	{ "ega", "EGA", kRenderEGA },
 	{ "vga", "VGA", kRenderVGA },
 	{ "amiga", "Amiga", kRenderAmiga },
@@ -69,7 +70,8 @@ static const RenderGUIOMapping s_renderGUIOMapping[] = {
 	{ kRenderApple2GS,		GUIO_RENDERAPPLE2GS },
 	{ kRenderAtariST,		GUIO_RENDERATARIST },
 	{ kRenderMacintosh,		GUIO_RENDERMACINTOSH },
-	{ kRenderMacintoshBW,	GUIO_RENDERMACINTOSHBW }
+	{ kRenderMacintoshBW,	GUIO_RENDERMACINTOSHBW },
+	{ kRenderCGAComp,	    GUIO_RENDERCGACOMP },
 };
 
 DECLARE_TRANSLATION_ADDITIONAL_CONTEXT("Hercules Green", "lowres")
diff --git a/common/rendermode.h b/common/rendermode.h
index 4fad2b40f87..145e0ffe48e 100644
--- a/common/rendermode.h
+++ b/common/rendermode.h
@@ -57,7 +57,8 @@ enum RenderMode {
 	kRenderApple2GS = 10,
 	kRenderAtariST = 11,
 	kRenderMacintosh = 12,
-	kRenderMacintoshBW = 13
+	kRenderMacintoshBW = 13,
+	kRenderCGAComp = 14
 };
 
 struct RenderModeDescription {


Commit: 97fbe867cb9121863e4ba07443c3852651b7fced
    https://github.com/scummvm/scummvm/commit/97fbe867cb9121863e4ba07443c3852651b7fced
Author: athrxx (athrxx at scummvm.org)
Date: 2022-07-10T01:04:38+02:00

Commit Message:
SCUMM: (MMv1/ZAKv1) - add support for CGA, CGA Composite and Hercules modes

This does not improve anything about these modes for v2 and v3, except:
- brighter CGA colors
- v2 will also get the more accurate Hercules mouse cursor

I will do improve v2/v3 as separate tasks. v3 seems to be mostly fine, anyway, except for the actors (we dither them just like the backgrounds, but that looks different in DOSBox).

Changed paths:
    NEWS.md
    engines/scumm/charset.cpp
    engines/scumm/costume.cpp
    engines/scumm/cursor.cpp
    engines/scumm/gfx.cpp
    engines/scumm/gfx.h
    engines/scumm/input.cpp
    engines/scumm/palette.cpp
    engines/scumm/saveload.cpp
    engines/scumm/script_v2.cpp
    engines/scumm/scumm.cpp
    engines/scumm/scumm.h
    engines/scumm/scumm_v2.h
    engines/scumm/vars.cpp
    engines/scumm/verbs.cpp


diff --git a/NEWS.md b/NEWS.md
index 5735674ad36..60f3965c641 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -20,6 +20,10 @@ For a more comprehensive changelog of the latest experimental code, see:
    - Added support for the Korean version of Legend of Kyrandia 1.
    - Added support for the Hebrew version of Legend of Kyrandia 3.
 
+ SCUMM:
+   - Add support for CGA, CGA Composite and Hercules modes for SCUMM 1
+     versions of Zak McKracken and Maniac Mansion.
+
  Toon:
    - Made game menus behave like in the original.
 
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index b313e807728..ab505f8c295 100644
--- a/engines/scumm/charset.cpp
+++ b/engines/scumm/charset.cpp
@@ -943,6 +943,10 @@ void CharsetRendererV3::drawChar(int chr, Graphics::Surface &s, int x, int y) {
 }
 
 void CharsetRenderer::translateColor() {
+	// Don't do anything for v1 here.
+	if (_vm->_game.version == 1)
+		return;
+
 	// Based on disassembly
 	if (_vm->_renderMode == Common::kRenderCGA) {
 		static const byte CGAtextColorMap[16] = {0,  3, 3, 3, 5, 5, 5,  15,
diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp
index 5bbacde979a..44c242a4849 100644
--- a/engines/scumm/costume.cpp
+++ b/engines/scumm/costume.cpp
@@ -319,9 +319,11 @@ byte ClassicCostumeRenderer::mainRoutine(int xmoveCur, int ymoveCur) {
 	return drawFlag;
 }
 
+// Skin colors
 static const int v1MMActorPalatte1[25] = {
 	8, 8, 8, 8, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
 };
+// Suit colors
 static const int v1MMActorPalatte2[25] = {
 	0, 7, 2, 6, 9, 1, 3, 7, 7, 1, 1, 9, 1, 4, 5, 5, 4, 1, 0, 5, 4, 2, 2, 7, 7
 };
@@ -359,16 +361,16 @@ void ClassicCostumeRenderer::procC64(Codec1 &v1, int actor) {
 	byte palette[4] = { 0, 0, 0, 0 };
 	if (_vm->getCurrentLights() & LIGHTMODE_actor_use_colors) {
 		if (_vm->_game.id == GID_MANIAC) {
-			palette[1] = v1MMActorPalatte1[actor];
-			palette[2] = v1MMActorPalatte2[actor];
+			palette[1] = _vm->_gdi->remapColorToRenderMode(v1MMActorPalatte1[actor]);
+			palette[2] = _vm->_gdi->remapColorToRenderMode(v1MMActorPalatte2[actor]);
 		} else {
 			// Adjust for C64 version of Zak McKracken
-			palette[1] = (_vm->_game.platform == Common::kPlatformC64) ? 10 : 8;
-			palette[2] = _palette[actor];
+			palette[1] = _vm->_gdi->remapColorToRenderMode(_vm->_game.platform == Common::kPlatformC64 ? 10 : 8);
+			palette[2] = _vm->_gdi->remapColorToRenderMode(_palette[actor]);
 		}
 	} else {
-		palette[2] = 11;
-		palette[3] = 11;
+		palette[2] = _vm->_gdi->remapColorToRenderMode(11);
+		palette[3] = _vm->_gdi->remapColorToRenderMode(11);
 	}
 	mask = v1.mask_ptr;
 
diff --git a/engines/scumm/cursor.cpp b/engines/scumm/cursor.cpp
index d0de41ab8ad..34e72766718 100644
--- a/engines/scumm/cursor.cpp
+++ b/engines/scumm/cursor.cpp
@@ -41,7 +41,7 @@ namespace Scumm {
 /*
  * Mouse cursor cycle colors (for the default crosshair).
  */
-static const byte default_v1_cursor_colors[4] = {
+static const byte default_v0_cursor_colors[4] = {
 	1, 1, 12, 11
 };
 
@@ -465,10 +465,14 @@ void ScummEngine_v2::setBuiltinCursor(int idx) {
 
 	memset(_grabbedCursor, 0xFF, sizeof(_grabbedCursor));
 
-	if (_game.version <= 1)
-		color = default_v1_cursor_colors[idx];
+	if (_game.version == 0)
+		color = default_v0_cursor_colors[idx];
+	else if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderCGAComp)
+		color = (idx & 1) * 3;
+	else if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG)
+		color = idx & 1;
 	else
-		color = default_cursor_colors[idx];
+		color = default_cursor_colors[idx];	
 
 	if (_game.platform == Common::kPlatformNES) {
 		_cursor.width = 8;
@@ -561,6 +565,29 @@ void ScummEngine_v2::setBuiltinCursor(int idx) {
 		*(hotspot - (_cursor.width * 5) + 1) = color;
 		*(hotspot + (_cursor.width * 5) - 1) = color;
 		*(hotspot + (_cursor.width * 5) + 1) = color;
+
+		if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
+			const byte *src = &_grabbedCursor[_cursor.width * _cursor.height - 1];
+
+			_cursor.width <<= 1;
+			_cursor.height <<= 1;
+			_cursor.hotspotX <<= 1;
+			_cursor.hotspotY <<= 1;
+
+			byte *dst1 = &_grabbedCursor[_cursor.width * _cursor.height - 1];
+			byte *dst2 = dst1 - _cursor.width;
+
+			while (dst2 >= _grabbedCursor) {
+				for (i = _cursor.width >> 1; i; --i) {
+					*dst2-- = *src;
+					*dst2-- = *src--;
+					*dst1-- = 0xFF;
+					*dst1-- = 0xFF;
+				}
+				dst1 -= _cursor.width;
+				dst2 -= _cursor.width;
+			}
+		}
 	}
 
 	updateCursor();
diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp
index d033d1f3d5f..93d7006a3fa 100644
--- a/engines/scumm/gfx.cpp
+++ b/engines/scumm/gfx.cpp
@@ -246,6 +246,15 @@ GdiV1::GdiV1(ScummEngine *vm) : Gdi(vm) {
 	memset(&_V1, 0, sizeof(_V1));
 }
 
+void GdiV1::setRenderModeColorMap(const byte *map) {
+	_colorMap = map;
+}
+
+byte GdiV1::remapColorToRenderMode(byte col) const {
+	assert(_colorMap);
+	return _colorMap[col];
+}
+
 GdiV2::GdiV2(ScummEngine *vm) : Gdi(vm) {
 	_roomStrips = nullptr;
 }
@@ -736,29 +745,12 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i
 		src = _compositeBuf;
 		pitch = width * vs->format.bytesPerPixel;
 
-		if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
-			ditherHerc(_compositeBuf, _herculesBuf, width, &x, &y, &width, &height);
-
-			src = _herculesBuf + x + y * kHercWidth;
-			pitch = kHercWidth;
-
-			// center image on the screen
-			x += (kHercWidth - _screenWidth * 2) / 2;	// (720 - 320*2)/2 = 40
-		} else if (_useCJKMode && m == 2) {
-			pitch *= m;
-			x *= m;
-			y *= m;
-			width *= m;
-			height *= m;
-		} else {
-			if (_renderMode == Common::kRenderCGA)
-				ditherCGA(_compositeBuf, width, x, y, width, height);
-
+		if (_game.platform == Common::kPlatformNES) {
 			// HACK: This is dirty hack which renders narrow NES rooms centered
 			// NES can address negative number strips and that poses problem for
 			// our code. So instead of adding zillions of fixes and potentially
 			// breaking other games, we shift it right at the rendering stage.
-			if ((_game.platform == Common::kPlatformNES) && (((_NESStartStrip > 0) && (vs->number == kMainVirtScreen)) || (vs->number == kTextVirtScreen))) {
+			if (((_NESStartStrip > 0) && (vs->number == kMainVirtScreen)) || (vs->number == kTextVirtScreen)) {
 				x += 16;
 				while (x + width >= _screenWidth)
 					width -= 16;
@@ -775,7 +767,27 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i
 					_system->copyRectToScreen(blackbuf, 16, 0, 0, 16, 240); // Fix left strip
 				}
 			}
+		} else if (_game.version == 1) {
+			src = postProcessV1Graphics(vs, x, y, width, height);
+			if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG)
+				pitch = kHercWidth;
 
+		} else if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
+			ditherHerc(_compositeBuf, _herculesBuf, width, &x, &y, &width, &height);
+
+			src = _herculesBuf + x + y * kHercWidth;
+			pitch = kHercWidth;
+
+			// center image on the screen
+			x += (kHercWidth - _screenWidth * 2) / 2;	// (720 - 320*2)/2 = 40
+		} else if (_useCJKMode && m == 2) {
+			pitch *= m;
+			x *= m;
+			y *= m;
+			width *= m;
+			height *= m;
+		} else if (_renderMode == Common::kRenderCGA) {
+			ditherCGA(_compositeBuf, width, x, y, width, height);
 		}
 	}
 
@@ -783,6 +795,94 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i
 	_system->copyRectToScreen(src, pitch, x, y, width, height);
 }
 
+const byte *ScummEngine::postProcessV1Graphics(VirtScreen *vs, int &x, int &y, int &width, int &height) const {
+	static const byte zakVrbColMap[] =	{ 0x0, 0x5, 0x5, 0x5, 0xA, 0xA, 0xA, 0xF, 0xF, 0x5, 0x5, 0x5, 0xA, 0xA, 0xF, 0xF };
+	static const byte zakTxtColMap[] =	{ 0x0, 0xF, 0xA, 0x5, 0xA, 0x5, 0x5, 0xF, 0xA, 0xA, 0xA, 0xA, 0xA, 0x5, 0x5, 0xF };
+	static const byte mmVrbColMap[] =	{ 0x0, 0x5, 0x5, 0x5, 0xA, 0xA, 0xA, 0xF, 0xA, 0x5, 0x5, 0x5, 0xA, 0xA, 0xA, 0xF };
+
+	byte mmTxtColMap[16];
+	for (uint8 i = 0; i < ARRAYSIZE(mmTxtColMap); ++i)
+		mmTxtColMap[i] = mmVrbColMap[_gdi->remapColorToRenderMode(i)];
+
+	byte *res = _compositeBuf;
+	byte *dst = _compositeBuf;
+	const byte *src = res;
+
+	if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderCGAComp) {
+		const byte *colMap = (_game.id == GID_ZAK) ? (vs->number == kVerbVirtScreen ? zakVrbColMap : zakTxtColMap) : (vs->number == kVerbVirtScreen ? mmVrbColMap : mmTxtColMap);
+
+		if (vs->number == kMainVirtScreen) {
+			for (int h = height; h; --h) {
+				for (int w = width >> 1; w; --w) {
+					*dst++ = (*src++ >> 2) & 3;
+					*dst++ = *src++ & 3;
+				}
+			}
+		} else {
+			for (int h = height; h; --h) {
+				for (int w = width >> 1; w; --w) {
+					*dst++ = (colMap[*src++] >> 2) & 3;
+					*dst++ = colMap[*src++] & 3;
+				}
+			}
+		}
+
+	} else if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
+		const byte *colMap = (_game.id == GID_ZAK) ? zakVrbColMap : (vs->number == kVerbVirtScreen ? mmVrbColMap : mmTxtColMap);
+		dst = res = _herculesBuf;
+
+		if (vs->number == kMainVirtScreen) {
+			uint32 *dst2 = (uint32*)(dst + kHercWidth);
+			int pitch = (kHercWidth - width) << 1;
+			int pitch2 = pitch >> 2;
+			y = (y - vs->topline) * 2 + vs->topline;
+			height = MIN<int>(height << 1, kHercHeight - y);
+
+			for (int h = height >> 1; h; --h) {
+				for (int w = width >> 1; w; --w) {
+					*dst++ = (*src >> 3) & 1;
+					*dst++ = (*src >> 2) & 1;
+					*dst++ = (*src >> 1) & 1;
+					*dst++ = *src & 1;
+					*dst2++ = 0;
+					src += 2;
+				}
+				dst += pitch;
+				dst2 += pitch2;
+			}
+
+		} else {
+			int pitch = kHercWidth - (width << 1);
+			y -= vs->topline;
+			if (vs->number == kVerbVirtScreen) {
+				y += vs->topline * 2 - 16;
+				height = MIN<int>(height, kHercHeight - y);
+			}
+
+			for (int h = height; h; --h) {
+				for (int w = width; w; --w) {
+					uint8 col = colMap[*src++];
+					*dst++ = (col >> 1) & 1;
+					*dst++ = col & 1;
+				}
+				dst += pitch;
+			}
+		}
+
+		x = x * 2 + 40;
+		width *= 2;
+
+	} else if (vs->number == kTextVirtScreen) {
+		// For EGA, the omly colors that need remapping are for the kTextVirtScreen.
+		for (int h = height; h; --h)  {
+			for (int w = width; w; --w)
+				*dst++ = _gdi->remapColorToRenderMode(*src++);
+		}
+	}
+
+	return res;
+}
+
 // CGA
 // indy3 loom maniac monkey1 zak
 //
@@ -798,17 +898,16 @@ static const byte cgaDither[2][2][16] = {
 	{{0, 0, 1, 1, 0, 2, 2, 3, 0, 3, 1, 1, 3, 3, 1, 3},
 	 {0, 1, 0, 1, 2, 2, 0, 0, 3, 1, 1, 1, 3, 2, 1, 3}}};
 
-// CGA dithers 4x4 square with direct substitutes
-// Odd lines have colors swapped, so there will be checkered patterns.
-// But apparently there is a mistake for 10th color.
 void ScummEngine::ditherCGA(byte *dst, int dstPitch, int x, int y, int width, int height) const {
 	byte *ptr;
 	int idx1, idx2;
-
+	// CGA dithers 4x4 square with direct substitutes
+	// Odd lines have colors swapped, so there will be checkered patterns.
+	// But apparently there is a mistake for 10th color.
 	for (int y1 = 0; y1 < height; y1++) {
 		ptr = dst + y1 * dstPitch;
 
-		if (_game.version == 2)
+		if (_game.version <= 2)
 			idx1 = 0;
 		else
 			idx1 = (y + y1) % 2;
@@ -3172,10 +3271,10 @@ void GdiV1::drawStripV1Background(byte *dst, int dstPitch, int stripnr, int heig
 		charIdx = _V1.picMap[y + stripnr * height] * 8;
 		for (int i = 0; i < 8; i++) {
 			byte c = _V1.charMap[charIdx + i];
-			dst[0] = dst[1] = _V1.colors[(c >> 6) & 3];
-			dst[2] = dst[3] = _V1.colors[(c >> 4) & 3];
-			dst[4] = dst[5] = _V1.colors[(c >> 2) & 3];
-			dst[6] = dst[7] = _V1.colors[(c >> 0) & 3];
+			dst[0] = dst[1] = _colorMap[_V1.colors[(c >> 6) & 3]];
+			dst[2] = dst[3] = _colorMap[_V1.colors[(c >> 4) & 3]];
+			dst[4] = dst[5] = _colorMap[_V1.colors[(c >> 2) & 3]];
+			dst[6] = dst[7] = _colorMap[_V1.colors[(c >> 0) & 3]];
 			dst += dstPitch;
 		}
 	}
@@ -3190,10 +3289,10 @@ void GdiV1::drawStripV1Object(byte *dst, int dstPitch, int stripnr, int width, i
 		charIdx = _V1.objectMap[y * width + stripnr] * 8;
 		for (int i = 0; i < 8; i++) {
 			byte c = _V1.charMap[charIdx + i];
-			dst[0] = dst[1] = _V1.colors[(c >> 6) & 3];
-			dst[2] = dst[3] = _V1.colors[(c >> 4) & 3];
-			dst[4] = dst[5] = _V1.colors[(c >> 2) & 3];
-			dst[6] = dst[7] = _V1.colors[(c >> 0) & 3];
+			dst[0] = dst[1] = _colorMap[_V1.colors[(c >> 6) & 3]];
+			dst[2] = dst[3] = _colorMap[_V1.colors[(c >> 4) & 3]];
+			dst[4] = dst[5] = _colorMap[_V1.colors[(c >> 2) & 3]];
+			dst[6] = dst[7] = _colorMap[_V1.colors[(c >> 0) & 3]];
 			dst += dstPitch;
 		}
 	}
diff --git a/engines/scumm/gfx.h b/engines/scumm/gfx.h
index e3754a152c8..79e92564f95 100644
--- a/engines/scumm/gfx.h
+++ b/engines/scumm/gfx.h
@@ -270,6 +270,9 @@ public:
 	Gdi(ScummEngine *vm);
 	virtual ~Gdi();
 
+	virtual void setRenderModeColorMap(const byte *map) {}
+	virtual byte remapColorToRenderMode(byte col) const { return col; }
+
 	virtual void init();
 	virtual void roomChanged(byte *roomptr);
 	virtual void loadTiles(byte *roomptr);
@@ -404,6 +407,8 @@ protected:
 		byte maskMap[4096], maskChar[4096];
 	} _V1;
 
+	const byte *_colorMap;
+
 protected:
 	void decodeV1Gfx(const byte *src, byte *dst, int size) const;
 
@@ -426,6 +431,9 @@ protected:
 public:
 	GdiV1(ScummEngine *vm);
 
+	void setRenderModeColorMap(const byte *map) override;
+	byte remapColorToRenderMode(byte col) const override;
+
 	void roomChanged(byte *roomptr) override;
 };
 
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index 9d478908150..1ff06dd54f9 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -199,7 +199,16 @@ void ScummEngine::parseEvent(Common::Event event) {
 		if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
 			_mouse.x -= (kHercWidth - _screenWidth * 2) / 2;
 			_mouse.x >>= 1;
-			_mouse.y = _mouse.y * 4 / 7;
+			if (_game.version == 1) {
+				if (_mouse.y >= _virtscr[kMainVirtScreen].topline)
+					_mouse.y = _mouse.y / 2 + _virtscr[kMainVirtScreen].topline / 2;
+				if (_mouse.y > _virtscr[kVerbVirtScreen].topline)
+					_mouse.y += (_mouse.y - _virtscr[kVerbVirtScreen].topline);
+					
+			} else {
+				_mouse.y = _mouse.y * 4 / 7;
+			}
+			
 		} else if (_macScreen || (_useCJKMode && _textSurfaceMultiplier == 2)) {
 			_mouse.x >>= 1;
 			_mouse.y >>= 1;
diff --git a/engines/scumm/palette.cpp b/engines/scumm/palette.cpp
index 474b692e91c..0534127cc5f 100644
--- a/engines/scumm/palette.cpp
+++ b/engines/scumm/palette.cpp
@@ -144,17 +144,11 @@ void ScummEngine::resetPalette() {
 		0xFF, 0x55, 0x55, 	0xFF, 0x55, 0xFF, 	0xFF, 0xFF, 0x55, 	0xFF, 0xFF, 0xFF
 	};
 
-	static const byte tableV1Palette[] = {
-		0x00, 0x00, 0x00, 	0xFF, 0xFF, 0xFF, 	0xAA, 0x00, 0x00, 	0x00, 0xAA, 0xAA,
-		0xAA, 0x00, 0xAA, 	0x00, 0xAA, 0x00, 	0x00, 0x00, 0xAA, 	0xFF, 0xFF, 0x55,
-		0xFF, 0x55, 0x55, 	0xAA, 0x55, 0x00, 	0xFF, 0x55, 0x55, 	0x55, 0x55, 0x55,
-		0xAA, 0xAA, 0xAA, 	0x55, 0xFF, 0x55, 	0x55, 0x55, 0xFF, 	0x55, 0x55, 0x55,
-
-		0xFF, 0x55, 0xFF
-	};
-
-	static const byte tableCGAPalette[] = {
-		0x00, 0x00, 0x00, 	0x00, 0xA8, 0xA8,	0xA8, 0x00, 0xA8, 	0xA8, 0xA8, 0xA8
+	static const byte _cgaColors[4][12] = {
+		{ 0x00, 0x00, 0x00, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0x00, 0xAA, 0x55, 0x00 },
+		{ 0x00, 0x00, 0x00, 0x55, 0xFF, 0x55, 0xFF, 0x55, 0x55, 0xFF, 0xFF, 0x55 },
+		{ 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0x00, 0xAA, 0xAA, 0xAA, 0xAA },
+		{ 0x00, 0x00, 0x00, 0x55, 0xFF, 0xFF, 0xFF, 0x55, 0xFF, 0xFF, 0xFF, 0xFF }
 	};
 
 	static const byte tableHercAPalette[] = {
@@ -194,6 +188,9 @@ void ScummEngine::resetPalette() {
 #endif
 #endif
 
+	int cgaPalIndex = 1;
+	int cgaPalIntensity = 1;
+
 	if (_game.version <= 1) {
 		if (_game.platform == Common::kPlatformApple2GS) {
 			setPaletteFromTable(tableApple2gsPalette, sizeof(tableApple2gsPalette) / 3);
@@ -204,10 +201,14 @@ void ScummEngine::resetPalette() {
 				setPaletteFromTable(tableNESClassicPalette, sizeof(tableNESClassicPalette) / 3);
 			else
 				setPaletteFromTable(tableNESNTSCPalette, sizeof(tableNESNTSCPalette) / 3);
+		} else if (_renderMode == Common::kRenderHercA) {
+			setPaletteFromTable(tableHercAPalette, sizeof(tableHercAPalette) / 3);
+		} else if (_renderMode == Common::kRenderHercG) {
+			setPaletteFromTable(tableHercGPalette, sizeof(tableHercGPalette) / 3);
+		} else if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderCGAComp) {
+			setPaletteFromTable(_cgaColors[cgaPalIndex * 2 + cgaPalIntensity], sizeof(_cgaColors[0]) / 3);
 		} else {
-			setPaletteFromTable(tableV1Palette, sizeof(tableV1Palette) / 3);
-			if (_game.id == GID_ZAK)
-				setPalColor(15, 170, 170, 170);
+			setPaletteFromTable(tableEGAPalette, sizeof(tableEGAPalette) / 3);
 		}
 	} else if (_game.features & GF_16COLOR) {
 		bool setupCursor = false;
@@ -226,7 +227,7 @@ void ScummEngine::resetPalette() {
 			break;
 
 		case Common::kRenderCGA:
-			setPaletteFromTable(tableCGAPalette, sizeof(tableCGAPalette) / 3);
+			setPaletteFromTable(_cgaColors[cgaPalIndex * 2 + cgaPalIntensity], sizeof(_cgaColors[0]) / 3);
 			setupCursor = true;
 			break;
 
@@ -463,6 +464,28 @@ void ScummEngine::setAmigaPaletteFromPtr(const byte *ptr) {
 	setDirtyColors(0, 255);
 }
 
+void ScummEngine::updateColorTableV1(int renderMode) {
+	static const byte v1ColorMaps[5][16] = {
+		// C-64: Just leave everything the way it is
+		{	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,	0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F },
+		// ZAK: EGA, Tandy, MCGA, CGA Composite
+		{	0x00, 0x0F, 0x04, 0x03, 0x05, 0x02, 0x01, 0x0E,	0x0C, 0x06, 0x0D, 0x08, 0x07, 0x0A, 0x09, 0x07 },
+		// ZAK: CGA, CGA B&W, Hercules
+		{	0x00, 0x0F, 0x08, 0x05, 0x0A, 0x05, 0x01, 0x0D,	0x0A, 0x02, 0x0A, 0x0C, 0x0F, 0x0A, 0x05, 0x0C },
+		// MM: EGA, Tandy, MCGA, CGA Composite
+		{	0x00, 0x0F, 0x04, 0x03, 0x05, 0x02, 0x01, 0x0E, 0x0C, 0x06, 0x0C, 0x08, 0x07, 0x0A, 0x09, 0x08 },
+		// MM: CGA, CGA B&W, Hercules
+		{	0x00, 0x0F, 0x08, 0x05, 0x0A, 0x05, 0x01, 0x0D, 0x0A, 0x02, 0x0A, 0x0C, 0x0F, 0x0A, 0x05, 0x0C }
+	};
+
+	int tbl = (_game.platform == Common::kPlatformC64) ? 0 : (_game.id == GID_ZAK ? 1 : 3);
+	if (renderMode == Common::kRenderHercA || renderMode == Common::kRenderHercG || renderMode == Common::kRenderCGA)
+		++tbl;
+
+	assert(_gdi);
+	_gdi->setRenderModeColorMap(v1ColorMaps[tbl]);
+}
+
 void ScummEngine::amigaPaletteFindFirstUsedColor() {
 	for (_amigaFirstUsedColor = 80; _amigaFirstUsedColor < 256; ++_amigaFirstUsedColor) {
 		// We look for the first used color here. If all color components are
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 72d2b35f43e..07b574620a2 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -67,7 +67,7 @@ struct SaveInfoSection {
 
 #define SaveInfoSectionSize (4+4+4 + 4+4 + 4+2)
 
-#define CURRENT_VER 105
+#define CURRENT_VER 106
 #define INFOSECTION_VERSION 2
 
 #pragma mark -
@@ -1567,6 +1567,19 @@ void ScummEngine_v2::saveLoadWithSerializer(Common::Serializer &s) {
 
 	s.syncAsByte(_flashlight.xStrips, VER(99));
 	s.syncAsByte(_flashlight.yStrips, VER(99));
+
+	// Old saves are based on a diffenrent color mapping, so the verb
+	// colors need to be adjusted.
+	if (s.getVersion() < VER(106) && s.isLoading()) {
+		initV2MouseOver();
+		for (int i = 0; i < _numVerbs; ++i) {
+			if (!_verbs[i].verbid)
+				continue;
+			_verbs[i].color = 2;
+			_verbs[i].hicolor = _hiLiteColorVerbArrow;
+			_verbs[i].dimcolor = 8;
+		}
+	}
 }
 
 void ScummEngine_v5::saveLoadWithSerializer(Common::Serializer &s) {
diff --git a/engines/scumm/script_v2.cpp b/engines/scumm/script_v2.cpp
index ba5d347578e..61d1f3a4ed0 100644
--- a/engines/scumm/script_v2.cpp
+++ b/engines/scumm/script_v2.cpp
@@ -849,13 +849,13 @@ void ScummEngine_v2::o2_verbOps() {
 			vs->color = 1;
 			vs->hicolor = 1;
 			vs->dimcolor = 1;
-		} else if (_game.version == 1) {
-			vs->color = (_game.id == GID_MANIAC && (_game.features & GF_DEMO)) ? 16 : 5;
+		} else if (_game.platform == Common::kPlatformC64) {
+			vs->color = 5;
 			vs->hicolor = 7;
 			vs->dimcolor = 11;
 		} else {
 			vs->color = (_game.id == GID_MANIAC && (_game.features & GF_DEMO)) ? 13 : 2;
-			vs->hicolor = 14;
+			vs->hicolor = _hiLiteColorVerbArrow;
 			vs->dimcolor = 8;
 		}
 		vs->type = kTextVerbType;
@@ -1088,10 +1088,11 @@ void ScummEngine_v2::o2_drawSentence() {
 	if (_game.platform == Common::kPlatformNES) {
 		_string[2].xpos = 16;
 		_string[2].color = 0;
-	} else if (_game.version == 1)
+	} else if (_game.platform == Common::kPlatformC64) {
 		_string[2].color = 16;
-	else
+	} else {
 		_string[2].color = 13;
+	}
 
 	byte string[80];
 	const char *ptr = _sentenceBuf.c_str();
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 0ce1f69eab5..9e5d6d94ab3 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -247,10 +247,6 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
 			dialog.runModal();
 		}
 
-	// Check some render mode restrictions
-	if (_game.version <= 1)
-		_renderMode = Common::kRenderDefault;
-
 	switch (_renderMode) {
 	case Common::kRenderHercA:
 	case Common::kRenderHercG:
@@ -258,6 +254,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
 			_renderMode = Common::kRenderDefault;
 		break;
 
+	case Common::kRenderCGAComp:
 	case Common::kRenderCGA:
 	case Common::kRenderEGA:
 	case Common::kRenderAmiga:
@@ -323,6 +320,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
 	if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
 		_herculesBuf = (byte *)malloc(kHercWidth * kHercHeight);
 	}
+	updateColorTableV1(_renderMode);
 
 	_isRTL = (_language == Common::HE_ISR && _game.heversion == 0)
 			&& (_game.id == GID_MANIAC || (_game.version >= 4 && _game.version < 7));
@@ -390,6 +388,7 @@ ScummEngine::~ScummEngine() {
 
 	free(_compositeBuf);
 	free(_herculesBuf);
+	delete[] _ditheringTableV1;
 
 	free(_16BitPalette);
 
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index 052e0082d61..e99fc357e17 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -1025,6 +1025,7 @@ protected:
 	void setPCEPaletteFromPtr(const byte *ptr);
 	void setAmigaPaletteFromPtr(const byte *ptr);
 	virtual void setPaletteFromPtr(const byte *ptr, int numcolor = -1);
+	void updateColorTableV1(int renderMode);
 
 	virtual void setPalColor(int index, int r, int g, int b);
 	void setDirtyColors(int min, int max);
@@ -1059,6 +1060,7 @@ protected:
 	// Screen rendering
 	byte *_compositeBuf;
 	byte *_herculesBuf = nullptr;
+	const uint16 *_ditheringTableV1 = nullptr;
 
 	virtual void drawDirtyScreenParts();
 	void updateDirtyScreen(VirtScreenNumber slot);
@@ -1070,6 +1072,7 @@ protected:
 	void mac_undrawIndy3TextBox();
 	void mac_undrawIndy3CreditsText();
 
+	const byte *postProcessV1Graphics(VirtScreen *vs, int &x, int &y, int &width, int &height) const;
 	void ditherCGA(byte *dst, int dstPitch, int x, int y, int width, int height) const;
 
 public:
diff --git a/engines/scumm/scumm_v2.h b/engines/scumm/scumm_v2.h
index 75f162a3499..37e3048739e 100644
--- a/engines/scumm/scumm_v2.h
+++ b/engines/scumm/scumm_v2.h
@@ -52,6 +52,10 @@ public:
 	int checkV2Inventory(int x, int y);
 	void redrawV2Inventory();
 
+protected:
+	byte _hiLiteColorVerbArrow = 0x0E;
+	byte _hiLiteColorInvSentence = 0x0E;
+
 protected:
 	void setupOpcodes() override;
 
diff --git a/engines/scumm/vars.cpp b/engines/scumm/vars.cpp
index 78aaa55e917..9f445349e66 100644
--- a/engines/scumm/vars.cpp
+++ b/engines/scumm/vars.cpp
@@ -791,7 +791,7 @@ void ScummEngine::resetScummVars() {
 		// Value only used by the Amiga version of Monkey Island 2
 		else if (_game.platform == Common::kPlatformAmiga)
 			VAR(VAR_VIDEOMODE) = 82;
-		else if (_renderMode == Common::kRenderCGA)
+		else if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderCGAComp)
 			VAR(VAR_VIDEOMODE) = 4;
 		else if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG)
 			VAR(VAR_VIDEOMODE) = 30;
diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp
index 309ee8e78e1..66c3e3c7d25 100644
--- a/engines/scumm/verbs.cpp
+++ b/engines/scumm/verbs.cpp
@@ -194,16 +194,20 @@ void ScummEngine_v0::switchActor(int slot) {
 
 void ScummEngine_v2::initV2MouseOver() {
 	int i;
-	int arrow_color, color, hi_color;
-
-	if (_game.version == 2) {
-		color = 13;
-		hi_color = 14;
-		arrow_color = 1;
-	} else {
+	int arrow_color, color;
+	_hiLiteColorVerbArrow = _hiLiteColorInvSentence = 14;
+	if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderCGAComp)
+		_hiLiteColorInvSentence = 15;
+	else if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG)
+		_hiLiteColorVerbArrow = _hiLiteColorInvSentence = 15;
+
+	if (_game.platform == Common::kPlatformC64) {
 		color = 16;
-		hi_color = 7;
+		_hiLiteColorVerbArrow = _hiLiteColorInvSentence = 7;
 		arrow_color = 6;
+	} else {
+		color = 13;
+		arrow_color = 1;
 	}
 
 	_mouseOverBoxV2 = -1;
@@ -217,7 +221,7 @@ void ScummEngine_v2::initV2MouseOver() {
 		_mouseOverBoxesV2[2 * i].rect.bottom = _mouseOverBoxesV2[2 * i].rect.top + 8;
 
 		_mouseOverBoxesV2[2 * i].color = color;
-		_mouseOverBoxesV2[2 * i].hicolor = hi_color;
+		_mouseOverBoxesV2[2 * i].hicolor = _hiLiteColorInvSentence;
 
 		_mouseOverBoxesV2[2 * i + 1].rect.left = 176;
 		_mouseOverBoxesV2[2 * i + 1].rect.right = 320;
@@ -225,7 +229,7 @@ void ScummEngine_v2::initV2MouseOver() {
 		_mouseOverBoxesV2[2 * i + 1].rect.bottom = _mouseOverBoxesV2[2 * i].rect.bottom;
 
 		_mouseOverBoxesV2[2 * i + 1].color = color;
-		_mouseOverBoxesV2[2 * i + 1].hicolor = hi_color;
+		_mouseOverBoxesV2[2 * i + 1].hicolor = _hiLiteColorInvSentence;
 	}
 
 	// Inventory arrows
@@ -236,7 +240,7 @@ void ScummEngine_v2::initV2MouseOver() {
 	_mouseOverBoxesV2[kInventoryUpArrow].rect.bottom = 40;
 
 	_mouseOverBoxesV2[kInventoryUpArrow].color = arrow_color;
-	_mouseOverBoxesV2[kInventoryUpArrow].hicolor = hi_color;
+	_mouseOverBoxesV2[kInventoryUpArrow].hicolor = _hiLiteColorVerbArrow;
 
 	_mouseOverBoxesV2[kInventoryDownArrow].rect.left = 144;
 	_mouseOverBoxesV2[kInventoryDownArrow].rect.right = 176;
@@ -244,7 +248,7 @@ void ScummEngine_v2::initV2MouseOver() {
 	_mouseOverBoxesV2[kInventoryDownArrow].rect.bottom = 48;
 
 	_mouseOverBoxesV2[kInventoryDownArrow].color = arrow_color;
-	_mouseOverBoxesV2[kInventoryDownArrow].hicolor = hi_color;
+	_mouseOverBoxesV2[kInventoryDownArrow].hicolor = _hiLiteColorVerbArrow;
 
 	// Sentence line
 
@@ -254,7 +258,7 @@ void ScummEngine_v2::initV2MouseOver() {
 	_mouseOverBoxesV2[kSentenceLine].rect.bottom = 8;
 
 	_mouseOverBoxesV2[kSentenceLine].color = color;
-	_mouseOverBoxesV2[kSentenceLine].hicolor = hi_color;
+	_mouseOverBoxesV2[kSentenceLine].hicolor = _hiLiteColorInvSentence;
 }
 
 void ScummEngine_v2::initNESMouseOver() {




More information about the Scummvm-git-logs mailing list