[Scummvm-git-logs] scummvm master -> 533dcc9b1d56e69d9c70ec585f761794cb844cdd
neuromancer
noreply at scummvm.org
Mon Nov 3 06:55:34 UTC 2025
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
533dcc9b1d PRIVATE: Fix Mavis Weld's apartment
Commit: 533dcc9b1d56e69d9c70ec585f761794cb844cdd
https://github.com/scummvm/scummvm/commit/533dcc9b1d56e69d9c70ec585f761794cb844cdd
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2025-11-03T07:55:30+01:00
Commit Message:
PRIVATE: Fix Mavis Weld's apartment
The bitmap images in Mavis Weld's apartment store their transparent
color in palette entry 2. Our engine assumes that all bitmaps use
palette entry 250 for their transparent color. These entry numbers
are specific to each bitmap image's embedded palette.
Now images with different transparent color locations are detected
and their color is swapped with 250 during decoding.
Fixes Mavis Weld's apartment being inaccessible due to every click
being treated as clicking on the exit door.
Changed paths:
engines/private/private.cpp
engines/private/private.h
diff --git a/engines/private/private.cpp b/engines/private/private.cpp
index b4dc6dcc234..aed66fb7f9a 100644
--- a/engines/private/private.cpp
+++ b/engines/private/private.cpp
@@ -292,7 +292,11 @@ Common::Error PrivateEngine::run() {
// Load the game frame once
byte *palette;
bool isNewPalette;
- _frameImage = decodeImage(_framePath, nullptr, nullptr);
+ _frameImage = decodeImage(_framePath, &palette, &isNewPalette);
+ if (isNewPalette) {
+ free(palette);
+ palette = nullptr;
+ }
_mframeImage = decodeImage(_framePath, &palette, &isNewPalette);
_framePalette = (byte *) malloc(3*256);
@@ -1616,26 +1620,22 @@ Graphics::Surface *PrivateEngine::decodeImage(const Common::String &name, byte *
g_system->getPaletteManager()->grabPalette(currentPalette, 0, 256);
newImage = oldImage->convertTo(_pixelFormat, currentPalette);
remapImage(ncolors, oldImage, oldPalette, newImage, currentPalette);
- if (palette != nullptr) {
- *palette = currentPalette;
- if (isNewPalette != nullptr) {
- *isNewPalette = true;
- }
- } else {
- free(currentPalette);
- if (isNewPalette != nullptr) {
- *isNewPalette = false;
- }
- }
+ *palette = currentPalette;
+ *isNewPalette = true;
} else {
currentPalette = const_cast<byte *>(oldPalette);
newImage = oldImage->convertTo(_pixelFormat, currentPalette);
- if (palette != nullptr) {
- *palette = currentPalette;
- }
- if (isNewPalette != nullptr) {
- *isNewPalette = false;
- }
+ *palette = currentPalette;
+ *isNewPalette = false;
+ }
+
+ // Most images store the transparent color (green) in color 250, except for
+ // those in Mavis' apartment. Our engine assumes that all images share the
+ // the same transparent color number (250), so if this image stores it in
+ // a different palette entry then swap it with 250.
+ uint32 maskTransparentColor = findMaskTransparentColor(currentPalette, _transparentColor);
+ if (maskTransparentColor != _transparentColor) {
+ swapImageColors(newImage, currentPalette, maskTransparentColor, _transparentColor);
}
return newImage;
@@ -1681,6 +1681,51 @@ void PrivateEngine::remapImage(uint16 ncolors, const Graphics::Surface *oldImage
}
}
+uint32 PrivateEngine::findMaskTransparentColor(const byte *palette, uint32 defaultColor) {
+ // Green is used for the transparent color in masks. It is not always
+ // the same shade of green, and it is not always the same palette
+ // index in the bitmap image. It appears that the original searched
+ // each bitmap's palette for the nearest match to RGB 00 FF 00.
+ // Some masks use 00 FC 00. Green is usually color 250 in masks,
+ // but it is color 2 in the masks in Mavis' apartment.
+ uint32 transparentColor = defaultColor;
+ for (uint32 c = 0; c < 256; c++) {
+ byte r = palette[3 * c + 0];
+ byte g = palette[3 * c + 1];
+ byte b = palette[3 * c + 2];
+ if (r == 0 && b == 0) {
+ if (g == 0xff) {
+ // exact match, stop scanning
+ transparentColor = c;
+ break;
+ }
+ if (g == 0xfc) {
+ // almost green, keep scanning
+ transparentColor = c;
+ }
+ }
+ }
+ return transparentColor;
+}
+
+// swaps two colors in an image
+void PrivateEngine::swapImageColors(Graphics::Surface *image, byte *palette, uint32 a, uint32 b) {
+ SWAP(palette[3 * a + 0], palette[3 * b + 0]);
+ SWAP(palette[3 * a + 1], palette[3 * b + 1]);
+ SWAP(palette[3 * a + 2], palette[3 * b + 2]);
+
+ for (int y = 0; y < image->h; y++) {
+ for (int x = 0; x < image->w; x++) {
+ uint32 pixel = image->getPixel(x, y);
+ if (pixel == a) {
+ image->setPixel(x, y, b);
+ } else if (pixel == b) {
+ image->setPixel(x, y, a);
+ }
+ }
+ }
+}
+
void PrivateEngine::loadImage(const Common::String &name, int x, int y) {
debugC(1, kPrivateDebugFunction, "%s(%s,%d,%d)", __FUNCTION__, name.c_str(), x, y);
byte *palette;
diff --git a/engines/private/private.h b/engines/private/private.h
index 7790651f128..dccf5d210d1 100644
--- a/engines/private/private.h
+++ b/engines/private/private.h
@@ -231,6 +231,8 @@ public:
Graphics::Surface *decodeImage(const Common::String &file, byte **palette, bool *isNewPalette);
//byte *decodePalette(const Common::String &name);
void remapImage(uint16 ncolors, const Graphics::Surface *oldImage, const byte *oldPalette, Graphics::Surface *newImage, const byte *currentPalette);
+ static uint32 findMaskTransparentColor(const byte *palette, uint32 defaultColor);
+ static void swapImageColors(Graphics::Surface *image, byte *palette, uint32 a, uint32 b);
void loadImage(const Common::String &file, int x, int y);
void drawScreenFrame(const byte *videoPalette);
More information about the Scummvm-git-logs
mailing list