[Scummvm-git-logs] scummvm master -> e263f77f95c7d6108d7daf219d1ecc2fdb71b10e

sev- noreply at scummvm.org
Thu Apr 17 07:33:06 UTC 2025


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

Summary:
492369e234 QDENGINE: Add support for rgba8888 format
f9abeb8c07 QDENGINE: Fix game_screenshot when using rgba8888
76b6bb38a1 QDENGINE: DT: Fix dumpFrameTiles to support rgba8888
0b2a91727c QDENGINE: make_rgb565u -> make_rgb in qdCamera::graw_grid
a0b960fa5f QDENGINE: Fix incorrect logic in qdCamera::is_walkable()
d3ca5b44df QDENGINE: Add STUBs to untested methods in grDispatcher
349b47908a QDENGINE: Fix incorrect shadowing in shveik
e263f77f95 QDENGINE: Add 16bpp mode option to engine options


Commit: 492369e234e84953d0a1a876f6cdb0f756b80de7
    https://github.com/scummvm/scummvm/commit/492369e234e84953d0a1a876f6cdb0f756b80de7
Author: Alikhan Balpykov (lowliet1990 at mail.ru)
Date: 2025-04-17T15:32:57+08:00

Commit Message:
QDENGINE: Add support for rgba8888 format

Changed paths:
    engines/qdengine/qdengine.cpp
    engines/qdengine/system/graphics/gr_dispatcher.cpp
    engines/qdengine/system/graphics/gr_dispatcher.h
    engines/qdengine/system/graphics/gr_draw_sprite.cpp
    engines/qdengine/system/graphics/gr_draw_sprite_rle.cpp
    engines/qdengine/system/graphics/gr_tile_sprite.cpp


