[Scummvm-git-logs] scummvm master -> 0add487eea42ee8ce05d271b3715fbcf52ca3b91

AndywinXp noreply at scummvm.org
Sat Aug 31 11:30:19 UTC 2024


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

Summary:
0add487eea SCUMM: SAMNMAX: Implement original noir mode


Commit: 0add487eea42ee8ce05d271b3715fbcf52ca3b91
    https://github.com/scummvm/scummvm/commit/0add487eea42ee8ce05d271b3715fbcf52ca3b91
Author: AndywinXp (andywinxp at gmail.com)
Date: 2024-08-31T13:30:15+02:00

Commit Message:
SCUMM: SAMNMAX: Implement original noir mode

At default, we still use our improved version (for which
I restored the correct accurate grayscale colors, though).

For this original noir mode we have to play without the
"minor bug fixes" enhancement class active.

Changed paths:
    engines/scumm/palette.cpp
    engines/scumm/script_v6.cpp
    engines/scumm/scumm.h


diff --git a/engines/scumm/palette.cpp b/engines/scumm/palette.cpp
index abc47074fe1..629854164ca 100644
--- a/engines/scumm/palette.cpp
+++ b/engines/scumm/palette.cpp
@@ -419,6 +419,9 @@ void ScummEngine::setPaletteFromPtr(const byte *ptr, int numcolor) {
 	}
 
 	setDirtyColors(firstIndex, numcolor - 1);
+
+	if (_game.id == GID_SAMNMAX && !enhancementEnabled(kEnhMinorBugFixes))
+		VAR(77) = 0;
 }
 
 void ScummEngine::setAmigaPaletteFromPtr(const byte *ptr) {
@@ -1180,6 +1183,10 @@ void ScummEngine::darkenPalette(int redScale, int greenScale, int blueScale, int
 			}
 			if (_game.heversion != 70)
 				setDirtyColors(startColor, endColor);
+
+			// Original noir mode behavior
+			if (_game.id == GID_SAMNMAX && !enhancementEnabled(kEnhMinorBugFixes) && VAR(77) == 1)
+				applyGrayscaleToPaletteRange(startColor, endColor);
 		}
 	}
 }
