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

AndywinXp noreply at scummvm.org
Sat Aug 10 22:09:41 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:
0f87863c7b SCUMM: MANIAC/ZAK (C64): Make screen layout pixel-perfect


Commit: 0f87863c7b1a39abc4f9c65a6b646e9e7dc099e2
    https://github.com/scummvm/scummvm/commit/0f87863c7b1a39abc4f9c65a6b646e9e7dc099e2
Author: AndywinXp (andywinxp at gmail.com)
Date: 2024-08-11T00:09:33+02:00

Commit Message:
SCUMM: MANIAC/ZAK (C64): Make screen layout pixel-perfect

This closes and fixes #11971:
"SCUMM: MANIAC/ZAK C64: GUI & dialog text are incorrectly
positioned on screen, and cursor is improperly layered"

The ticket also mentions improperly layered cursor:
"the pointer cursors pass *behind* the various character sprites
on screen", but there's really nothing we can do about it,
our cursor handling is way too different to function like the original
(and anyway, it looks like a severe C64 hardware limitation quirk...)

Changed paths:
    engines/scumm/charset.cpp
    engines/scumm/gfx_gui.cpp
    engines/scumm/script_v0.cpp
    engines/scumm/script_v2.cpp
    engines/scumm/scumm.cpp
    engines/scumm/string.cpp
    engines/scumm/verbs.cpp


diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index ae63e017fb5..90ab517fd17 100644
--- a/engines/scumm/charset.cpp
+++ b/engines/scumm/charset.cpp
@@ -747,6 +747,7 @@ void CharsetRendererPC::drawBits1(Graphics::Surface &dest, int x, int y, const b
 	byte *dst4 = dst - dest.pitch;
 	byte prevBits = 0;
 	bool leftShadePixel = false;
+	int savedX = x;
 
 	for (y = 0; y < height && y + drawTop < dest.h; y++) {
 		for (x = 0; x < width; x++) {
@@ -775,7 +776,13 @@ void CharsetRendererPC::drawBits1(Graphics::Surface &dest, int x, int y, const b
 					if (prevBits & revBitMask(x % 8))
 						dst4[0] = _shadowColor;
 				}
-				dst[0] = col;
+
+				// Since C64 texts are moved one pixel forward in the X axis, let's avoid
+				// any out-of-line pixel drawing...
+				if (_vm->_game.platform != Common::kPlatformC64 || (savedX + x < dest.pitch)) {
+					dst[0] = col;
+				}
+
 			} else if (!(bits & revBitMask(x % 8))) {
 				leftShadePixel = true;
 				if (y < height - 1 && _vm->_useCJKMode && _vm->_game.platform == Common::kPlatformSegaCD)
diff --git a/engines/scumm/gfx_gui.cpp b/engines/scumm/gfx_gui.cpp
index d03abec50e9..86fed566ce3 100644
--- a/engines/scumm/gfx_gui.cpp
+++ b/engines/scumm/gfx_gui.cpp
@@ -328,6 +328,8 @@ Common::KeyState ScummEngine::showBannerAndPause(int bannerId, int32 waitTime, c
 
 Common::KeyState ScummEngine::printMessageAndPause(const char *msg, int color, int32 waitTime, bool drawOnSentenceLine) {
 	Common::Rect sentenceline;
+	int pixelYOffset = (_game.platform == Common::kPlatformC64) ? 1 : 0;
+	int pixelXOffset = (_game.platform == Common::kPlatformC64) ? 1 : 0;
 
 	// Pause the engine
 	PauseToken pt = pauseEngine();
@@ -336,9 +338,9 @@ Common::KeyState ScummEngine::printMessageAndPause(const char *msg, int color, i
 		setSnailCursor();
 
 		_string[2].charset = 1;
-		_string[2].ypos = _virtscr[kVerbVirtScreen].topline;
-		_string[2].xpos = 0;
-		_string[2].right = _virtscr[kVerbVirtScreen].w - 1;
+		_string[2].ypos = _virtscr[kVerbVirtScreen].topline + pixelYOffset;
+		_string[2].xpos = 0 + pixelXOffset;
+		_string[2].right = _virtscr[kVerbVirtScreen].w - 1 + pixelXOffset;
 		if (_game.platform == Common::kPlatformNES) {
 			_string[2].xpos = 16;
 			_string[2].color = 0;
@@ -376,18 +378,18 @@ Common::KeyState ScummEngine::printMessageAndPause(const char *msg, int color, i
 			sentenceline.left = 16;
 			sentenceline.right = _virtscr[kVerbVirtScreen].w - 1;
 		} else {
-			sentenceline.top = _virtscr[kVerbVirtScreen].topline;
-			sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 8;
-			sentenceline.left = 0;
-			sentenceline.right = _virtscr[kVerbVirtScreen].w - 1;
+			sentenceline.top = _virtscr[kVerbVirtScreen].topline + pixelYOffset;
+			sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 8 + pixelYOffset;
+			sentenceline.left = 0 + pixelXOffset;
+			sentenceline.right = _virtscr[kVerbVirtScreen].w - 1 + pixelXOffset;
 		}
 		restoreBackground(sentenceline);
 		drawString(2, (byte *)string);
 		drawDirtyScreenParts();
 	} else {
-		_string[0].xpos = 0;
+		_string[0].xpos = 0 + pixelXOffset;
 		_string[0].ypos = 0;
-		_string[0].right = _screenWidth - 1;
+		_string[0].right = _screenWidth - 1 + pixelXOffset;
 		_string[0].center = false;
 		_string[0].overhead = false;
 
diff --git a/engines/scumm/script_v0.cpp b/engines/scumm/script_v0.cpp
index 8526dc51cfb..3196fca4bff 100644
--- a/engines/scumm/script_v0.cpp
+++ b/engines/scumm/script_v0.cpp
@@ -393,10 +393,11 @@ void ScummEngine_v0::decodeParseString() {
 	}
 	*ptr = 0;
 
+	int pixelXOffset = (_game.platform == Common::kPlatformC64) ? 1 : 0;
 	int textSlot = 0;
-	_string[textSlot].xpos = 0;
+	_string[textSlot].xpos = 0 + pixelXOffset;
 	_string[textSlot].ypos = 0;
-	_string[textSlot].right = _screenWidth - 1;
+	_string[textSlot].right = _screenWidth - 1 + pixelXOffset;
 	_string[textSlot].center = false;
 	_string[textSlot].overhead = false;
 
@@ -408,10 +409,13 @@ void ScummEngine_v0::decodeParseString() {
 
 void ScummEngine_v0::clearSentenceLine() {
 	Common::Rect sentenceline;
-	sentenceline.top = _virtscr[kVerbVirtScreen].topline;
-	sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 8;
-	sentenceline.left = 0;
-	sentenceline.right = _virtscr[kVerbVirtScreen].w - 1;
+	int pixelYOffset = (_game.platform == Common::kPlatformC64) ? 1 : 0;
+	int pixelXOffset = (_game.platform == Common::kPlatformC64) ? 1 : 0;
+
+	sentenceline.top = _virtscr[kVerbVirtScreen].topline + pixelYOffset;
+	sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 8 + pixelYOffset;
+	sentenceline.left = 0 + pixelXOffset;
+	sentenceline.right = _virtscr[kVerbVirtScreen].w - 1 + pixelXOffset;
 	restoreBackground(sentenceline);
 }
 
@@ -419,6 +423,8 @@ void ScummEngine_v0::flushSentenceLine() {
 	byte string[80];
 	const char *ptr = _sentenceBuf.c_str();
 	int i = 0, len = 0;
+	int pixelYOffset = (_game.platform == Common::kPlatformC64) ? 1 : 0;
+	int pixelXOffset = (_game.platform == Common::kPlatformC64) ? 1 : 0;
 
 	// Maximum length of printable characters
 	int maxChars = 40;
@@ -435,9 +441,9 @@ void ScummEngine_v0::flushSentenceLine() {
 	string[i] = 0;
 
 	_string[2].charset = 1;
-	_string[2].ypos = _virtscr[kVerbVirtScreen].topline;
-	_string[2].xpos = 0;
-	_string[2].right = _virtscr[kVerbVirtScreen].w - 1;
+	_string[2].ypos = _virtscr[kVerbVirtScreen].topline + pixelYOffset;
+	_string[2].xpos = 0 + pixelXOffset;
+	_string[2].right = _virtscr[kVerbVirtScreen].w - 1 + pixelXOffset;
 	_string[2].color = 16;
 	drawString(2, (byte *)string);
 }
diff --git a/engines/scumm/script_v2.cpp b/engines/scumm/script_v2.cpp
index c5bae64707e..30656b0455f 100644
--- a/engines/scumm/script_v2.cpp
+++ b/engines/scumm/script_v2.cpp
@@ -428,10 +428,11 @@ void ScummEngine_v2::decodeParseString() {
 		buffer[29] = 'y';
 	}
 
+	int pixelXOffset = (_game.platform == Common::kPlatformC64) ? 1 : 0;
 	int textSlot = 0;
-	_string[textSlot].xpos = 0;
+	_string[textSlot].xpos = 0 + pixelXOffset;
 	_string[textSlot].ypos = 0;
-	_string[textSlot].right = _screenWidth - 1;
+	_string[textSlot].right = _screenWidth - 1 + pixelXOffset;
 	_string[textSlot].center = false;
 	_string[textSlot].overhead = false;
 
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 3aa6d90f1eb..cbb3a8a2d22 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -1731,12 +1731,16 @@ void ScummEngine::resetScumm() {
 		_macGui->reset();
 	}
 
-	if (_game.version == 0) {
+	if ((_game.id == GID_MANIAC) && (_game.platform == Common::kPlatformC64)) {
+		initScreens(9, 145); // The main virtual screen is offset lower by one pixel
+	} else if (_game.version == 0) {
 		initScreens(8, 144);
 	} else if ((_game.id == GID_MANIAC) && (_game.version <= 1) && !(_game.platform == Common::kPlatformNES)) {
 		initScreens(16, 152);
 	} else if (_game.version >= 7 || _game.heversion >= 71) {
 		initScreens(0, _screenHeight);
+	} else if ((_game.id == GID_ZAK) && (_game.platform == Common::kPlatformC64)) {
+		initScreens(17, 145); // The main virtual screen is offset lower by one pixel
 	} else {
 		initScreens(16, 144);
 	}
diff --git a/engines/scumm/string.cpp b/engines/scumm/string.cpp
index e3a4b59a415..1a6fb5dfc87 100644
--- a/engines/scumm/string.cpp
+++ b/engines/scumm/string.cpp
@@ -848,6 +848,8 @@ void ScummEngine_v2::drawSentence() {
 	Common::Rect sentenceline;
 	const byte *temp;
 	int slot = getVerbSlot(VAR(VAR_SENTENCE_VERB), 0);
+	int pixelYOffset = (_game.platform == Common::kPlatformC64) ? 1 : 0;
+	int pixelXOffset = (_game.platform == Common::kPlatformC64) ? 1 : 0;
 
 	if (!((_userState & USERSTATE_IFACE_SENTENCE) ||
 		  (_game.platform == Common::kPlatformNES && (_userState & USERSTATE_IFACE_ALL))))
@@ -890,9 +892,9 @@ void ScummEngine_v2::drawSentence() {
 	}
 
 	_string[2].charset = 1;
-	_string[2].ypos = _virtscr[kVerbVirtScreen].topline;
-	_string[2].xpos = 0;
-	_string[2].right = _virtscr[kVerbVirtScreen].w - 1;
+	_string[2].ypos = _virtscr[kVerbVirtScreen].topline + pixelYOffset;
+	_string[2].xpos = 0 + pixelXOffset;
+	_string[2].right = _virtscr[kVerbVirtScreen].w - 1 + pixelXOffset;
 	if (_game.platform == Common::kPlatformNES) {
 		_string[2].xpos = 16;
 		_string[2].color = 0;
@@ -930,10 +932,10 @@ void ScummEngine_v2::drawSentence() {
 		sentenceline.left = 16;
 		sentenceline.right = _virtscr[kVerbVirtScreen].w - 1;
 	} else {
-		sentenceline.top = _virtscr[kVerbVirtScreen].topline;
-		sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 8;
-		sentenceline.left = 0;
-		sentenceline.right = _virtscr[kVerbVirtScreen].w - 1;
+		sentenceline.top = _virtscr[kVerbVirtScreen].topline + pixelYOffset;
+		sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 8 + pixelYOffset;
+		sentenceline.left = 0 + pixelXOffset;
+		sentenceline.right = _virtscr[kVerbVirtScreen].w - 1 + pixelXOffset;
 	}
 	restoreBackground(sentenceline);
 
@@ -1167,6 +1169,8 @@ void ScummEngine::displayDialog() {
 			}
 		}
 		if (_game.version <= 3) {
+			if (c == '%')
+				debug("hey");
 			_charset->printChar(c, false);
 			_msgCount += 1;
 		} else {
diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp
index 3e96899250d..fe37f636d99 100644
--- a/engines/scumm/verbs.cpp
+++ b/engines/scumm/verbs.cpp
@@ -136,10 +136,12 @@ void ScummEngine_v0::verbDrawDemoString(int VerbDemoNumber) {
 
 	}
 	string[i] = 0;
+	int pixelYOffset = (_game.platform == Common::kPlatformC64) ? 1 : 0;
+	int pixelXOffset = (_game.platform == Common::kPlatformC64) ? 1 : 0;
 
 	_string[2].charset = 1;
-	_string[2].ypos = _virtscr[kVerbVirtScreen].topline + (8 * VerbDemoNumber);
-	_string[2].xpos = 0;
+	_string[2].ypos = _virtscr[kVerbVirtScreen].topline + (8 * VerbDemoNumber) + pixelYOffset;
+	_string[2].xpos = 0 + pixelXOffset;
 	_string[2].right = _virtscr[kVerbVirtScreen].w - 1;
 	_string[2].color = v0DemoStr[VerbDemoNumber].color;
 	drawString(2, (byte *)string);
@@ -213,19 +215,22 @@ void ScummEngine_v2::initV2MouseOver() {
 
 	_mouseOverBoxV2 = -1;
 
+	int pixelYOffset = (_game.platform == Common::kPlatformC64) ? 1 : 0;
+	int pixelXOffset = (_game.platform == Common::kPlatformC64) ? 1 : 0;
+
 	// Inventory items
 
 	for (i = 0; i < 2; i++) {
-		_mouseOverBoxesV2[2 * i].rect.left = 0;
-		_mouseOverBoxesV2[2 * i].rect.right = 144;
-		_mouseOverBoxesV2[2 * i].rect.top = 32 + 8 * i;
+		_mouseOverBoxesV2[2 * i].rect.left = 0 + pixelXOffset;
+		_mouseOverBoxesV2[2 * i].rect.right = 144 + pixelXOffset;
+		_mouseOverBoxesV2[2 * i].rect.top = 32 + 8 * i + pixelYOffset;
 		_mouseOverBoxesV2[2 * i].rect.bottom = _mouseOverBoxesV2[2 * i].rect.top + 8;
 
 		_mouseOverBoxesV2[2 * i].color = color;
 		_mouseOverBoxesV2[2 * i].hicolor = _hiLiteColorInvSentence;
 
-		_mouseOverBoxesV2[2 * i + 1].rect.left = 176;
-		_mouseOverBoxesV2[2 * i + 1].rect.right = 320;
+		_mouseOverBoxesV2[2 * i + 1].rect.left = 176 + pixelXOffset;
+		_mouseOverBoxesV2[2 * i + 1].rect.right = 320 + pixelXOffset;
 		_mouseOverBoxesV2[2 * i + 1].rect.top = _mouseOverBoxesV2[2 * i].rect.top;
 		_mouseOverBoxesV2[2 * i + 1].rect.bottom = _mouseOverBoxesV2[2 * i].rect.bottom;
 
@@ -235,28 +240,28 @@ void ScummEngine_v2::initV2MouseOver() {
 
 	// Inventory arrows
 
-	_mouseOverBoxesV2[kInventoryUpArrow].rect.left = 144;
-	_mouseOverBoxesV2[kInventoryUpArrow].rect.right = 176;
-	_mouseOverBoxesV2[kInventoryUpArrow].rect.top = 32;
-	_mouseOverBoxesV2[kInventoryUpArrow].rect.bottom = 40;
+	_mouseOverBoxesV2[kInventoryUpArrow].rect.left = 144 + pixelXOffset;
+	_mouseOverBoxesV2[kInventoryUpArrow].rect.right = 176 + pixelXOffset;
+	_mouseOverBoxesV2[kInventoryUpArrow].rect.top = 32 + pixelYOffset;
+	_mouseOverBoxesV2[kInventoryUpArrow].rect.bottom = 40 + pixelYOffset;
 
 	_mouseOverBoxesV2[kInventoryUpArrow].color = arrow_color;
 	_mouseOverBoxesV2[kInventoryUpArrow].hicolor = _hiLiteColorVerbArrow;
 
-	_mouseOverBoxesV2[kInventoryDownArrow].rect.left = 144;
-	_mouseOverBoxesV2[kInventoryDownArrow].rect.right = 176;
-	_mouseOverBoxesV2[kInventoryDownArrow].rect.top = 40;
-	_mouseOverBoxesV2[kInventoryDownArrow].rect.bottom = 48;
+	_mouseOverBoxesV2[kInventoryDownArrow].rect.left = 144 + pixelXOffset;
+	_mouseOverBoxesV2[kInventoryDownArrow].rect.right = 176 + pixelXOffset;
+	_mouseOverBoxesV2[kInventoryDownArrow].rect.top = 40 + pixelYOffset;
+	_mouseOverBoxesV2[kInventoryDownArrow].rect.bottom = 48 + pixelYOffset;
 
 	_mouseOverBoxesV2[kInventoryDownArrow].color = arrow_color;
 	_mouseOverBoxesV2[kInventoryDownArrow].hicolor = _hiLiteColorVerbArrow;
 
 	// Sentence line
 
-	_mouseOverBoxesV2[kSentenceLine].rect.left = 0;
-	_mouseOverBoxesV2[kSentenceLine].rect.right = 320;
-	_mouseOverBoxesV2[kSentenceLine].rect.top = 0;
-	_mouseOverBoxesV2[kSentenceLine].rect.bottom = 8;
+	_mouseOverBoxesV2[kSentenceLine].rect.left = 0 + pixelXOffset;
+	_mouseOverBoxesV2[kSentenceLine].rect.right = 320 + pixelXOffset;
+	_mouseOverBoxesV2[kSentenceLine].rect.top = 0 + pixelYOffset;
+	_mouseOverBoxesV2[kSentenceLine].rect.bottom = 8 + pixelYOffset;
 
 	_mouseOverBoxesV2[kSentenceLine].color = color;
 	_mouseOverBoxesV2[kSentenceLine].hicolor = _hiLiteColorInvSentence;
@@ -422,6 +427,8 @@ void ScummEngine_v2::redrawV2Inventory() {
 	bool isNES = (_game.platform == Common::kPlatformNES);
 	int inventoryArea = isNES ? 48 : 32;
 	int maxChars = isNES ? 13 : 18;
+	int pixelYOffset = (_game.platform == Common::kPlatformC64) ? 1 : 0;
+	int pixelXOffset = (_game.platform == Common::kPlatformC64) ? 1 : 0;
 
 	_mouseOverBoxV2 = -1;
 
@@ -429,10 +436,10 @@ void ScummEngine_v2::redrawV2Inventory() {
 		return;
 
 	// Clear on all invocations
-	inventoryBox.top = vs->topline + inventoryArea;
-	inventoryBox.bottom = vs->topline + vs->h;
-	inventoryBox.left = 0;
-	inventoryBox.right = vs->w;
+	inventoryBox.top = vs->topline + inventoryArea + pixelYOffset;
+	inventoryBox.bottom = vs->topline + vs->h + pixelYOffset;
+	inventoryBox.left = 0 + pixelXOffset;
+	inventoryBox.right = vs->w + pixelXOffset;
 	restoreBackground(inventoryBox);
 
 	_string[1].charset = 1;
@@ -1094,6 +1101,8 @@ void ScummEngine_v7::drawVerb(int verb, int mode) {
 void ScummEngine::drawVerb(int verb, int mode) {
 	VerbSlot *vs;
 	bool tmp;
+	int pixelYOffset = (_game.platform == Common::kPlatformC64) ? (_game.id == GID_ZAK ? 2 : 1) : 0;
+	int pixelXOffset = (_game.platform == Common::kPlatformC64) ? 1 : 0;
 
 	if (_macGui && _game.id == GID_INDY3)
 		return;
@@ -1113,8 +1122,8 @@ void ScummEngine::drawVerb(int verb, int mode) {
 
 		const bool isRtl = _language == Common::HE_ISR && !vs->center;
 		_string[4].charset = vs->charset_nr;
-		_string[4].xpos = isRtl ? vs->origLeft : vs->curRect.left;
-		_string[4].ypos = vs->curRect.top;
+		_string[4].xpos = isRtl ? vs->origLeft : vs->curRect.left + pixelXOffset;
+		_string[4].ypos = vs->curRect.top + pixelYOffset;
 		_string[4].right = _screenWidth - 1;
 		_string[4].center = vs->center;
 
@@ -1141,8 +1150,8 @@ void ScummEngine::drawVerb(int verb, int mode) {
 
 		if (isRtl)
 			vs->curRect.left = _charset->_str.left;
-		vs->curRect.right = (_game.version <= 2) ? MIN<int>(vs->curRect.left + (getResourceSize(rtVerb, verb) - 1) * 8, _screenWidth) : _charset->_str.right;
-		vs->curRect.bottom = _charset->_str.bottom;
+		vs->curRect.right = pixelXOffset + (_game.version <= 2) ? MIN<int>(vs->curRect.left + (getResourceSize(rtVerb, verb) - 1) * 8, _screenWidth) : _charset->_str.right;
+		vs->curRect.bottom = _charset->_str.bottom + pixelYOffset;
 		vs->oldRect = _charset->_str;
 		_charset->_str.left = _charset->_str.right;
 	} else if (_game.id != GID_FT) {




More information about the Scummvm-git-logs mailing list