diff --git a/engines/qdengine/qdengine.cpp b/engines/qdengine/qdengine.cpp
index d51966f7a97..ccc3cdcb95e 100644
--- a/engines/qdengine/qdengine.cpp
+++ b/engines/qdengine/qdengine.cpp
@@ -72,7 +72,11 @@ static void qd_show_load_progress(int percents_loaded, void *p);
 QDEngineEngine::QDEngineEngine(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst),
 	_gameDescription(gameDesc), _randomSource("QDEngine") {
 	g_engine = this;
-	_pixelformat = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
+
+	if (syst->getSupportedFormats().front().bytesPerPixel == 4)
+		_pixelformat = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
+	else
+		_pixelformat = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
 
 	_screenW = 640;
 	_screenH = 480;
@@ -467,7 +471,10 @@ void QDEngineEngine::init_graphics() {
 
 	grDispatcher::set_instance(_grD);
 
-	grDispatcher::instance()->init(g_engine->_screenW, g_engine->_screenH, GR_RGB565);
+	if (g_engine->_pixelformat.bytesPerPixel == 4)
+		grDispatcher::instance()->init(g_engine->_screenW, g_engine->_screenH, GR_RGBA8888);
+	else
+		grDispatcher::instance()->init(g_engine->_screenW, g_engine->_screenH, GR_RGB565);
 
 	grDispatcher::instance()->setClip();
 	grDispatcher::instance()->setClipMode(1);
diff --git a/engines/qdengine/system/graphics/gr_dispatcher.cpp b/engines/qdengine/system/graphics/gr_dispatcher.cpp
index e2f0c07ec19..d53f3093ac0 100644
--- a/engines/qdengine/system/graphics/gr_dispatcher.cpp
+++ b/engines/qdengine/system/graphics/gr_dispatcher.cpp
@@ -315,11 +315,16 @@ void grDispatcher::rectangleAlpha(int x, int y, int sx, int sy, uint32 color, in
 	int psy = sy;
 
 	if (!clip_rectangle(x, y, px, py, psx, psy)) return;
-	int dx = 1;
+	int dx = 2;
 	int dy = 1;
 
 	byte mr, mg, mb;
-	split_rgb565u(color, mr, mg, mb);
+	if (_pixel_format == GR_RGB565) {
+		split_rgb565u(color, mr, mg, mb);
+	} else {
+		dx *= 2;
+		split_rgb888(color, mr, mg, mb);
+	}
 
 	mr = (mr * (255 - alpha)) >> 8;
 	mg = (mg * (255 - alpha)) >> 8;
@@ -328,10 +333,16 @@ void grDispatcher::rectangleAlpha(int x, int y, int sx, int sy, uint32 color, in
 	uint32 mcl = make_rgb565u(mr, mg, mb);
 
 	for (int i = 0; i < psy; i++) {
-		uint16 *scr_buf = reinterpret_cast<uint16 *>(_screenBuf->getBasePtr(x, y));
+		byte *scr_buf = reinterpret_cast<byte *>(_screenBuf->getBasePtr(x, y));
 
 		for (int j = 0; j < psx; j++) {
-			*scr_buf = alpha_blend_565(mcl, *scr_buf, alpha);
+			if (_pixel_format == GR_RGB565) {
+				*(uint16 *)scr_buf = alpha_blend_565(mcl, *(uint16 *)scr_buf, alpha);
+			} else {
+				scr_buf[3] = mr + ((alpha * scr_buf[3]) >> 8);
+				scr_buf[2] = mg + ((alpha * scr_buf[2]) >> 8);
+				scr_buf[1] = mb + ((alpha * scr_buf[1]) >> 8);
+			}
 			scr_buf += dx;
 		}
 
@@ -359,25 +370,64 @@ void grDispatcher::resetSurfaceOverride() {
 void grDispatcher::setPixel(int x, int y, int col) {
 	if (_clipMode && !clipCheck(x, y)) return;
 
-	uint16 *p = (uint16 *)(_screenBuf->getBasePtr(x, y));
-	*p = col;
+	if (_pixel_format == GR_RGB565) {
+		uint16 *p = (uint16 *)(_screenBuf->getBasePtr(x, y));
+		*p = col;
+	} else {
+		uint32 *p = (uint32 *)(_screenBuf->getBasePtr(x, y));
+		*p = col << 8;
+	}
+}
+
+void grDispatcher::setPixelFast(byte* buf, uint32 col) {
+	if (_pixel_format == GR_RGB565) {
+		uint16 *p = (uint16 *)buf;
+		*p = col;
+	} else {
+		uint32 *p = (uint32 *)buf;
+		*p = col << 8;
+	}
 }
 
 void grDispatcher::setPixelFast(int x, int y, int col) {
-	uint16 *p = (uint16 *)(_screenBuf->getBasePtr(x, y));
-	*p = col;
+	if (_pixel_format == GR_RGB565) {
+		uint16 *p = (uint16 *)(_screenBuf->getBasePtr(x, y));
+		*p = col;
+	} else {
+		// NOTE
+		// The original had blue and red colors swapped in this method
+		uint32 *p = (uint32 *)(_screenBuf->getBasePtr(x, y));
+		*p = col << 8;
+	}
 }
 
 void grDispatcher::setPixelFast(int x, int y, int r, int g, int b) {
-	uint16 *p = (uint16 *)(_screenBuf->getBasePtr(x, y));
-	*p = (((r >> 3) << 11) + ((g >> 2) << 5) + ((b >> 3) << 0));
+	if (_pixel_format == GR_RGB565) {
+		uint16 *p = (uint16 *)(_screenBuf->getBasePtr(x, y));
+		*p = (((r >> 3) << 11) + ((g >> 2) << 5) + ((b >> 3) << 0));
+	} else {
+		uint32 *p = (uint32 *)(_screenBuf->getBasePtr(x, y));
+		*p = ((r << 24) | (g << 16) | (b << 8));
+	}
 }
 
 void grDispatcher::setPixel(int x, int y, int r, int g, int b) {
 	if (_clipMode && !clipCheck(x, y)) return;
 
-	uint16 *p = (uint16 *)(_screenBuf->getBasePtr(x * 2, y));
-	*p = (((r >> 3) << 11) + ((g >> 2) << 5) + ((b >> 3) << 0));
+	if (_pixel_format == GR_RGB565) {
+		uint16 *p = (uint16 *)(_screenBuf->getBasePtr(x * 2, y));
+		*p = (((r >> 3) << 11) + ((g >> 2) << 5) + ((b >> 3) << 0));
+	} else {
+		uint32 *p = (uint32 *)(_screenBuf->getBasePtr(x, y));
+		*p = ((r << 24) + (g << 16) + (b << 8));
+	}
+}
+
+void grDispatcher::getPixel(int x, int y, uint32 &col) {
+	if (_pixel_format == GR_RGB565)
+		col = *(uint16 *)(_screenBuf->getBasePtr(x, y));
+	else
+		col = *(uint32 *)(_screenBuf->getBasePtr(x, y));
 }
 
 void grDispatcher::getPixel(int x, int y, uint16 &col) {
@@ -385,8 +435,15 @@ void grDispatcher::getPixel(int x, int y, uint16 &col) {
 }
 
 void grDispatcher::getPixel(int x, int y, byte &r, byte &g, byte &b) {
-	uint16 col = *(uint16 *)(_screenBuf->getBasePtr(x, y));
-	split_rgb565u(col, r, g, b);
+	if (_pixel_format == GR_RGB565) {
+		uint16 col = *(uint16 *)(_screenBuf->getBasePtr(x, y));
+		split_rgb565u(col, r, g, b);
+	} else {
+		byte *p = (byte *)(_screenBuf->getBasePtr(x, y));
+		r = p[3];
+		g = p[2];
+		b = p[1];
+	}
 }
 
 bool grDispatcher::clip_line(int &x0, int &y0, int &x1, int &y1) const {
diff --git a/engines/qdengine/system/graphics/gr_dispatcher.h b/engines/qdengine/system/graphics/gr_dispatcher.h
index 9d95e8af922..2753cd800db 100644
--- a/engines/qdengine/system/graphics/gr_dispatcher.h
+++ b/engines/qdengine/system/graphics/gr_dispatcher.h
@@ -73,7 +73,8 @@ enum grPixelFormat {
 	GR_RGB565 = 0,
 	GR_ARGB1555,
 	GR_RGB888,
-	GR_ARGB8888
+	GR_ARGB8888,
+	GR_RGBA8888
 };
 
 class grFont;
@@ -233,6 +234,7 @@ public:
 	void erase(int x, int y, int sx, int sy, int r, int g, int b);
 
 	void setPixel(int x, int y, int col);
+	void setPixelFast(byte *buf, uint32 col);
 	void setPixelFast(int x, int y, int col);
 	void setPixelFast(int x, int y, int r, int g, int b);
 
@@ -241,6 +243,7 @@ public:
 	void surfaceOverride(Graphics::ManagedSurface *target);
 	void resetSurfaceOverride();
 
+	void getPixel(int x, int y, uint32 &col);
 	void getPixel(int x, int y, uint16 &col);
 	void getPixel(int x, int y, byte &r, byte &g, byte &b);
 
@@ -287,6 +290,7 @@ public:
 			return make_rgb555u((color >> 0) & 0xFF, (color >> 8) & 0xFF, (color >> 16) & 0xFF);
 		case GR_RGB888:
 		case GR_ARGB8888:
+		case GR_RGBA8888:
 			return color;
 		}
 
@@ -302,6 +306,8 @@ public:
 		case GR_RGB888:
 		case GR_ARGB8888:
 			return ((b << 16) | (g << 8) | r);
+		case GR_RGBA8888:
+			return ((r << 16) | (g << 8) | b);
 		}
 
 		return 0;
@@ -343,7 +349,7 @@ public:
 		b = ((col & mask_555_b) >> 0) << 3;
 	}
 
-	static inline void split_rgb888(uint32 col, uint32 &r, uint32 &g, uint32 &b) {
+	static inline void split_rgb888(uint32 col, byte &r, byte &g, byte &b) {
 		r = (col >>  0) & 0xFF;
 		g = (col >>  8) & 0xFF;
 		b = (col >> 16) & 0xFF;
diff --git a/engines/qdengine/system/graphics/gr_draw_sprite.cpp b/engines/qdengine/system/graphics/gr_draw_sprite.cpp
index 1d17b28b76f..cc2c8eccdab 100644
--- a/engines/qdengine/system/graphics/gr_draw_sprite.cpp
+++ b/engines/qdengine/system/graphics/gr_draw_sprite.cpp
@@ -75,12 +75,23 @@ void grDispatcher::putSpr_a(int x, int y, int sx, int sy, const byte *p, int mod
 			uint32 a = src_data[3];
 
 			if (a != 255 && clipCheck(x + j, y + i)) {
-				if (a) {
-					uint16 sc;
-					getPixel(x + j, y + i, sc);
-					setPixel(x + j, y + i, alpha_blend_565(make_rgb565u(src_data[2], src_data[1], src_data[0]), sc, a));
-				} else
-					setPixel(x + j, y + i, make_rgb565u(src_data[2], src_data[1], src_data[0]));
+				if (_pixel_format == GR_RGB565) {
+					if (a) {
+						uint16 sc;
+						getPixel(x + j, y + i, sc);
+						setPixel(x + j, y + i, alpha_blend_565(make_rgb565u(src_data[2], src_data[1], src_data[0]), sc, a));
+					} else
+						setPixel(x + j, y + i, make_rgb565u(src_data[2], src_data[1], src_data[0])); 
+				} else {
+					byte sr, sg, sb;
+					getPixel(x + j, y + i, sr, sg, sb);
+
+					uint32 r = src_data[2] + ((a * sr) >> 8);
+					uint32 g = src_data[1] + ((a * sg) >> 8);
+					uint32 b = src_data[0] + ((a * sb) >> 8);
+
+					setPixelFast(x + j, y + i, r, g, b);
+				}
 			}
 			fx += dx;
 		}
@@ -119,19 +130,42 @@ void grDispatcher::putSpr(int x, int y, int sx, int sy, const byte *p, int mode,
 		x1 = 0;
 		ix = -1;
 	}
-	const uint16 *src = reinterpret_cast<const uint16 *>(p);
+	if (_pixel_format == GR_RGB565) {
+		const uint16 *src = reinterpret_cast<const uint16 *>(p);
 
-	for (int i = y0; i != y1; i += iy) {
-		const uint16 *line_src = src + ((fy >> 16) * sx);
+		for (int i = y0; i != y1; i += iy) {
+			const uint16 *line_src = src + ((fy >> 16) * sx);
 
-		fy += dy;
-		fx = (1 << 15);
+			fy += dy;
+			fx = (1 << 15);
 
-		for (int j = x0; j != x1; j += ix) {
-			uint32 cl = line_src[fx >> 16];
-			if (cl)
-				setPixel(x + j, y + i, cl);
-			fx += dx;
+			for (int j = x0; j != x1; j += ix) {
+				uint32 cl = line_src[fx >> 16];
+				if (cl)
+					setPixel(x + j, y + i, cl);
+				fx += dx;
+			}
+		}
+	} else {
+		int sx3 = sx * 3;
+		for (int i = y0; i != y1; i += iy) {
+			const byte *line_src = p + ((fy >> 16) * sx3);
+
+			fy += dy;
+			fx = (1 << 15);
+
+			for (int j = x0; j != x1; j += ix) {
+				int idx = (fx >> 16) * 3;
+
+				uint32 r = line_src[idx + 2];
+				uint32 g = line_src[idx + 1];
+				uint32 b = line_src[idx + 0];
+
+				if (r || g || b)
+					setPixel(x + j, y + i, r, g, b);
+
+				fx += dx;
+			}
 		}
 	}
 	return;
@@ -147,14 +181,17 @@ void grDispatcher::putSpr_a(int x, int y, int sx, int sy, const byte *p, int mod
 	int psy = sy;
 
 	if (!clip_rectangle(x, y, px, py, psx, psy)) return;
-	int dx = -1;
+	int dx = -2;
 	int dy = -1;
 
 	if (mode & GR_FLIP_HORIZONTAL) {
 		x += psx - 1;
 		px = sx - px - psx;
 	} else
-		dx = 1;
+		dx = 2;
+
+	if (_pixel_format == GR_RGBA8888)
+		dx *= 2;
 
 	if (mode & GR_FLIP_VERTICAL) {
 		y += psy - 1;
@@ -167,16 +204,28 @@ void grDispatcher::putSpr_a(int x, int y, int sx, int sy, const byte *p, int mod
 
 	const byte *data_ptr = p + py * sx;
 	for (int i = 0; i < psy; i++) {
-		uint16 *scr_buf = reinterpret_cast<uint16 *>(_screenBuf->getBasePtr(x, y));
+		byte *scr_buf = reinterpret_cast<byte *>(_screenBuf->getBasePtr(x, y));
 		const byte *data_line = data_ptr + px;
 
 		for (int j = 0; j < psx; j++) {
 			uint32 a = data_line[3];
 			if (a != 255) {
-				if (a)
-					*scr_buf = alpha_blend_565(make_rgb565u(data_line[2], data_line[1], data_line[0]), *scr_buf, a);
-				else
-					*scr_buf = make_rgb565u(data_line[2], data_line[1], data_line[0]);
+				if (_pixel_format == GR_RGB565) {
+					if (a)
+						setPixelFast(scr_buf, alpha_blend_565(make_rgb565u(data_line[2], data_line[1], data_line[0]), *(uint16 *)scr_buf, a));
+					else
+						setPixelFast(scr_buf, make_rgb565u(data_line[2], data_line[1], data_line[0]));
+				} else {
+					if (a) {
+						scr_buf[1] = data_line[0] + ((a * scr_buf[1]) >> 8);
+						scr_buf[2] = data_line[1] + ((a * scr_buf[2]) >> 8);
+						scr_buf[3] = data_line[2] + ((a * scr_buf[3]) >> 8);
+					} else {
+						scr_buf[1] = data_line[0];
+						scr_buf[2] = data_line[1];
+						scr_buf[3] = data_line[2];
+					}
+				}
 			}
 
 			scr_buf += dx;
@@ -607,14 +656,17 @@ void grDispatcher::putSpr(int x, int y, int sx, int sy, const byte *p, int mode,
 	int psy = sy;
 
 	if (!clip_rectangle(x, y, px, py, psx, psy)) return;
-	int dx = -1;
+	int dx = -2;
 	int dy = -1;
 
 	if (mode & GR_FLIP_HORIZONTAL) {
 		x += psx - 1;
 		px = sx - px - psx;
 	} else
-		dx = 1;
+		dx = 2;
+
+	if (_pixel_format == GR_RGBA8888)
+		dx *= 2;
 
 	if (mode & GR_FLIP_VERTICAL) {
 		y += psy - 1;
@@ -629,12 +681,12 @@ void grDispatcher::putSpr(int x, int y, int sx, int sy, const byte *p, int mode,
 		const byte *data_ptr = p + py * sx;
 
 		for (int i = 0; i < psy; i++) {
-			uint16 *scr_buf = reinterpret_cast<uint16 *>(_screenBuf->getBasePtr(x, y));
+			byte *scr_buf = reinterpret_cast<byte *>(_screenBuf->getBasePtr(x, y));
 			const byte *data_line = data_ptr + px;
 
 			for (int j = 0; j < psx; j++) {
 				if (data_line[0] || data_line[1] || data_line[2])
-					*scr_buf = make_rgb565u(data_line[2], data_line[1], data_line[0]);
+					setPixelFast(scr_buf, make_rgb(data_line[2], data_line[1], data_line[0]));
 				scr_buf += dx;
 				data_line += 3;
 			}
@@ -649,12 +701,15 @@ void grDispatcher::putSpr(int x, int y, int sx, int sy, const byte *p, int mode,
 		const byte *data_ptr = p + py * sx;
 
 		for (int i = 0; i < psy; i++) {
-			uint16 *scr_buf = reinterpret_cast<uint16 *>(_screenBuf->getBasePtr(x, y));
+			byte *scr_buf = reinterpret_cast<byte *>(_screenBuf->getBasePtr(x, y));
 			const byte *data_line = data_ptr + px;
 
 			for (int j = 0; j < psx; j++) {
-				if (*data_line)
-					*scr_buf = *(const uint16 *)data_line;
+				if (*data_line) {
+					byte r, g, b;
+					split_rgb565u(*(uint16 *)data_line, r, g, b);
+					setPixelFast(scr_buf, make_rgb(r, g, b));
+				}
 				scr_buf += dx;
 				data_line += 2;
 			}
@@ -987,25 +1042,52 @@ void grDispatcher::putChar(int x, int y, uint32 color, int font_sx, int font_sy,
 
 	color = make_rgb(color);
 
-	for (int i = 0; i < psy; i++, y++) {
-		uint16 *scr_buf = reinterpret_cast<uint16 *>(_screenBuf->getBasePtr(x, y));
-		for (int j = 0; j < psx; j++) {
-			uint32 a = alpha_buf[j];
-			uint32 a1 = 255 - a;
-			if (a) {
-				if (a != 255) {
-					uint32 scr_col = *scr_buf;
-					*scr_buf++ = (((((color & mask_565_r) * a) >> 8) & mask_565_r) |
-									((((color & mask_565_g) * a) >> 8) & mask_565_g) |
-									((((color & mask_565_b) * a) >> 8) & mask_565_b)) +
-									(((((scr_col & mask_565_r) * a1) >> 8) & mask_565_r) |
-									((((scr_col & mask_565_g) * a1) >> 8) & mask_565_g) |
-									((((scr_col & mask_565_b) * a1) >> 8) & mask_565_b));
-				} else
-					*scr_buf++ = color;
-			} else scr_buf++;
+	if (_pixel_format == GR_RGB565) {
+		for (int i = 0; i < psy; i++, y++) {
+			uint16 *scr_buf = reinterpret_cast<uint16 *>(_screenBuf->getBasePtr(x, y));
+			for (int j = 0; j < psx; j++) {
+				uint32 a = alpha_buf[j];
+				uint32 a1 = 255 - a;
+				if (a) {
+					if (a != 255) {
+						uint32 scr_col = *scr_buf;
+						*scr_buf++ = (((((color & mask_565_r) * a) >> 8) & mask_565_r) |
+										((((color & mask_565_g) * a) >> 8) & mask_565_g) |
+										((((color & mask_565_b) * a) >> 8) & mask_565_b)) +
+										(((((scr_col & mask_565_r) * a1) >> 8) & mask_565_r) |
+										((((scr_col & mask_565_g) * a1) >> 8) & mask_565_g) |
+										((((scr_col & mask_565_b) * a1) >> 8) & mask_565_b));
+					} else
+						*scr_buf++ = color;
+				} else scr_buf++;
+			}
+			alpha_buf += font_sx;
+		}
+	} else {
+		uint32 r = ((byte *)(&color))[2];
+		uint32 g = ((byte *)(&color))[1];
+		uint32 b = ((byte *)(&color))[0];
+
+		for (int i = 0; i < psy; i++, y++) {
+			byte *scr_buf = reinterpret_cast<byte *>(_screenBuf->getBasePtr(x, y));
+			for (int j = 0; j < psx; j++) {
+				uint32 a = alpha_buf[j];
+				uint32 a1 = 255 - a;
+				if (a) {
+					if (a != 255) {
+						scr_buf[1] = ((r * a) >> 8) + ((a1 * scr_buf[1]) >> 8);
+						scr_buf[2] = ((g * a) >> 8) + ((a1 * scr_buf[2]) >> 8);
+						scr_buf[3] = ((b * a) >> 8) + ((a1 * scr_buf[3]) >> 8);
+					} else {
+						scr_buf[1] = r;
+						scr_buf[2] = g;
+						scr_buf[3] = b;
+					}
+				}
+				scr_buf += 4;
+			}
+			alpha_buf += font_sx;
 		}
-		alpha_buf += font_sx;
 	}
 	return;
 }
@@ -1138,14 +1220,17 @@ void grDispatcher::putSprMask_a(int x, int y, int sx, int sy, const byte *p, uin
 	int psy = sy;
 
 	if (!clip_rectangle(x, y, px, py, psx, psy)) return;
-	int dx = -1;
+	int dx = -2;
 	int dy = -1;
 
 	if (mode & GR_FLIP_HORIZONTAL) {
 		x += psx - 1;
 		px = sx - px - psx;
 	} else
-		dx = 1;
+		dx = 2;
+
+	if (_pixel_format == GR_RGBA8888)
+		dx *= 2;
 
 	if (mode & GR_FLIP_VERTICAL) {
 		y += psy - 1;
@@ -1159,10 +1244,13 @@ void grDispatcher::putSprMask_a(int x, int y, int sx, int sy, const byte *p, uin
 	const byte *data_ptr = p + py * sx + px;
 
 	byte mr, mg, mb;
-	split_rgb565u(mask_color, mr, mg, mb);
+	if (_pixel_format == GR_RGB565)
+		split_rgb565u(mask_color, mr, mg, mb);
+	else
+		split_rgb888(mask_color, mr, mg, mb);
 
 	for (int i = 0; i < psy; i++) {
-		uint16 *scr_buf = (uint16 *)(_screenBuf->getBasePtr(x, y));
+		byte *scr_buf = (byte *)(_screenBuf->getBasePtr(x, y));
 		const byte *data_line = data_ptr;
 
 		for (int j = 0; j < psx; j++) {
@@ -1175,9 +1263,15 @@ void grDispatcher::putSprMask_a(int x, int y, int sx, int sy, const byte *p, uin
 				uint32 g = (mg * (255 - a)) >> 8;
 				uint32 b = (mb * (255 - a)) >> 8;
 
-				uint32 cl = make_rgb565u(r, g, b);
+				if (_pixel_format == GR_RGB565) {
+					uint32 cl = make_rgb565u(r, g, b);
 
-				*scr_buf = alpha_blend_565(cl, *scr_buf, a);
+					setPixelFast(scr_buf, alpha_blend_565(cl, *(uint16 *)scr_buf, a));
+				} else {
+					scr_buf[1] = b + ((a * scr_buf[1]) >> 8);
+					scr_buf[2] = g + ((a * scr_buf[2]) >> 8);
+					scr_buf[3] = r + ((a * scr_buf[3]) >> 8);
+				}
 			}
 			scr_buf += dx;
 			data_line += 4;
@@ -1224,7 +1318,10 @@ void grDispatcher::putSprMask_a(int x, int y, int sx, int sy, const byte *p, uin
 
 	sx <<= 2;
 	byte mr, mg, mb;
-	split_rgb565u(mask_color, mr, mg, mb);
+	if (_pixel_format == GR_RGB565)
+		split_rgb565u(mask_color, mr, mg, mb);
+	else
+		split_rgb888(mask_color, mr, mg, mb);
 
 	for (i = y0; i != y1; i += iy) {
 		const byte *line_src = p + ((fy >> 16) * sx);
@@ -1237,18 +1334,29 @@ void grDispatcher::putSprMask_a(int x, int y, int sx, int sy, const byte *p, uin
 			uint32 a = src_data[3];
 
 			if (a != 255 && clipCheck(x + j, y + i)) {
-				uint16 sc;
+				uint32 sc;
 				getPixel(x + j, y + i, sc);
 
 				a = mask_alpha + ((a * (255 - mask_alpha)) >> 8);
 
-				uint32 r = (mr * (255 - a)) >> 8;
-				uint32 g = (mg * (255 - a)) >> 8;
-				uint32 b = (mb * (255 - a)) >> 8;
+				 uint32 r = (mr * (255 - a)) >> 8;
+				 uint32 g = (mg * (255 - a)) >> 8;
+				 uint32 b = (mb * (255 - a)) >> 8;
+
+				if (_pixel_format == GR_RGB565) {
+					uint32 cl = make_rgb565u(r, g, b);
 
-				uint32 cl = make_rgb565u(r, g, b);
+					setPixel(x + j, y + i, alpha_blend_565(cl, sc, a));
+				} else {
+					byte sr, sg, sb;
+					getPixel(x + j, y + i, sr, sg, sb);
 
-				setPixel(x + j, y + i, alpha_blend_565(cl, sc, a));
+					r = r + ((a * sr) >> 8);
+					g = g + ((a * sg) >> 8);
+					b = b + ((a * sb) >> 8);
+
+					setPixel(x + j, y + i, r, g, b);
+				}
 			}
 			fx += dx;
 		}
diff --git a/engines/qdengine/system/graphics/gr_draw_sprite_rle.cpp b/engines/qdengine/system/graphics/gr_draw_sprite_rle.cpp
index cbba2649d36..99011d9d87c 100644
--- a/engines/qdengine/system/graphics/gr_draw_sprite_rle.cpp
+++ b/engines/qdengine/system/graphics/gr_draw_sprite_rle.cpp
@@ -40,14 +40,17 @@ void grDispatcher::putSpr_rle(int x, int y, int sx, int sy, const class RLEBuffe
 	int psy = sy;
 
 	if (!clip_rectangle(x, y, px, py, psx, psy)) return;
-	int dx = -1;
+	int dx = -2;
 	int dy = -1;
 
 	if (mode & GR_FLIP_HORIZONTAL) {
 		x += (psx - 1);
 		px = sx - px - psx;
 	} else
-		dx = 1;
+		dx = 2;
+
+	if (_pixel_format == GR_RGBA8888)
+		dx *= 2;
 
 	psx += px;
 
@@ -58,7 +61,7 @@ void grDispatcher::putSpr_rle(int x, int y, int sx, int sy, const class RLEBuffe
 		dy = 1;
 
 	for (int i = 0; i < psy; i++) {
-		uint16 *scr_buf = reinterpret_cast<uint16 *>(_screenBuf->getBasePtr(x, y));
+		byte *scr_buf = reinterpret_cast<byte *>(_screenBuf->getBasePtr(x, y));
 
 		const int8 *rle_header = p->header_ptr(py + i);
 		const uint32 *rle_data = p->data_ptr(py + i);
@@ -95,8 +98,8 @@ void grDispatcher::putSpr_rle(int x, int y, int sx, int sy, const class RLEBuffe
 					while (count && j < psx) {
 						if (*rle_data) {
 							const byte *rle_buf = (const byte *)rle_data;
-							uint32 cl = make_rgb565u(rle_buf[2], rle_buf[1], rle_buf[0]);
-							*scr_buf = cl;
+							uint32 cl = make_rgb(rle_buf[2], rle_buf[1], rle_buf[0]);
+							setPixelFast(scr_buf, cl);
 						}
 						scr_buf += dx;
 						count--;
@@ -109,8 +112,8 @@ void grDispatcher::putSpr_rle(int x, int y, int sx, int sy, const class RLEBuffe
 						while (count && j < psx) {
 							if (*rle_data) {
 								const byte *rle_buf = (const byte *)rle_data;
-								uint32 cl = make_rgb565u(rle_buf[2], rle_buf[1], rle_buf[0]);
-								*scr_buf = cl;
+								uint32 cl = make_rgb(rle_buf[2], rle_buf[1], rle_buf[0]);
+								setPixelFast(scr_buf, cl);
 							}
 							scr_buf += dx;
 							rle_data++;
@@ -127,7 +130,15 @@ void grDispatcher::putSpr_rle(int x, int y, int sx, int sy, const class RLEBuffe
 					while (count && j < psx) {
 						const byte *rle_buf = (const byte *)rle_data;
 						uint32 a = rle_buf[3];
-						*scr_buf = alpha_blend_565(make_rgb565u(rle_buf[2], rle_buf[1], rle_buf[0]), *scr_buf, a);
+						if (_pixel_format == GR_RGB565) {
+							*(uint16 *)scr_buf = alpha_blend_565(make_rgb565u(rle_buf[2], rle_buf[1], rle_buf[0]), *(uint16 *)scr_buf, a);
+						} else {
+							if (a != 255) {
+								scr_buf[1] = rle_buf[0] + ((a * scr_buf[1]) >> 8);
+								scr_buf[2] = rle_buf[1] + ((a * scr_buf[2]) >> 8);
+								scr_buf[3] = rle_buf[2] + ((a * scr_buf[3]) >> 8);
+							}
+						}
 						scr_buf += dx;
 						count--;
 						j++;
@@ -139,7 +150,15 @@ void grDispatcher::putSpr_rle(int x, int y, int sx, int sy, const class RLEBuffe
 						while (count && j < psx) {
 							const byte *rle_buf = (const byte *)rle_data;
 							uint32 a = rle_buf[3];
-							*scr_buf = alpha_blend_565(make_rgb565u(rle_buf[2], rle_buf[1], rle_buf[0]), *scr_buf, a);
+							if (_pixel_format == GR_RGB565) {
+								*(uint16 *)scr_buf = alpha_blend_565(make_rgb565u(rle_buf[2], rle_buf[1], rle_buf[0]), *(uint16 *)scr_buf, a);
+							} else {
+								if (a != 255) {
+									scr_buf[1] = rle_buf[0] + ((a * scr_buf[1]) >> 8);
+									scr_buf[2] = rle_buf[1] + ((a * scr_buf[2]) >> 8);
+									scr_buf[3] = rle_buf[2] + ((a * scr_buf[3]) >> 8);
+								}
+							}
 							scr_buf += dx;
 							rle_data++;
 							count--;
@@ -198,7 +217,7 @@ void grDispatcher::putSpr_rle(int x, int y, int sx, int sy, const class RLEBuffe
 				if (clipCheck(x + j, y + i)) {
 					const byte *src_data = line_src + (fx >> 16) * 3;
 					if (src_data[0] || src_data[1] || src_data[2])
-						setPixelFast(x + j, y + i, make_rgb565u(src_data[2], src_data[1], src_data[0]));
+						setPixelFast(x + j, y + i, make_rgb(src_data[2], src_data[1], src_data[0]));
 				}
 				fx += dx;
 			}
@@ -217,15 +236,26 @@ void grDispatcher::putSpr_rle(int x, int y, int sx, int sy, const class RLEBuffe
 
 					uint32 a = src_data[3];
 					if (a != 255) {
-						uint32 cl = make_rgb565u(src_data[2], src_data[1], src_data[0]);
+						if (_pixel_format == GR_RGB565) {
+							uint32 cl = make_rgb565u(src_data[2], src_data[1], src_data[0]);
 
-						if (a) {
-							uint16 scl;
-							getPixel(x + j, y + i, scl);
+							if (a) {
+								uint16 scl;
+								getPixel(x + j, y + i, scl);
 
-							setPixelFast(x + j, y + i, alpha_blend_565(cl, scl, a));
-						} else
-							setPixelFast(x + j, y + i, cl);
+								setPixelFast(x + j, y + i, alpha_blend_565(cl, scl, a));
+							} else
+								setPixelFast(x + j, y + i, cl);
+						} else {
+							byte sr, sg, sb;
+							getPixel(x + j, y + i, sr, sg, sb);
+
+							uint32 r = src_data[2] + ((a * sr) >> 8);
+							uint32 g = src_data[1] + ((a * sg) >> 8);
+							uint32 b = src_data[0] + ((a * sb) >> 8);
+
+							setPixelFast(x + j, y + i, r, g, b);
+						}
 					}
 				}
 				fx += dx;
@@ -245,14 +275,17 @@ void grDispatcher::putSprMask_rle(int x, int y, int sx, int sy, const RLEBuffer
 
 	if (!clip_rectangle(x, y, px, py, psx, psy)) return;
 
-	int dx = -1;
+	int dx = -2;
 	int dy = -1;
 
 	if (mode & GR_FLIP_HORIZONTAL) {
-		x += (psx - 1) * 2;
+		x += (psx - 1);
 		px = sx - px - psx;
 	} else
-		dx = 1;
+		dx = 2;
+
+	if (_pixel_format == GR_RGBA8888)
+		dx *= 2;
 
 	psx += px;
 
@@ -263,7 +296,7 @@ void grDispatcher::putSprMask_rle(int x, int y, int sx, int sy, const RLEBuffer
 		dy = 1;
 
 	for (int i = 0; i < psy; i++) {
-		uint16 *scr_buf = reinterpret_cast<uint16 *>(_screenBuf->getBasePtr(x, y));
+		byte *scr_buf = reinterpret_cast<byte *>(_screenBuf->getBasePtr(x, y));
 
 		const int8 *rle_header = p->header_ptr(py + i);
 		const uint32 *rle_data = p->data_ptr(py + i);
@@ -294,20 +327,31 @@ void grDispatcher::putSprMask_rle(int x, int y, int sx, int sy, const RLEBuffer
 			}
 		}
 		byte mr, mg, mb;
-		split_rgb565u(mask_color, mr, mg, mb);
-
-		mr = (mr * (255 - mask_alpha)) >> 8;
-		mg = (mg * (255 - mask_alpha)) >> 8;
-		mb = (mb * (255 - mask_alpha)) >> 8;
+		if (_pixel_format == GR_RGB565)
+			split_rgb565u(mask_color, mr, mg, mb);
+		else
+			split_rgb888(mask_color, mr, mg, mb);
+
+		if (_pixel_format == GR_RGB565) {
+			mr = (mr * (255 - mask_alpha)) >> 8;
+			mg = (mg * (255 - mask_alpha)) >> 8;
+			mb = (mb * (255 - mask_alpha)) >> 8;
+		}
 
-		uint32 cl = make_rgb565u(mr, mg, mb);
+		uint32 cl = make_rgb(mr, mg, mb);
 
 		if (!alpha_flag) {
 			while (j < psx) {
 				if (count > 0) {
 					while (count && j < psx) {
 						if (*rle_data) {
-							*scr_buf = cl;
+							if (_pixel_format == GR_RGB565) {
+								setPixelFast(scr_buf, cl);
+							} else {
+								scr_buf[3] = ((mr * (255 - mask_alpha)) >> 8) + ((mask_alpha * scr_buf[3]) >> 8);
+								scr_buf[2] = ((mg * (255 - mask_alpha)) >> 8) + ((mask_alpha * scr_buf[2]) >> 8);
+								scr_buf[1] = ((mb * (255 - mask_alpha)) >> 8) + ((mask_alpha * scr_buf[1]) >> 8);
+							}
 						}
 						scr_buf += dx;
 						count--;
@@ -319,7 +363,13 @@ void grDispatcher::putSprMask_rle(int x, int y, int sx, int sy, const RLEBuffer
 						count = -count;
 						while (count && j < psx) {
 							if (*rle_data) {
-								*scr_buf = cl;
+								if (_pixel_format == GR_RGB565) {
+									setPixelFast(scr_buf, cl);
+								} else {
+									scr_buf[3] = ((mr * (255 - mask_alpha)) >> 8) + ((mask_alpha * scr_buf[3]) >> 8);
+									scr_buf[2] = ((mg * (255 - mask_alpha)) >> 8) + ((mask_alpha * scr_buf[2]) >> 8);
+									scr_buf[1] = ((mb * (255 - mask_alpha)) >> 8) + ((mask_alpha * scr_buf[1]) >> 8);
+								}
 							}
 							scr_buf += dx;
 							rle_data++;
@@ -344,8 +394,14 @@ void grDispatcher::putSprMask_rle(int x, int y, int sx, int sy, const RLEBuffer
 							uint32 g = (mg * (255 - a)) >> 8;
 							uint32 b = (mb * (255 - a)) >> 8;
 
-							cl = make_rgb565u(r, g, b);
-							*scr_buf = alpha_blend_565(cl, *scr_buf, a);
+							if (_pixel_format == GR_RGB565) {
+								cl = make_rgb565u(r, g, b);
+								*(uint16 *)scr_buf = alpha_blend_565(cl, *(uint16 *)scr_buf, a);
+							} else {
+								scr_buf[1] = b + ((a * scr_buf[1]) >> 8);
+								scr_buf[2] = g + ((a * scr_buf[2]) >> 8);
+								scr_buf[3] = r + ((a * scr_buf[3]) >> 8);
+							}
 						}
 
 						scr_buf += dx;
@@ -367,8 +423,14 @@ void grDispatcher::putSprMask_rle(int x, int y, int sx, int sy, const RLEBuffer
 								uint32 g = (mg * (255 - a)) >> 8;
 								uint32 b = (mb * (255 - a)) >> 8;
 
-								cl = make_rgb565u(r, g, b);
-								*scr_buf = alpha_blend_565(cl, *scr_buf, a);
+								if (_pixel_format == GR_RGB565) {
+									cl = make_rgb565u(r, g, b);
+									*(uint16 *)scr_buf = alpha_blend_565(cl, *(uint16 *)scr_buf, a);
+								} else {
+									scr_buf[1] = b + ((a * scr_buf[1]) >> 8);
+									scr_buf[2] = g + ((a * scr_buf[2]) >> 8);
+									scr_buf[3] = r + ((a * scr_buf[3]) >> 8);
+								}
 							}
 
 							scr_buf += dx;
@@ -419,13 +481,16 @@ void grDispatcher::putSprMask_rle(int x, int y, int sx, int sy, const RLEBuffer
 	}
 	if (!alpha_flag) {
 		byte mr, mg, mb;
-		split_rgb565u(mask_color, mr, mg, mb);
+		if (_pixel_format == GR_RGB565)
+			split_rgb565u(mask_color, mr, mg, mb);
+		else
+			split_rgb888(mask_color, mr, mg, mb);
 
 		mr = (mr * (255 - mask_alpha)) >> 8;
 		mg = (mg * (255 - mask_alpha)) >> 8;
 		mb = (mb * (255 - mask_alpha)) >> 8;
 
-		uint32 mcl = (_pixel_format == GR_RGB565) ? make_rgb565u(mr, mg, mb) : make_rgb555u(mr, mg, mb);
+		uint32 mcl = make_rgb(mr, mg, mb);
 
 		const byte *line_src = RLEBuffer::get_buffer(0);
 
@@ -439,9 +504,20 @@ void grDispatcher::putSprMask_rle(int x, int y, int sx, int sy, const RLEBuffer
 				if (clipCheck(x + j, y + i)) {
 					const byte *src_buf = line_src + ((fx >> 16) << 2);
 					if (src_buf[0] || src_buf[1] || src_buf[2]) {
-						uint16 scl;
-						getPixel(x + j, y + i, scl);
-						setPixelFast(x + j, y + i, alpha_blend_565(mcl, scl, mask_alpha));
+						if (_pixel_format == GR_RGB565) {
+							uint16 scl;
+							getPixel(x + j, y + i, scl);
+							setPixelFast(x + j, y + i, alpha_blend_565(mcl, scl, mask_alpha));
+						} else {
+							byte sr, sg, sb;
+							getPixel(x + j, y + i, sr, sg, sb);
+
+							uint32 r = mr + ((mask_alpha * sr) >> 8);
+							uint32 g = mg + ((mask_alpha * sg) >> 8);
+							uint32 b = mb + ((mask_alpha * sb) >> 8);
+
+							setPixelFast(x + j, y + i, r, g, b);
+						}
 					}
 				}
 				fx += dx;
@@ -450,7 +526,10 @@ void grDispatcher::putSprMask_rle(int x, int y, int sx, int sy, const RLEBuffer
 	} else {
 		const byte *line_src = RLEBuffer::get_buffer(0);
 		byte mr, mg, mb;
-		split_rgb565u(mask_color, mr, mg, mb);
+		if (_pixel_format == GR_RGB565)
+			split_rgb565u(mask_color, mr, mg, mb);
+		else
+			split_rgb888(mask_color, mr, mg, mb);
 
 		for (int i = y0; i != y1; i += iy) {
 			p->decode_line(fy >> 16);
@@ -463,18 +542,28 @@ void grDispatcher::putSprMask_rle(int x, int y, int sx, int sy, const RLEBuffer
 					const byte *src_buf = line_src + ((fx >> 16) << 2);
 					uint32 a = src_buf[3];
 					if (a != 255) {
-						uint16 scl;
-						getPixel(x + j, y + i, scl);
-
 						a = mask_alpha + ((a * (255 - mask_alpha)) >> 8);
 
 						uint32 r = (mr * (255 - a)) >> 8;
 						uint32 g = (mg * (255 - a)) >> 8;
 						uint32 b = (mb * (255 - a)) >> 8;
 
-						uint32 cl = make_rgb565u(r, g, b);
+						if (_pixel_format == GR_RGB565) {
+							uint16 scl;
+							getPixel(x + j, y + i, scl);
 
-						setPixelFast(x + j, y + i, alpha_blend_565(cl, scl, a));
+							uint16 cl = make_rgb565u(r, g, b);
+							setPixelFast(x + j, y + i, alpha_blend_565(cl, scl, a));
+						} else {
+							byte sr, sg, sb;
+							getPixel(x + j, y + i, sr, sg, sb);
+
+							r = r + ((a * sr) >> 8);
+							g = g + ((a * sg) >> 8);
+							b = b + ((a * sb) >> 8);
+
+							setPixelFast(x + j, y + i, r, g, b);
+						}
 					}
 				}
 				fx += dx;
diff --git a/engines/qdengine/system/graphics/gr_tile_sprite.cpp b/engines/qdengine/system/graphics/gr_tile_sprite.cpp
index f629a7b7bd8..287b55a5bf8 100644
--- a/engines/qdengine/system/graphics/gr_tile_sprite.cpp
+++ b/engines/qdengine/system/graphics/gr_tile_sprite.cpp
@@ -106,14 +106,17 @@ void grDispatcher::putTileSpr(int x, int y, const grTileSprite &sprite, bool has
 	if (clip && !clip_rectangle(x, y, px, py, psx, psy))
 		return;
 
-	int dx = -1;
+	int dx = -2;
 	int dy = -1;
 
 	if (mode & GR_FLIP_HORIZONTAL) {
 		x += psx - 1;
 		px = GR_TILE_SPRITE_SIZE_X - px - psx;
 	} else
-		dx = 1;
+		dx = 2;
+
+	if (_pixel_format == GR_RGBA8888)
+		dx *= 2;
 
 	if (mode & GR_FLIP_VERTICAL) {
 		y += psy - 1;
@@ -127,16 +130,28 @@ void grDispatcher::putTileSpr(int x, int y, const grTileSprite &sprite, bool has
 	const byte *data_ptr = (const byte *)(sprite.data() + px + py * GR_TILE_SPRITE_SIZE_X);
 
 	for (int i = 0; i < psy; i++) {
-		uint16 *scr_buf = reinterpret_cast<uint16 *>(surf->getBasePtr(x, y));
+		byte *scr_buf = reinterpret_cast<byte *>(surf->getBasePtr(x, y));
 		const byte *data_line = data_ptr;
 
 		for (int j = 0; j < psx; j++) {
 			uint32 a = data_line[3];
 			if (a != 255) {
-				if (a)
-					*scr_buf = alpha_blend_565(make_rgb565u(data_line[2], data_line[1], data_line[0]), *scr_buf, a);
-				else
-					*scr_buf = make_rgb565u(data_line[2], data_line[1], data_line[0]);
+				if (_pixel_format == GR_RGB565) {
+					if (a)
+						setPixelFast(scr_buf, alpha_blend_565(make_rgb565u(data_line[2], data_line[1], data_line[0]), *(uint16 *)scr_buf, a));
+					else
+						setPixelFast(scr_buf, make_rgb565u(data_line[2], data_line[1], data_line[0]));
+				} else {
+					if (a) {
+						scr_buf[1] = data_line[0] + ((a * scr_buf[1]) >> 8);
+						scr_buf[2] = data_line[1] + ((a * scr_buf[2]) >> 8);
+						scr_buf[3] = data_line[2] + ((a * scr_buf[3]) >> 8);
+					} else {
+						scr_buf[1] = data_line[0];
+						scr_buf[2] = data_line[1];
+						scr_buf[3] = data_line[2];
+					}
+				}
 			}
 			scr_buf += dx;
 			data_line += 4;


Commit: f9abeb8c07ae22184b9a92d5047d6811e66712fa
    https://github.com/scummvm/scummvm/commit/f9abeb8c07ae22184b9a92d5047d6811e66712fa
Author: Alikhan Balpykov (lowliet1990 at mail.ru)
Date: 2025-04-17T15:32:57+08:00

Commit Message:
QDENGINE: Fix game_screenshot when using rgba8888

Changed paths:
    engines/qdengine/qdcore/qd_game_dispatcher.cpp


diff --git a/engines/qdengine/qdcore/qd_game_dispatcher.cpp b/engines/qdengine/qdcore/qd_game_dispatcher.cpp
index 9bb997367b7..253d36cb256 100644
--- a/engines/qdengine/qdcore/qd_game_dispatcher.cpp
+++ b/engines/qdengine/qdcore/qd_game_dispatcher.cpp
@@ -2846,8 +2846,14 @@ bool qdGameDispatcher::game_screenshot(Graphics::Surface &thumb) const {
 		for (int i = 0; i < h; i++) {
 			uint16 *dst = (uint16 *)thumb.getBasePtr(0, i);
 			for (int j = 0; j < w; j++) {
-				grDispatcher::instance()->getPixel(j, i, col);
-				*dst = col;
+				if (grDispatcher::instance()->pixel_format() == GR_RGB565) {
+					grDispatcher::instance()->getPixel(j, i, col);
+					*dst = col;
+				} else {
+					byte r, g, b;
+					grDispatcher::instance()->getPixel(j, i, r, g, b);
+					*dst = grDispatcher::make_rgb565u(r, g, b);
+				}
 				dst++;
 			}
 		}


Commit: 76b6bb38a19f6ef8eb9bc1cada61aeda438781d2
    https://github.com/scummvm/scummvm/commit/76b6bb38a19f6ef8eb9bc1cada61aeda438781d2
Author: Alikhan Balpykov (lowliet1990 at mail.ru)
Date: 2025-04-17T15:32:57+08:00

Commit Message:
QDENGINE: DT: Fix dumpFrameTiles to support rgba8888

Changed paths:
    engines/qdengine/system/graphics/gr_tile_animation.cpp


diff --git a/engines/qdengine/system/graphics/gr_tile_animation.cpp b/engines/qdengine/system/graphics/gr_tile_animation.cpp
index d605762c52a..d876e9b5eb9 100644
--- a/engines/qdengine/system/graphics/gr_tile_animation.cpp
+++ b/engines/qdengine/system/graphics/gr_tile_animation.cpp
@@ -613,6 +613,7 @@ Graphics::ManagedSurface *grTileAnimation::dumpFrameTiles(int frame_index, float
 	Graphics::ManagedSurface *dstSurf = new Graphics::ManagedSurface(w, h, g_engine->_pixelformat);
 
 	int idx = frameStart + frameTileSize.x * frameTileSize.y * frame_index;
+	int dx = grDispatcher::instance()->pixel_format() == GR_RGB565 ? 2 : 4;
 
 	for (int i = 0; i < frameTileSize.y; i++) {
 		for (int j = 0; j < frameTileSize.x; j++) {
@@ -624,11 +625,11 @@ Graphics::ManagedSurface *grTileAnimation::dumpFrameTiles(int frame_index, float
 			const byte *src = (const byte *)getTile(_frameIndex[idx++]).data();
 
 			for (int yy = 0; yy < GR_TILE_SPRITE_SIZE_Y; yy++) {
-				uint16 *dst = (uint16 *)dstSurf->getBasePtr(j * (GR_TILE_SPRITE_SIZE_X + 1), i * (GR_TILE_SPRITE_SIZE_Y + 1) + yy);
+				byte *dst = (byte *)dstSurf->getBasePtr(j * (GR_TILE_SPRITE_SIZE_X + 1), i * (GR_TILE_SPRITE_SIZE_Y + 1) + yy);
 
 				for (int xx = 0; xx < GR_TILE_SPRITE_SIZE_X; xx++) {
-					*dst = grDispatcher::instance()->make_rgb565u(src[2], src[1], src[0]);
-					dst++;
+					grDispatcher::instance()->setPixelFast(dst, grDispatcher::instance()->make_rgb(src[2], src[1], src[0]));
+					dst += dx;
 					src += 4;
 				}
 			}


Commit: 0b2a91727c08431002b328e88c7623c411fa2f0d
    https://github.com/scummvm/scummvm/commit/0b2a91727c08431002b328e88c7623c411fa2f0d
Author: Alikhan Balpykov (lowliet1990 at mail.ru)
Date: 2025-04-17T15:32:57+08:00

Commit Message:
QDENGINE: make_rgb565u -> make_rgb in qdCamera::graw_grid

Changed paths:
    engines/qdengine/qdcore/qd_camera.cpp


diff --git a/engines/qdengine/qdcore/qd_camera.cpp b/engines/qdengine/qdcore/qd_camera.cpp
index 61bdc7dcbd7..413f4ede096 100644
--- a/engines/qdengine/qdcore/qd_camera.cpp
+++ b/engines/qdengine/qdcore/qd_camera.cpp
@@ -677,14 +677,14 @@ bool qdCamera::draw_grid() const {
 			if (_grid[cnt].height() || _grid[cnt].attributes()) {
 				color = 0;
 				if (_grid[cnt].attributes() & sGridCell::CELL_IMPASSABLE)
-					color = grDispatcher::make_rgb565u(0xff, 0x00, 0x00);
+					color = grDispatcher::instance()->make_rgb(0xff, 0x00, 0x00);
 				else if (_grid[cnt].attributes() & sGridCell::CELL_PERSONAGE_OCCUPIED)
-					color = grDispatcher::make_rgb565u(0xff, 0xff, 0x00);
+					color = grDispatcher::instance()->make_rgb(0xff, 0xff, 0x00);
 				else if (_grid[cnt].height())
-					color = grDispatcher::make_rgb565u(0xff, 0xff, 0xff);
+					color = grDispatcher::instance()->make_rgb(0xff, 0xff, 0xff);
 
 				if (_grid[cnt].attributes() & sGridCell::CELL_OCCUPIED)
-					color = grDispatcher::make_rgb565u(0x00, 0x00, 0xff);
+					color = grDispatcher::instance()->make_rgb(0x00, 0x00, 0xff);
 				if (_grid[cnt].attributes() & sGridCell::CELL_PERSONAGE_PATH)
 					warning("path");
 


Commit: a0b960fa5feff1a1a1608708d1b6ec8f5a061ce2
    https://github.com/scummvm/scummvm/commit/a0b960fa5feff1a1a1608708d1b6ec8f5a061ce2
Author: Alikhan Balpykov (lowliet1990 at mail.ru)
Date: 2025-04-17T15:32:57+08:00

Commit Message:
QDENGINE: Fix incorrect logic in qdCamera::is_walkable()

This change fixes draw_grid() method, where IMPASSIBLE_CELL_CLR was used
for normal cells.

Changed paths:
    engines/qdengine/qdcore/qd_camera.h


diff --git a/engines/qdengine/qdcore/qd_camera.h b/engines/qdengine/qdcore/qd_camera.h
index 8d4901a9222..efca90c220a 100644
--- a/engines/qdengine/qdcore/qd_camera.h
+++ b/engines/qdengine/qdcore/qd_camera.h
@@ -56,7 +56,7 @@ public:
 	~sGridCell() { }
 
 	bool is_walkable() const {
-		return check_attribute(CELL_IMPASSABLE);
+		return !check_attribute(CELL_IMPASSABLE);
 	}
 	void make_impassable() {
 		set_attribute(CELL_IMPASSABLE);


Commit: d3ca5b44df45b208684e51697129885a89a31531
    https://github.com/scummvm/scummvm/commit/d3ca5b44df45b208684e51697129885a89a31531
Author: Alikhan Balpykov (lowliet1990 at mail.ru)
Date: 2025-04-17T15:32:57+08:00

Commit Message:
QDENGINE: Add STUBs to untested methods in grDispatcher

Changed paths:
    engines/qdengine/system/graphics/gr_draw_sprite.cpp


diff --git a/engines/qdengine/system/graphics/gr_draw_sprite.cpp b/engines/qdengine/system/graphics/gr_draw_sprite.cpp
index cc2c8eccdab..4affa7ce078 100644
--- a/engines/qdengine/system/graphics/gr_draw_sprite.cpp
+++ b/engines/qdengine/system/graphics/gr_draw_sprite.cpp
@@ -279,6 +279,8 @@ void grDispatcher::putSpr_rot(const Vect2i &pos, const Vect2i &size, const byte
 	int sin_a = round(sn * float(1 << F_PREC));
 	int cos_a = round(cs * float(1 << F_PREC));
 
+	warning("STUB: grDispatcher::putSpr_rot");
+
 	if (has_alpha) {
 		for (int y = 0; y <= sy; y++) {
 			uint16 *screen_ptr = (uint16 *)_screenBuf->getBasePtr(x0, y + y0);
@@ -370,6 +372,8 @@ void grDispatcher::putSpr_rot(const Vect2i &pos, const Vect2i &size, const byte
 	Vect2i iscale = Vect2i(scale.x * float(1 << F_PREC), scale.y * float(1 << F_PREC));
 	Vect2i scaled_size = Vect2i(iscale.x * size.x, iscale.y * size.y);
 
+	warning("STUB: grDispatcher::putSpr_rot (scaled)");
+
 	if (has_alpha) {
 		for (int y = 0; y <= sy; y++) {
 			uint16 *screen_ptr = (uint16 *)_screenBuf->getBasePtr(x0, y + y0);
@@ -457,6 +461,8 @@ void grDispatcher::putSprMask_rot(const Vect2i &pos, const Vect2i &size, const b
 	int sin_a = round(sn * float(1 << F_PREC));
 	int cos_a = round(cs * float(1 << F_PREC));
 
+	warning("STUB: grDispatcher::putSprMask_rot");
+
 	if (has_alpha) {
 		byte mr, mg, mb;
 		split_rgb565u(mask_color, mr, mg, mb);
@@ -567,6 +573,8 @@ void grDispatcher::putSprMask_rot(const Vect2i &pos, const Vect2i &size, const b
 	Vect2i iscale = Vect2i(scale.x * float(1 << F_PREC), scale.y * float(1 << F_PREC));
 	Vect2i scaled_size = Vect2i(iscale.x * size.x, iscale.y * size.y);
 
+	warning("STUB: grDispatcher::putSprMask_rot (scaled)");
+
 	if (has_alpha) {
 		byte mr, mg, mb;
 		split_rgb565u(mask_color, mr, mg, mb);
@@ -1192,6 +1200,8 @@ void grDispatcher::putSprMask(int x, int y, int sx, int sy, const byte *p, uint3
 
 	sx *= 3;
 
+	warning("STUB: grDispatcher::putSprMask (scaled)");
+
 	for (int i = y0; i != y1; i += iy) {
 		const byte *line_src = p + ((fy >> 16) * sx);
 


Commit: 349b47908a6843f2ed898a415d210970c72a2c16
    https://github.com/scummvm/scummvm/commit/349b47908a6843f2ed898a415d210970c72a2c16
Author: Alikhan Balpykov (lowliet1990 at mail.ru)
Date: 2025-04-17T15:32:57+08:00

Commit Message:
QDENGINE: Fix incorrect shadowing in shveik

This change fixes bug when rgb565 is used. The code for RGBA8888 mode was
already correct.

Changed paths:
    engines/qdengine/system/graphics/gr_draw_sprite_rle.cpp


diff --git a/engines/qdengine/system/graphics/gr_draw_sprite_rle.cpp b/engines/qdengine/system/graphics/gr_draw_sprite_rle.cpp
index 99011d9d87c..64f8842db99 100644
--- a/engines/qdengine/system/graphics/gr_draw_sprite_rle.cpp
+++ b/engines/qdengine/system/graphics/gr_draw_sprite_rle.cpp
@@ -332,15 +332,13 @@ void grDispatcher::putSprMask_rle(int x, int y, int sx, int sy, const RLEBuffer
 		else
 			split_rgb888(mask_color, mr, mg, mb);
 
-		if (_pixel_format == GR_RGB565) {
+		if (!alpha_flag) {
 			mr = (mr * (255 - mask_alpha)) >> 8;
 			mg = (mg * (255 - mask_alpha)) >> 8;
 			mb = (mb * (255 - mask_alpha)) >> 8;
-		}
 
-		uint32 cl = make_rgb(mr, mg, mb);
+			uint32 cl = make_rgb(mr, mg, mb);
 
-		if (!alpha_flag) {
 			while (j < psx) {
 				if (count > 0) {
 					while (count && j < psx) {
@@ -348,9 +346,9 @@ void grDispatcher::putSprMask_rle(int x, int y, int sx, int sy, const RLEBuffer
 							if (_pixel_format == GR_RGB565) {
 								setPixelFast(scr_buf, cl);
 							} else {
-								scr_buf[3] = ((mr * (255 - mask_alpha)) >> 8) + ((mask_alpha * scr_buf[3]) >> 8);
-								scr_buf[2] = ((mg * (255 - mask_alpha)) >> 8) + ((mask_alpha * scr_buf[2]) >> 8);
-								scr_buf[1] = ((mb * (255 - mask_alpha)) >> 8) + ((mask_alpha * scr_buf[1]) >> 8);
+								scr_buf[3] = mr + ((mask_alpha * scr_buf[3]) >> 8);
+								scr_buf[2] = mg + ((mask_alpha * scr_buf[2]) >> 8);
+								scr_buf[1] = mb + ((mask_alpha * scr_buf[1]) >> 8);
 							}
 						}
 						scr_buf += dx;
@@ -366,9 +364,9 @@ void grDispatcher::putSprMask_rle(int x, int y, int sx, int sy, const RLEBuffer
 								if (_pixel_format == GR_RGB565) {
 									setPixelFast(scr_buf, cl);
 								} else {
-									scr_buf[3] = ((mr * (255 - mask_alpha)) >> 8) + ((mask_alpha * scr_buf[3]) >> 8);
-									scr_buf[2] = ((mg * (255 - mask_alpha)) >> 8) + ((mask_alpha * scr_buf[2]) >> 8);
-									scr_buf[1] = ((mb * (255 - mask_alpha)) >> 8) + ((mask_alpha * scr_buf[1]) >> 8);
+									scr_buf[3] = mr + ((mask_alpha * scr_buf[3]) >> 8);
+									scr_buf[2] = mg + ((mask_alpha * scr_buf[2]) >> 8);
+									scr_buf[1] = mb + ((mask_alpha * scr_buf[1]) >> 8);
 								}
 							}
 							scr_buf += dx;
@@ -395,7 +393,7 @@ void grDispatcher::putSprMask_rle(int x, int y, int sx, int sy, const RLEBuffer
 							uint32 b = (mb * (255 - a)) >> 8;
 
 							if (_pixel_format == GR_RGB565) {
-								cl = make_rgb565u(r, g, b);
+								uint16 cl = make_rgb565u(r, g, b);
 								*(uint16 *)scr_buf = alpha_blend_565(cl, *(uint16 *)scr_buf, a);
 							} else {
 								scr_buf[1] = b + ((a * scr_buf[1]) >> 8);
@@ -424,7 +422,7 @@ void grDispatcher::putSprMask_rle(int x, int y, int sx, int sy, const RLEBuffer
 								uint32 b = (mb * (255 - a)) >> 8;
 
 								if (_pixel_format == GR_RGB565) {
-									cl = make_rgb565u(r, g, b);
+									uint16 cl = make_rgb565u(r, g, b);
 									*(uint16 *)scr_buf = alpha_blend_565(cl, *(uint16 *)scr_buf, a);
 								} else {
 									scr_buf[1] = b + ((a * scr_buf[1]) >> 8);


Commit: e263f77f95c7d6108d7daf219d1ecc2fdb71b10e
    https://github.com/scummvm/scummvm/commit/e263f77f95c7d6108d7daf219d1ecc2fdb71b10e
Author: Alikhan Balpykov (lowliet1990 at mail.ru)
Date: 2025-04-17T15:32:57+08:00

Commit Message:
QDENGINE: Add 16bpp mode option to engine options

Changed paths:
  A engines/qdengine/dialogs.cpp
  A engines/qdengine/dialogs.h
    engines/qdengine/detection.cpp
    engines/qdengine/metaengine.cpp
    engines/qdengine/metaengine.h
    engines/qdengine/module.mk
    engines/qdengine/qdengine.cpp
    engines/qdengine/qdengine.h


diff --git a/engines/qdengine/detection.cpp b/engines/qdengine/detection.cpp
index 2ac38ba67e3..ccb5f084ebe 100644
--- a/engines/qdengine/detection.cpp
+++ b/engines/qdengine/detection.cpp
@@ -45,6 +45,7 @@ static const DebugChannelDef debugFlagList[] = {
 	{ QDEngine::kDebugQuant, "quant", "Enable quant tracing"},
 	{ QDEngine::kDebugMinigames, "minigames", "Enable minigames tracing"},
 	{ QDEngine::kDebugText, "text", "Enable text tracing"},
+	{ QDEngine::kDebug16BppMode, "16bpp", "Enable 16bpp mode"},
 	DEBUG_CHANNEL_END
 };
 
diff --git a/engines/qdengine/dialogs.cpp b/engines/qdengine/dialogs.cpp
new file mode 100644
index 00000000000..5efae03868b
--- /dev/null
+++ b/engines/qdengine/dialogs.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/translation.h"
+
+#include "gui/ThemeEval.h"
+
+#include "qdengine/dialogs.h"
+
+namespace QDEngine {
+
+QdOptionsWidget::QdOptionsWidget(GuiObject* boss, const Common::String& name, const Common::String& domain) : OptionsContainerWidget(boss, name, "QdGameOptionsDialog", domain),
+	_16bppModeCheckbox(nullptr) {
+	_16bppModeCheckbox = new GUI::CheckboxWidget(widgetsBoss(), "QdGameOptionsDialog.16bppMode", _("Enable 16 bits per pixel mode"), _("Enable this if backend does not support 32bpp and/or to debug graphics"));
+}
+
+QdOptionsWidget::~QdOptionsWidget() {
+}
+
+void QdOptionsWidget::defineLayout(GUI::ThemeEval &layouts, const Common::String &layoutName, const Common::String &overlayedLayout) const {
+	layouts.addDialog(layoutName, overlayedLayout)
+		.addLayout(GUI::ThemeLayout::kLayoutVertical)
+			.addPadding(0, 0, 0, 0)
+			.addWidget("16bppMode", "Checkbox")
+		.closeLayout()
+	.closeDialog();
+}
+
+void QdOptionsWidget::load() {
+	if (_16bppModeCheckbox)
+		_16bppModeCheckbox->setState(ConfMan.getBool("16bpp"));
+}
+
+bool QdOptionsWidget::save() {
+	if (_16bppModeCheckbox)
+		ConfMan.setBool("16bpp", _16bppModeCheckbox->getState());
+
+	return true;
+}
+
+} // End of namespace QDEngine
diff --git a/engines/qdengine/dialogs.h b/engines/qdengine/dialogs.h
new file mode 100644
index 00000000000..a541f42b804
--- /dev/null
+++ b/engines/qdengine/dialogs.h
@@ -0,0 +1,46 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef QDENGINE_DIALOGS_H
+#define QDENGINE_DIALOGS_H
+
+#include "gui/dialog.h"
+#include "gui/widget.h"
+
+namespace QDEngine {
+
+class QdOptionsWidget : public GUI::OptionsContainerWidget {
+public:
+	QdOptionsWidget(GuiObject *boss, const Common::String &name, const Common::String &domain);
+	~QdOptionsWidget() override;
+
+	void load() override;
+	bool save() override;
+
+private:
+	void defineLayout(GUI::ThemeEval &layouts, const Common::String &layoutName, const Common::String &overlayedLayout) const override;
+
+	GUI::CheckboxWidget *_16bppModeCheckbox;
+};
+
+} // End of namespace QDEngine
+
+#endif
diff --git a/engines/qdengine/metaengine.cpp b/engines/qdengine/metaengine.cpp
index 55daecbface..a52a191cd65 100644
--- a/engines/qdengine/metaengine.cpp
+++ b/engines/qdengine/metaengine.cpp
@@ -19,6 +19,7 @@
  *
  */
 
+#include "qdengine/dialogs.h"
 #include "qdengine/metaengine.h"
 #include "qdengine/qdengine.h"
 #include "qdengine/qdcore/qd_game_dispatcher.h"
@@ -32,6 +33,10 @@ Common::Error QDEngineMetaEngine::createInstance(OSystem *syst, Engine **engine,
 	return Common::kNoError;
 }
 
+GUI::OptionsContainerWidget *QDEngineMetaEngine::buildEngineOptionsWidget(GUI::GuiObject *boss, const Common::String &name, const Common::String &target) const {
+	return new QDEngine::QdOptionsWidget(boss, name, target);
+}
+
 bool QDEngineMetaEngine::hasFeature(MetaEngineFeature f) const {
 	return
 	    (f == kSavesUseExtendedFormat) ||
diff --git a/engines/qdengine/metaengine.h b/engines/qdengine/metaengine.h
index f69d11a733f..5f22a993eb3 100644
--- a/engines/qdengine/metaengine.h
+++ b/engines/qdengine/metaengine.h
@@ -31,6 +31,8 @@ public:
 
 	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
 
+	GUI::OptionsContainerWidget *buildEngineOptionsWidget(GUI::GuiObject *boss, const Common::String &name, const Common::String &target) const override;
+
 	/**
 	 * Determine whether the engine supports the specified MetaEngine feature.
 	 *
diff --git a/engines/qdengine/module.mk b/engines/qdengine/module.mk
index d405565e453..ce254f4a28f 100644
--- a/engines/qdengine/module.mk
+++ b/engines/qdengine/module.mk
@@ -3,6 +3,7 @@ MODULE := engines/qdengine
 MODULE_OBJS = \
 	qdengine.o \
 	console.o \
+	dialogs.o \
 	metaengine.o \
 	minigames/adv/common.o \
 	minigames/adv/EffectManager.o \
diff --git a/engines/qdengine/qdengine.cpp b/engines/qdengine/qdengine.cpp
index ccc3cdcb95e..fed3bc6d4a3 100644
--- a/engines/qdengine/qdengine.cpp
+++ b/engines/qdengine/qdengine.cpp
@@ -73,10 +73,7 @@ QDEngineEngine::QDEngineEngine(OSystem *syst, const ADGameDescription *gameDesc)
 	_gameDescription(gameDesc), _randomSource("QDEngine") {
 	g_engine = this;
 
-	if (syst->getSupportedFormats().front().bytesPerPixel == 4)
-		_pixelformat = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
-	else
-		_pixelformat = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
+	_pixelformat = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
 
 	_screenW = 640;
 	_screenH = 480;
@@ -91,6 +88,7 @@ QDEngineEngine::QDEngineEngine(OSystem *syst, const ADGameDescription *gameDesc)
 	ConfMan.registerDefault("sound_volume", 255);
 	ConfMan.registerDefault("splash_enabled", true);
 	ConfMan.registerDefault("splash_time", 3000);
+	ConfMan.registerDefault("16bpp", false);
 
 	memset(_tagMap, 0, sizeof(_tagMap));
 }
@@ -196,6 +194,10 @@ Common::Error QDEngineEngine::run() {
 		sp.destroy();
 	}
 
+	if (debugChannelSet(-1, kDebug16BppMode) || ConfMan.getBool("16bpp")) {
+		_pixelformat = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
+	}
+
 	init_graphics();
 
 	sndDispatcher *sndD = new sndDispatcher;
diff --git a/engines/qdengine/qdengine.h b/engines/qdengine/qdengine.h
index b6fe5304e8f..d22ae36d66d 100644
--- a/engines/qdengine/qdengine.h
+++ b/engines/qdengine/qdengine.h
@@ -57,6 +57,7 @@ enum QDEngineDebugChannels {
 	kDebugMinigames,
 	kDebugMovement,
 	kDebugText,
+	kDebug16BppMode,
 };
 
 enum {




More information about the Scummvm-git-logs mailing list