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

dreammaster noreply at scummvm.org
Fri Aug 14 02:11:35 UTC 2026


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

Summary:
8d8b7b26fb MADS: NEBULAR: Greyscale fixes when looking at inventory objects
c360a6fa7e MADS: NEBULAR: Fix greyscale fade out examining inventory items


Commit: 8d8b7b26fb64c255d694c09d2226b3069be18741
    https://github.com/scummvm/scummvm/commit/8d8b7b26fb64c255d694c09d2226b3069be18741
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2026-08-14T12:11:25+10:00

Commit Message:
MADS: NEBULAR: Greyscale fixes when looking at inventory objects

Changed paths:
    engines/mads/core/sort.cpp
    engines/mads/nebular/extra.cpp
    engines/mads/nebular/extra.h


diff --git a/engines/mads/core/sort.cpp b/engines/mads/core/sort.cpp
index 17e275a722b..949f88e0a21 100644
--- a/engines/mads/core/sort.cpp
+++ b/engines/mads/core/sort.cpp
@@ -20,6 +20,8 @@
  */
 
 #include "mads/core/general.h"
+#include "mads/mads.h"
+#include "mads/nebular/extra.h"
 
 namespace MADS {
 
@@ -121,6 +123,11 @@ void sort_insertion_16(int elements, byte *id, word *value) {
 }
 
 void sort_insertion_8(int elements, byte *id, byte *value) {
+	if (g_engine->getGameID() == GType_RexNebular) {
+		RexNebular::sort_insertion_8(elements, id, value);
+		return;
+	}
+
 	int  restart_mark = 0;
 	byte my_value;
 	byte my_id;
diff --git a/engines/mads/nebular/extra.cpp b/engines/mads/nebular/extra.cpp
index aa690a70b61..27c4828aa16 100644
--- a/engines/mads/nebular/extra.cpp
+++ b/engines/mads/nebular/extra.cpp
@@ -463,6 +463,64 @@ done:
 	return roomPtr;
 }
 
+void sort_insertion_8(int elements, byte *id, byte *value) {
+	int endIndex = elements - 1;
+
+	for (;;) {  // restart_sort
+		bool continueFlag = false;
+		if (endIndex <= 0)
+			return;
+
+		int di = 0;
+		for (;;) {
+			if (continueFlag)
+				break;
+
+			int palIndex = di;
+			byte v1 = value[di];
+			byte v2 = id[di];
+
+			if (value[di + 1] < v1) {
+				// Extract the out-of-place (larger) element, close the gap
+				int deletion = elements - di - 1;
+				if (deletion > 0) {
+					memmove(&value[di], &value[di + 1], deletion * sizeof(byte));
+					memmove(&id[di], &id[di + 1], deletion * sizeof(byte));
+				}
+
+				// Find the insertion point: just after the last element <= v1
+				int si = 0;
+				bool found = false;
+				while (endIndex > si) {
+					if (found)
+						break;
+					if (value[si] > v1)
+						found = true;
+					si++;
+				}
+
+				continueFlag = true;
+
+				int insertion = elements - si - 1;
+				if (insertion > 0) {
+					memmove(&value[si + 1], &value[si], insertion * sizeof(byte));
+					memmove(&id[si + 1], &id[si], insertion * sizeof(byte));
+				}
+				value[si] = v1;
+				id[si] = v2;
+			}
+
+			++palIndex;
+			if (endIndex <= palIndex)
+				break;
+			di = palIndex;
+		}
+
+		if (!continueFlag)
+			return;
+	}
+}
+
 int buffer_legal(const Buffer &special, int orig_wrap,
 		int x1, int y1, int x2, int y2) {
 	if (special.data == nullptr)
diff --git a/engines/mads/nebular/extra.h b/engines/mads/nebular/extra.h
index 2f45bdee869..21d3aa6dd6b 100644
--- a/engines/mads/nebular/extra.h
+++ b/engines/mads/nebular/extra.h
@@ -64,6 +64,21 @@ extern int room_load_variant(Load *load_handle, Buffer *depth, Buffer *walk, Buf
  */
 extern int buffer_legal(const Buffer &special, int orig_wrap, int x1, int y1, int x2, int y2);
 
+/**
+ * Rex Nebular's version of sort_insertion_8() (see core/sort.h), called from it whenever
+ * the active game is Rex Nebular. Unlike the generic engine's version, this is a faithful,
+ * instruction-for-instruction port of Rex's own sort_insertion_8 disassembly, which is a
+ * genuinely different (and, unlike the generic version, stable) algorithm: on each pass it
+ * restarts the scan from index 0, and on finding an inversion extracts the earlier (larger)
+ * of the two out-of-order elements, closing the gap left behind, then re-inserts it just
+ * after the last remaining element that is <= it. This stability matters because
+ * magic_map_to_grey_ramp() (see core/magic.cpp) relies on tied elements keeping their
+ * original relative order to consistently bucket colors with identical grey-ramp hash
+ * values; the generic version's tie-breaking differs and produces a visibly different
+ * (incorrect) grey ramp for Rex.
+ */
+extern void sort_insertion_8(int elements, byte *id, byte *value);
+
 } // namespace RexNebular
 } // namespace MADS
 


Commit: c360a6fa7ef09bb5959f56f5cc898f0da5414d6a
    https://github.com/scummvm/scummvm/commit/c360a6fa7ef09bb5959f56f5cc898f0da5414d6a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2026-08-14T12:11:25+10:00

Commit Message:
MADS: NEBULAR: Fix greyscale fade out examining inventory items

Assisted-by: Claude Code:sonnet-5

Changed paths:
    engines/mads/core/object.cpp
    engines/mads/core/pal.cpp
    engines/mads/core/popup.h
    engines/mads/nebular/popup.cpp
    engines/mads/nebular/popup.h


diff --git a/engines/mads/core/object.cpp b/engines/mads/core/object.cpp
index ddeac9c8deb..4817661ba0b 100644
--- a/engines/mads/core/object.cpp
+++ b/engines/mads/core/object.cpp
@@ -39,6 +39,7 @@
 #include "mads/core/popup.h"
 #include "mads/core/room.h"
 #include "mads/core/speech.h"
+#include "mads/nebular/popup.h"
 #include "mads/core/sprite.h"
 #include "mads/core/text.h"
 #include "mads/core/tile.h"
@@ -341,6 +342,9 @@ int object_examine(int number, long message, int speech) {
 	if (message) {
 		text_saves_screen = false;
 
+		if (isRex)
+			RexNebular::popup_shift_dialog_colors(-10);
+
 		memcpy(&cycling_palette[248].r, &master_palette[248].r, 8 * sizeof(RGBcolor));
 
 		if (speech) {
@@ -351,6 +355,9 @@ int object_examine(int number, long message, int speech) {
 
 		text_show(message);
 
+		if (isRex)
+			RexNebular::popup_shift_dialog_colors(10);
+
 		if (speech && speech_system_active && speech_on) {
 			speech_all_off();
 		}
diff --git a/engines/mads/core/pal.cpp b/engines/mads/core/pal.cpp
index 4571aa877c3..97bcbe9d09c 100644
--- a/engines/mads/core/pal.cpp
+++ b/engines/mads/core/pal.cpp
@@ -563,8 +563,8 @@ void pal_grey(Palette &fixpal, int base_color, int num_colors,
 	int level;
 	word accum = 0;
 
-	dif = (high_grey - low_grey);
-	level = low_grey;
+	dif = (low_grey - high_grey);
+	level = high_grey;
 
 	for (count = 0; count < num_colors; count++) {
 		fixpal[base_color + count].r = (byte)level;
diff --git a/engines/mads/core/popup.h b/engines/mads/core/popup.h
index 546bd613fa2..5002a18317b 100644
--- a/engines/mads/core/popup.h
+++ b/engines/mads/core/popup.h
@@ -99,19 +99,6 @@ namespace MADS {
 
 #define popup_padding_width     3     /* Extra space on each side */
 
-enum {
-	REX_PALETTE_CYCLING_AREA	=   6,
-	REX_DIALOG_CONTENT1_COLOR	= 248,
-	REX_DIALOG_CONTENT2_COLOR	= 249,
-	REX_DIALOG_EDGE_COLOR		= 250,
-	REX_DIALOG_BACKGROUND_COLOR	= 251,
-	REX_DIALOG_FC_COLOR			= 252,
-	REX_DIALOG_FD_COLOR			= 253,
-	REX_DIALOG_FE_COLOR			= 254,
-	REX_DIALOG_BLACK_COLOR		=   0
-};
-
-
 struct BoxParam {
 	SeriesPtr series;           /* Sprite series for popup box */
 
diff --git a/engines/mads/nebular/popup.cpp b/engines/mads/nebular/popup.cpp
index fab74d6eada..9ba56827223 100644
--- a/engines/mads/nebular/popup.cpp
+++ b/engines/mads/nebular/popup.cpp
@@ -38,20 +38,56 @@ namespace RexNebular {
 
 enum {
 	DIALOG_BLACK_COLOR		= 0,
-	PALETTE_CYCLING_AREA	= 6,
-	DIALOG_CONTENT1_COLOR	= 248,
-	DIALOG_CONTENT2_COLOR	= 249,
-	DIALOG_EDGE_COLOR		= 250,
-	DIALOG_BACKGROUND_COLOR	= 251,
-	DIALOG_FC_COLOR			= 252,
-	DIALOG_FD_COLOR			= 253,
-	DIALOG_FE_COLOR			= 254
+	PALETTE_CYCLING_AREA	= 8,
+
+	DIALOG_CONTENT1_IDX = 0,
+	DIALOG_CONTENT2_IDX,
+	DIALOG_EDGE_IDX,
+	DIALOG_BACKGROUND_IDX,
+	DIALOG_FC_IDX,
+	DIALOG_FD_IDX,
+	DIALOG_FE_IDX
 };
 
+// Rex's object_examine temporarily shifts these down by 10 (via
+// popup_shift_dialog_colors()) while its item-description dialog is on
+// screen, then shifts them back afterwards, so they must be mutable state
+// rather than fixed constants. PALETTE_CYCLING_AREA (8) covers one byte
+// beyond DIALOG_FE_COLOR that the original also shifts, though nothing
+// else in the engine names or uses it.
+byte dialog_colors[PALETTE_CYCLING_AREA];
+
+#define DIALOG_CONTENT1_COLOR    dialog_colors[DIALOG_CONTENT1_IDX]
+#define DIALOG_CONTENT2_COLOR    dialog_colors[DIALOG_CONTENT2_IDX]
+#define DIALOG_EDGE_COLOR        dialog_colors[DIALOG_EDGE_IDX]
+#define DIALOG_BACKGROUND_COLOR  dialog_colors[DIALOG_BACKGROUND_IDX]
+#define DIALOG_FC_COLOR          dialog_colors[DIALOG_FC_IDX]
+#define DIALOG_FD_COLOR          dialog_colors[DIALOG_FD_IDX]
+#define DIALOG_FE_COLOR          dialog_colors[DIALOG_FE_IDX]
+
 int dialog_content_seed;
 
 void popup_init() {
 	dialog_content_seed = -1;
+
+	dialog_colors[DIALOG_CONTENT1_IDX] = 248;
+	dialog_colors[DIALOG_CONTENT2_IDX] = 249;
+	dialog_colors[DIALOG_EDGE_IDX] = 250;
+	dialog_colors[DIALOG_BACKGROUND_IDX] = 251;
+	dialog_colors[DIALOG_FC_IDX] = 252;
+	dialog_colors[DIALOG_FD_IDX] = 253;
+	dialog_colors[DIALOG_FE_IDX] = 254;
+	dialog_colors[7] = 255;
+}
+
+// Shifts all of the dialog colors (including the one unnamed trailing byte -
+// see PALETTE_CYCLING_AREA above) by delta. Called by Rex's object_examine
+// with -10 before showing its item-description dialog and +10 afterwards,
+// so the dialog temporarily borrows a different part of the palette than
+// the object grey ramp it's being drawn over.
+void popup_shift_dialog_colors(int delta) {
+	for (int i = 0; i < PALETTE_CYCLING_AREA; ++i)
+		dialog_colors[i] = (byte)(dialog_colors[i] + delta);
 }
 
 static uint16 rotr16(uint16 value, int amount) {
@@ -110,18 +146,18 @@ void popup_draw() {
 	askY = (box_param.font->max_y_size + 1) * box->ask_y;
 
 	// Fill area
-	buffer_rect_fill(scr_main, box->x, box->y, box->xs, box->ys, REX_DIALOG_BACKGROUND_COLOR);
+	buffer_rect_fill(scr_main, box->x, box->y, box->xs, box->ys, DIALOG_BACKGROUND_COLOR);
 
 	// Edge lines
-	buffer_rect_fill(scr_main, box->x + 1, box->y + box->ys - 2, box->xs - 1, 1, REX_DIALOG_EDGE_COLOR);
-	buffer_rect_fill(scr_main, box->x, box->y + box->ys - 1, box->xs, 1, REX_DIALOG_EDGE_COLOR);
+	buffer_rect_fill(scr_main, box->x + 1, box->y + box->ys - 2, box->xs - 1, 1, DIALOG_EDGE_COLOR);
+	buffer_rect_fill(scr_main, box->x, box->y + box->ys - 1, box->xs, 1, DIALOG_EDGE_COLOR);
 
 	// Right edge
-	buffer_rect_fill(scr_main, box->x + box->xs - 2, box->y + 2, 1, box->ys - 2, REX_DIALOG_EDGE_COLOR);
-	buffer_rect_fill(scr_main, box->x + box->xs - 1, box->y + 1, 1, box->ys - 1, REX_DIALOG_EDGE_COLOR);
+	buffer_rect_fill(scr_main, box->x + box->xs - 2, box->y + 2, 1, box->ys - 2, DIALOG_EDGE_COLOR);
+	buffer_rect_fill(scr_main, box->x + box->xs - 1, box->y + 1, 1, box->ys - 1, DIALOG_EDGE_COLOR);
 
 	dialog_content_seed = popup_draw_content(box->x + 2, box->y + 2, box->xs - 4, askY, 0,
-		REX_DIALOG_CONTENT2_COLOR, REX_DIALOG_CONTENT1_COLOR, box->ys - 4, scr_main);
+		DIALOG_CONTENT2_COLOR, DIALOG_CONTENT1_COLOR, box->ys - 4, scr_main);
 
 	askY = box->y + 5;
 
diff --git a/engines/mads/nebular/popup.h b/engines/mads/nebular/popup.h
index 5d35612617c..c27e1270331 100644
--- a/engines/mads/nebular/popup.h
+++ b/engines/mads/nebular/popup.h
@@ -33,6 +33,14 @@ extern void popup_draw();
 extern void popup_setup_cycle();
 extern void popup_update_ask(const char *string, int maxlen);
 
+/**
+ * Shifts the dialog palette colors (see popup_setup_cycle()) by delta. Called by
+ * object_examine() (see core/object.cpp) with -10 before showing its item-description
+ * dialog and +10 afterwards, so the dialog temporarily borrows a different part of
+ * the palette than the object grey ramp it's drawn over.
+ */
+extern void popup_shift_dialog_colors(int delta);
+
 } // namespace RexNebular
 } // namespace MADS
 




More information about the Scummvm-git-logs mailing list