@@ -1384,6 +1391,10 @@ void ScummEngine::copyPalColor(int dst, int src) {
 		_16BitPalette[dst] = get16BitColor(sp[0], sp[1], sp[2]);
 
 	setDirtyColors(dst, dst);
+
+	// Original noir mode behavior
+	if (_game.id == GID_SAMNMAX && !enhancementEnabled(kEnhMinorBugFixes) && VAR(77) == 1)
+		applyGrayscaleToPaletteRange(src, src);
 }
 
 void ScummEngine::setPalColor(int idx, int r, int g, int b) {
@@ -1447,6 +1458,10 @@ void ScummEngine::setPalColor(int idx, int r, int g, int b) {
 		_16BitPalette[idx] = get16BitColor(r, g, b);
 
 	setDirtyColors(idx, idx);
+
+	// Original noir mode behavior
+	if (_game.id == GID_SAMNMAX && !enhancementEnabled(kEnhMinorBugFixes) && VAR(77) == 1)
+		applyGrayscaleToPaletteRange(idx, idx);
 }
 
 void ScummEngine::setCurrentPalette(int palindex) {
@@ -1583,6 +1598,37 @@ uint32 ScummEngine::findClosestPaletteColor(byte *palette, int paletteLength, by
 	return (uint32)_pl.findBestColor(r, g, b, true);
 }
 
+void ScummEngine::applyGrayscaleToPaletteRange(int min, int max) {
+	assertRange(0, min, 256, "ScummEngine::applyGrayscaleToPaletteRange(): min");
+	assertRange(0, max, 256, "ScummEngine::applyGrayscaleToPaletteRange(): min");
+
+	if (min <= max) {
+		int count = max - min + 1;
+		byte *paletteEntry = &_currentPalette[3 * min];
+
+		for (int i = 0; i < count; i++) {
+			int r = paletteEntry[0];
+			int g = paletteEntry[1];
+			int b = paletteEntry[2];
+			byte average = (byte)((r + g + b) / 3);
+
+			// The original checks for colors to be < 126,
+			// but we handle things a little bit differently,
+			// so this is not needed...
+			// 
+			// if (r < 126 || g < 126 || b < 126) {
+				paletteEntry[0] = average;
+				paletteEntry[1] = average;
+				paletteEntry[2] = average;
+			// }
+
+			paletteEntry += 3;
+		}
+	}
+
+	setDirtyColors(min, max);
+}
+
 void ScummEngine::updatePalette() {
 	if (_game.features & GF_16BIT_COLOR)
 		return;
@@ -1623,7 +1669,7 @@ void ScummEngine::updatePalette() {
 
 		_system->getPaletteManager()->setPalette(mouseCursorPalette, 252, 3);
 	} else {
-		bool noir_mode = (_game.id == GID_SAMNMAX && readVar(0x8000));
+		bool noirMode = (_game.id == GID_SAMNMAX && readVar(0x8000));
 		int i;
 
 		first = _palDirtyMin;
@@ -1637,10 +1683,9 @@ void ScummEngine::updatePalette() {
 			else
 				data = _currentPalette + i * 3;
 
-			// Sam & Max film noir mode. Convert the colors to grayscale
-			// before uploading them to the backend.
-
-			if (noir_mode) {
+			// Sam & Max film noir mode - Enhanced version.
+			// Convert the colors to grayscale before uploading them to the backend.
+			if (noirMode && enhancementEnabled(kEnhMinorBugFixes)) {
 				int r, g, b;
 				byte brightness;
 
@@ -1648,7 +1693,7 @@ void ScummEngine::updatePalette() {
 				g = data[1];
 				b = data[2];
 
-				brightness = (byte)((0.299 * r + 0.587 * g + 0.114 * b) + 0.5);
+				brightness = (byte)((r + g + b) / 3);
 
 				*p++ = brightness;
 				*p++ = brightness;
diff --git a/engines/scumm/script_v6.cpp b/engines/scumm/script_v6.cpp
index 4e4fa89e896..6cc2c449684 100644
--- a/engines/scumm/script_v6.cpp
+++ b/engines/scumm/script_v6.cpp
@@ -2180,16 +2180,17 @@ void ScummEngine_v6::o6_roomOps() {
 	case SO_ROOM_NEW_PALETTE:
 		a = pop();
 
-		// This opcode is used when turning off noir mode in Sam & Max,
-		// but since our implementation of this feature doesn't change
-		// the original palette there's no need to reload it. Doing it
-		// this way, we avoid some graphics glitches that the original
-		// interpreter had.
-
-		if (_game.id == GID_SAMNMAX && _currentScript != 0xFF && vm.slot[_currentScript].number == 64)
+		// This opcode is used when turning off noir mode in Sam & Max;
+		// the original exhibited some minor glitches during this mode,
+		// so we have two ways to perform it: the accurate one, and our
+		// improved one...
+		if (_game.id == GID_SAMNMAX && enhancementEnabled(kEnhMinorBugFixes) &&
+			_currentScript != 0xFF && vm.slot[_currentScript].number == 64) {
 			setDirtyColors(0, 255);
-		else
+		} else {
 			setCurrentPalette(a);
+		}
+
 		break;
 	default:
 		error("o6_roomOps: default case %d", subOp);
@@ -3222,17 +3223,21 @@ void ScummEngine_v6::o6_kernelSetFunctions() {
 	case 114:
 		// Sam & Max film noir mode
 		if (_game.id == GID_SAMNMAX) {
-			// At this point ScummVM will already have set
-			// variable 0x8000 to indicate that the game is
-			// in film noir mode. All we have to do here is
-			// to mark the palette as "dirty", because
-			// updatePalette() will desaturate the colors
-			// as they are uploaded to the backend.
-			//
-			// This actually works better than the original
-			// interpreter, where actors would sometimes
-			// still be drawn in color.
-			setDirtyColors(0, 255);
+			if (enhancementEnabled(kEnhMinorBugFixes)) {
+				// At this point ScummVM will already have set
+				// variable 0x8000 to indicate that the game is
+				// in film noir mode. All we have to do here is
+				// to mark the palette as "dirty", because
+				// updatePalette() will desaturate the colors
+				// as they are uploaded to the backend.
+				//
+				// This actually works better than the original
+				// interpreter, where actors would sometimes
+				// still be drawn in color.
+				setDirtyColors(0, 255);
+			} else {
+				applyGrayscaleToPaletteRange(0, 254);
+			}
 		} else
 			error("stub o6_kernelSetFunctions_114()");
 		break;
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index 13b92cbb3db..1b9c0d44609 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -1386,6 +1386,7 @@ protected:
 	virtual void palManipulateInit(int resID, int start, int end, int time);
 	void palManipulate();
 	uint32 findClosestPaletteColor(byte *palette, int paletteLength, byte r, byte g, byte b);
+	void applyGrayscaleToPaletteRange(int min, int max); // For Sam&Max original noir mode
 
 public:
 	uint8 *getHEPaletteSlot(uint16 palSlot);




More information about the Scummvm-git-logs mailing list