[Scummvm-git-logs] scummvm master -> 6857eb56babdb9389f76bab75a1ef2cb2d7b03cd
athrxx
noreply at scummvm.org
Wed Mar 20 22:26:48 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:
6857eb56ba SCUMM: (LOOM/EGA/AMIGA) - add missing shadow mode
Commit: 6857eb56babdb9389f76bab75a1ef2cb2d7b03cd
https://github.com/scummvm/scummvm/commit/6857eb56babdb9389f76bab75a1ef2cb2d7b03cd
Author: athrxx (athrxx at scummvm.org)
Date: 2024-03-20T23:26:09+01:00
Commit Message:
SCUMM: (LOOM/EGA/AMIGA) - add missing shadow mode
(bug no. 15030)
I have verified that neither the FM-Towns versions nor
INDY3 VGA have that mode. I don't know about Indy 3 EGA
(I presume not, but it would be worth checking).
I have verified (as can be seen in the ticket) that the original
seems to glitch on that new shadow mode in varying ways.
I haven't found the cause of it yet (current state of guessing:
glitchy text mask). And I am not sure if we need to replicate
the glitch, anyway...
Changed paths:
engines/scumm/charset.cpp
engines/scumm/charset.h
engines/scumm/string.cpp
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index 0764f8e3392..a56b79a5f01 100644
--- a/engines/scumm/charset.cpp
+++ b/engines/scumm/charset.cpp
@@ -336,8 +336,7 @@ CharsetRenderer::~CharsetRenderer() {
}
CharsetRendererCommon::CharsetRendererCommon(ScummEngine *vm)
- : CharsetRenderer(vm), _fontPtr(nullptr), _bitsPerPixel(0), _fontHeight(0), _numChars(0) {
- _enableShadow = false;
+ : CharsetRenderer(vm), _fontPtr(nullptr), _bitsPerPixel(0), _fontHeight(0), _numChars(0), _shadowType(kNoShadowType) {
_shadowColor = 0;
}
@@ -723,10 +722,9 @@ int CharsetRendererV3::getCharWidth(uint16 chr) const {
return spacing;
}
-void CharsetRendererPC::enableShadow(bool enable) {
+void CharsetRendererPC::setShadowMode(ShadowType mode) {
_shadowColor = 0;
- _enableShadow = enable;
- _shadowType = kNormalShadowType;
+ _shadowType = mode;
}
void CharsetRendererPC::drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height) {
@@ -735,37 +733,47 @@ void CharsetRendererPC::drawBits1(Graphics::Surface &dest, int x, int y, const b
return;
}
+ if (_shadowType == kOutlineShadowType) {
+ x++;
+ y++;
+ }
+
byte *dst = (byte *)dest.getBasePtr(x, y);
byte bits = 0;
uint8 col = _color;
int pitch = dest.pitch - width * dest.format.bytesPerPixel;
byte *dst2 = dst + dest.pitch;
-
- if (_vm->_isIndy4Jap) {
- // Characters allow shadows only if this is the main virtual screen, and we are not drawing
- // a message on a GUI banner. The main menu is fine though, and allows shadows as well.
- VirtScreen *vs = _vm->findVirtScreen(_top);
- bool canDrawShadow = vs != nullptr && vs->number == kMainVirtScreen && !_vm->isMessageBannerActive();
- enableShadow(canDrawShadow);
- }
+ byte *dst3 = dst - 1;
+ byte *dst4 = dst - dest.pitch;
+ byte prevBits = 0;
+ bool leftShadePixel = false;
for (y = 0; y < height && y + drawTop < dest.h; y++) {
for (x = 0; x < width; x++) {
- if ((x % 8) == 0)
+ if ((x % 8) == 0) {
+ prevBits = ~bits;
bits = *src++;
+ leftShadePixel = true;
+ }
if ((bits & revBitMask(x % 8)) && y + drawTop >= 0) {
- if (_enableShadow) {
- if (_shadowType == kNormalShadowType) {
- dst[1] = dst2[1] = _shadowColor;
-
- // Mac and DOS/V versions of Japanese INDY4 don't
- // draw a shadow pixel below the first pixel.
- // Verified from disasm.
- if (!_vm->_isIndy4Jap)
- dst2[0] = _shadowColor;
- } else if (_shadowType == kHorizontalShadowType) {
- dst[1] = _shadowColor;
+ if (_shadowType == kNormalShadowType) {
+ dst[1] = dst2[1] = _shadowColor;
+
+ // Mac and DOS/V versions of Japanese INDY4 don't
+ // draw a shadow pixel below the first pixel.
+ // Verified from disasm.
+ if (!_vm->_isIndy4Jap)
+ dst2[0] = _shadowColor;
+ } else if (_shadowType == kHorizontalShadowType) {
+ dst[1] = _shadowColor;
+ } else if (_shadowType == kOutlineShadowType) {
+ dst[1] = dst2[0] = dst2[1] = _shadowColor;
+ if (leftShadePixel) {
+ dst3[0] = _shadowColor;
+ leftShadePixel = false;
}
+ if (prevBits & revBitMask(x % 8))
+ dst4[0] = _shadowColor;
}
dst[0] = col;
} else if (!(bits & revBitMask(x % 8)) && (y < height - 1) &&
@@ -775,10 +783,14 @@ void CharsetRendererPC::drawBits1(Graphics::Surface &dest, int x, int y, const b
dst += dest.format.bytesPerPixel;
dst2 += dest.format.bytesPerPixel;
+ dst3 += dest.format.bytesPerPixel;
+ dst4 += dest.format.bytesPerPixel;
}
dst += pitch;
dst2 += pitch;
+ dst3 += pitch;
+ dst4 += pitch;
}
}
@@ -843,39 +855,40 @@ int CharsetRendererV3::getDrawHeightIntern(uint16) {
return 8;
}
-void CharsetRendererV3::setColor(byte color) {
- bool useShadow = false;
+void CharsetRendererV3::setColor(byte color, bool shadowModeSpecialFlag) {
+ ShadowType mode = kNoShadowType;
_color = color;
- // FM-TOWNS version of Loom uses old color method as well
- if ((_vm->_game.version >= 2) && ((_vm->_game.features & GF_16COLOR) || (_vm->_game.id == GID_LOOM && _vm->_game.version == 3))) {
- useShadow = ((_color & 0xF0) != 0);
- _color &= 0x0f;
- } else if (_vm->_game.features & GF_OLD256) {
- useShadow = ((_color & 0x80) != 0);
- _color &= 0x7f;
- } else
- useShadow = false;
-
+ if (_vm->_game.features & GF_OLD256) {
+ if (_color & 0x80)
+ mode = kNormalShadowType;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
- if (_vm->_game.platform == Common::kPlatformFMTowns) {
- _color = (_color & 0x0f) | ((_color & 0x0f) << 4);
- if (_color == 0)
- _color = 0x88;
- }
+ if (_vm->_game.platform == Common::kPlatformFMTowns) {
+ _color = (_color & 0x0f) | ((_color & 0x0f) << 4);
+ if (_color == 0)
+ _color = 0x88;
+ } else
#endif
+ _color = (_vm->_game.id == GID_LOOM) ? _color & 0x0f : _color & 0x7f;
+ } else if (_vm->_game.id == GID_LOOM && _vm->_game.version == 3) {
+ mode = (_color & 0x40) ? (shadowModeSpecialFlag ? kNoShadowType : kOutlineShadowType) : ((_color & 0x80) ? kNormalShadowType : kNoShadowType);
+ _color &= 0x0f;
+ } else if (_vm->_game.version >= 2 && (_vm->_game.features & GF_16COLOR)) {
+ if ((_color & 0xF0) != 0)
+ mode = kNormalShadowType;
+ }
- enableShadow(useShadow);
+ setShadowMode(mode);
translateColor();
}
#ifdef USE_RGB_COLOR
-void CharsetRendererPCE::setColor(byte color) {
+void CharsetRendererPCE::setColor(byte color, bool) {
_vm->setPCETextPalette(color);
_color = 15;
- enableShadow(true);
+ setShadowMode(kNormalShadowType);
}
#endif
@@ -926,9 +939,12 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
if (_left + origWidth > _right + 1)
return;
- if (_enableShadow) {
+ if (_shadowType == kNormalShadowType) {
width++;
height++;
+ } else if (_shadowType == kOutlineShadowType) {
+ width += 2;
+ height += 2;
}
if (_firstChar) {
@@ -969,7 +985,7 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
if (_str.right < _left) {
_str.right = _left;
- if (_enableShadow)
+ if (_shadowType != kNoShadowType)
_str.right++;
}
@@ -1064,7 +1080,7 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
_vm->_charsetColorMap[1] = _color;
if (_vm->isScummvmKorTarget() && is2byte) {
- enableShadow(true);
+ setShadowMode(kNormalShadowType);
_charPtr = _vm->get2byteCharPtr(chr);
_width = _vm->_2byteWidth;
_height = _vm->_2byteHeight;
@@ -1125,7 +1141,6 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
_vm->markRectAsDirty(vs->number, _left, _left + _width, drawTop, drawTop + _height);
}
-
// This check for kPlatformFMTowns and kMainVirtScreen is at least required for the chat with
// the navigator's head in front of the ghost ship in Monkey Island 1
if (!ignoreCharsetMask || (_vm->_game.platform == Common::kPlatformFMTowns && vs->number == kMainVirtScreen)) {
@@ -1171,7 +1186,7 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
if (_str.right < _left) {
_str.right = _left;
- if (_vm->_game.platform != Common::kPlatformFMTowns && _enableShadow)
+ if (_vm->_game.platform != Common::kPlatformFMTowns && _shadowType != kNoShadowType)
_str.right++;
}
@@ -1285,14 +1300,22 @@ bool CharsetRendererClassic::prepareDraw(uint16 chr) {
_height = _origHeight = _vm->_2byteHeight;
_offsX = _offsY = 0;
- if (_enableShadow) {
+ if (_vm->_isIndy4Jap) {
+ // Characters allow shadows only if this is the main virtual screen, and we are not drawing
+ // a message on a GUI banner. The main menu is fine though, and allows shadows as well.
+ VirtScreen *vs = _vm->findVirtScreen(_top);
+ bool canDrawShadow = vs != nullptr && vs->number == kMainVirtScreen && !_vm->isMessageBannerActive();
+ setShadowMode(canDrawShadow ? kNormalShadowType : kNoShadowType);
+ }
+
+ if (_shadowType != kNoShadowType) {
_width++;
_height++;
}
return true;
} else {
- enableShadow(false);
+ setShadowMode(kNoShadowType);
}
uint32 charOffs = READ_LE_UINT32(_fontPtr + chr * 4 + 4);
@@ -1405,20 +1428,20 @@ int CharsetRendererTownsV3::getFontHeight() const {
return _vm->_useCJKMode ? 8 : _fontHeight;
}
-void CharsetRendererTownsV3::enableShadow(bool enable) {
+void CharsetRendererTownsV3::setShadowMode(ShadowType mode) {
if (_vm->isScummvmKorTarget()) {
- CharsetRendererV3::enableShadow(enable);
+ CharsetRendererV3::setShadowMode(mode);
return;
}
_shadowColor = 8;
- _enableShadow = enable;
+ _shadowType = mode;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
_shadowColor = 0x88;
#ifdef USE_RGB_COLOR
if (_vm->_cjkFont)
- _vm->_cjkFont->setDrawingMode(enable ? Graphics::FontSJIS::kFMTownsShadowMode : Graphics::FontSJIS::kDefaultMode);
+ _vm->_cjkFont->setDrawingMode(mode != kNoShadowType ? Graphics::FontSJIS::kFMTownsShadowMode : Graphics::FontSJIS::kDefaultMode);
#endif
#endif
}
@@ -1465,13 +1488,13 @@ void CharsetRendererTownsV3::drawBits1(Graphics::Surface &dest, int x, int y, co
bits = *src++;
if ((bits & revBitMask(x % 8)) && y + drawTop >= 0) {
if (dest.format.bytesPerPixel == 2) {
- if (_enableShadow) {
+ if (_shadowType != kNoShadowType) {
WRITE_UINT16(dst + 2, _vm->_16BitPalette[_shadowColor]);
WRITE_UINT16(dst + dest.pitch, _vm->_16BitPalette[_shadowColor]);
}
WRITE_UINT16(dst, _vm->_16BitPalette[_color]);
} else {
- if (_enableShadow) {
+ if (_shadowType != kNoShadowType) {
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (scale2x) {
dst[2] = dst[3] = dst2[2] = dst2[3] = _shadowColor;
@@ -1570,11 +1593,11 @@ void CharsetRendererPCE::drawBits1(Graphics::Surface &dest, int x, int y, const
bits = *src++;
if ((bits & revBitMask(bitCount % 8)) && y + drawTop >= 0) {
if (dest.format.bytesPerPixel == 2) {
- if (_enableShadow)
+ if (_shadowType != kNoShadowType)
WRITE_UINT16(dst + dest.pitch + 2, _vm->_16BitPalette[_shadowColor]);
WRITE_UINT16(dst, _vm->_16BitPalette[_color]);
} else {
- if (_enableShadow)
+ if (_shadowType != kNoShadowType)
*(dst + dest.pitch + 1) = _shadowColor;
*dst = _color;
}
@@ -1605,7 +1628,7 @@ void CharsetRendererPCE::setDrawCharIntern(uint16 chr) {
#endif
CharsetRendererMac::CharsetRendererMac(ScummEngine *vm, const Common::Path &fontFile)
- : CharsetRendererCommon(vm), _lastTop(0) {
+ : CharsetRendererCommon(vm), _lastTop(0) {
// The original Macintosh interpreter didn't use the correct spacing
// between characters for some of the text, e.g. the Grail Diary. This
@@ -1718,7 +1741,7 @@ void CharsetRendererMac::printChar(int chr, bool ignoreCharsetMask) {
_pad = false;
}
- bool enableShadow = _enableShadow;
+ bool enableShadow = (_shadowType != kNoShadowType);
int color = _color;
// HACK: Notes and their names should always be drawn with a shadow.
@@ -1913,12 +1936,11 @@ void CharsetRendererMac::printCharInternal(int chr, int color, bool shadow, int
}
}
-void CharsetRendererMac::setColor(byte color) {
+void CharsetRendererMac::setColor(byte color, bool) {
_color = color;
- _enableShadow = false;
_shadowColor = 0;
- _enableShadow = ((color & 0xF0) != 0);
+ _shadowType = ((color & 0xF0) != 0) ? kNormalShadowType : kNoShadowType;
// Anything outside the ordinary palette should be fine.
_shadowColor = 255;
_color &= 0x0F;
@@ -2124,7 +2146,7 @@ void CharsetRendererNES::printChar(int chr, bool ignoreCharsetMask) {
if (_str.right < _left) {
_str.right = _left;
- if (_enableShadow)
+ if (_shadowType != kNoShadowType)
_str.right++;
}
@@ -2279,7 +2301,7 @@ bool CharsetRendererTownsClassic::prepareDraw(uint16 chr) {
_origHeight = _height = _vm->_2byteHeight;
_charPtr = _vm->get2byteCharPtr(chr);
_offsX = _offsY = 0;
- if (_enableShadow) {
+ if (_shadowType != kNoShadowType) {
_width++;
_height++;
}
@@ -2291,7 +2313,7 @@ bool CharsetRendererTownsClassic::prepareDraw(uint16 chr) {
}
void CharsetRendererTownsClassic::setupShadowMode() {
- _enableShadow = true;
+ _shadowType = kNormalShadowType;
_shadowColor = _vm->_townsCharsetColorMap[0];
assert(_vm->_cjkFont);
diff --git a/engines/scumm/charset.h b/engines/scumm/charset.h
index 9cb11a3df14..16c97dc1434 100644
--- a/engines/scumm/charset.h
+++ b/engines/scumm/charset.h
@@ -111,13 +111,27 @@ public:
virtual int getCharHeight(uint16 chr) const { return getFontHeight(); }
virtual int getCharWidth(uint16 chr) const = 0;
- virtual void setColor(byte color) { _color = color; translateColor(); }
+ virtual void setColor(byte color, bool shadowModeSpecialFlag = false) { _color = color; translateColor(); }
virtual byte getColor() { return _color; }
void saveLoadWithSerializer(Common::Serializer &ser);
};
class CharsetRendererCommon : public CharsetRenderer {
+public:
+ enum ShadowType {
+ kNoShadowType,
+ kNormalShadowType,
+ kHorizontalShadowType,
+ kOutlineShadowType
+ };
+
+ CharsetRendererCommon(ScummEngine *vm);
+
+ void setCurID(int32 id) override;
+
+ int getFontHeight() const override;
+
protected:
const byte *_fontPtr;
int _bitsPerPixel;
@@ -125,32 +139,17 @@ protected:
int _numChars;
byte _shadowColor;
- bool _enableShadow;
-
-public:
- CharsetRendererCommon(ScummEngine *vm);
-
- void setCurID(int32 id) override;
-
- int getFontHeight() const override;
+ ShadowType _shadowType;
};
class CharsetRendererPC : public CharsetRendererCommon {
- enum ShadowType {
- kNoShadowType,
- kNormalShadowType,
- kHorizontalShadowType
- };
-
- ShadowType _shadowType;
+public:
+ CharsetRendererPC(ScummEngine *vm) : CharsetRendererCommon(vm) { }
protected:
- virtual void enableShadow(bool enable);
+ virtual void setShadowMode(ShadowType mode);
virtual void drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height);
void drawBits1Kor(Graphics::Surface &dest, int x1, int y1, const byte *src, int drawTop, int width, int height);
-
-public:
- CharsetRendererPC(ScummEngine *vm) : CharsetRendererCommon(vm), _shadowType(kNoShadowType) { }
};
class CharsetRendererClassic : public CharsetRendererPC {
@@ -232,7 +231,7 @@ public:
void printChar(int chr, bool ignoreCharsetMask) override;
void drawChar(int chr, Graphics::Surface &s, int x, int y) override;
void setCurID(int32 id) override;
- void setColor(byte color) override;
+ void setColor(byte color, bool shadowModeSpecialFlag) override;
int getCharWidth(uint16 chr) const override;
};
@@ -244,7 +243,7 @@ public:
int getFontHeight() const override;
private:
- void enableShadow(bool enable) override;
+ void setShadowMode(ShadowType mode) override;
void drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height) override;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
int getDrawWidthIntern(uint16 chr) override;
@@ -268,7 +267,7 @@ private:
public:
CharsetRendererPCE(ScummEngine *vm) : CharsetRendererV3(vm), _sjisCurChar(0) {}
- void setColor(byte color) override;
+ void setColor(byte color, bool) override;
};
#endif
@@ -309,7 +308,7 @@ public:
int getFontHeight() const override;
int getCharWidth(uint16 chr) const override;
void printChar(int chr, bool ignoreCharsetMask) override;
- void setColor(byte color) override;
+ void setColor(byte color, bool) override;
};
#ifdef ENABLE_SCUMM_7_8
diff --git a/engines/scumm/string.cpp b/engines/scumm/string.cpp
index 667962c9748..eb50085cb1f 100644
--- a/engines/scumm/string.cpp
+++ b/engines/scumm/string.cpp
@@ -1228,6 +1228,9 @@ void ScummEngine::drawString(int a, const byte *msg) {
_charset->_disableOffsX = _charset->_firstChar = true;
_charset->setCurID(_string[a].charset);
+ VirtScreen *vs = findVirtScreen(_charset->_top);
+ bool shadowModeFlag = (vs && vs->number == kMainVirtScreen);
+
if (_game.version >= 5)
memcpy(_charsetColorMap, _charsetData[_charset->getCurID()], 4);
@@ -1318,9 +1321,9 @@ void ScummEngine::drawString(int a, const byte *msg) {
color = buf[i] + (buf[i + 1] << 8);
i += 2;
if (color == 0xFF)
- _charset->setColor(_string[a].color);
+ _charset->setColor(_string[a].color, shadowModeFlag);
else
- _charset->setColor(color);
+ _charset->setColor(color, shadowModeFlag);
break;
default:
break;
More information about the Scummvm-git-logs
mailing list