[Scummvm-git-logs] scummvm master -> daed465639b625ef6f16c538a039102f44d2d967
sluicebox
noreply at scummvm.org
Mon Nov 7 07:05:27 UTC 2022
This automated email contains information about 7 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
ff017dc44f SCI: Fix SCI16 Mac QuickTime playback when upscaled
2506f89717 SCI: Add scaling for Mac cursors (SCI16)
1eeb0b1f24 SCI: Add scaling for Mac icon bar
2775987cba MACGUI: Expose font families in MacFontManager
b578f5be7b GRAPHICS: Expose Font leading and descent values
1efdb1cb6c SCI: Add support for Macintosh fonts
daed465639 SCI: Add option for high resolution Mac fonts
Commit: ff017dc44f7178e4aff3cda57ee7805cfcc829bd
https://github.com/scummvm/scummvm/commit/ff017dc44f7178e4aff3cda57ee7805cfcc829bd
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2022-11-06T23:05:20-08:00
Commit Message:
SCI: Fix SCI16 Mac QuickTime playback when upscaled
Required for Mac fonts. Previous code implicitly assumed that the first
format in the system's would always be 2 bytes per pixel. This is not
the case when upscaling. Now we explicitly search for the format.
Changed paths:
engines/sci/engine/kvideo.cpp
diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp
index e78670d8f88..388b8e3bc17 100644
--- a/engines/sci/engine/kvideo.cpp
+++ b/engines/sci/engine/kvideo.cpp
@@ -136,10 +136,18 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) {
// Mac QuickTime
// The only argument is the string for the video
- // HACK: Switch to 16bpp graphics for Cinepak.
+ // Switch to 16bpp graphics for Cinepak
if (g_system->getScreenFormat().bytesPerPixel == 1) {
- initGraphics(screenWidth, screenHeight, nullptr);
- switchedGraphicsMode = true;
+ const Common::List<Graphics::PixelFormat> supportedFormats = g_system->getSupportedFormats();
+ Common::List<Graphics::PixelFormat>::const_iterator it;
+ for (it = supportedFormats.begin(); it != supportedFormats.end(); ++it) {
+ if (it->bytesPerPixel == 2) {
+ const Graphics::PixelFormat format = *it;
+ initGraphics(screenWidth, screenHeight, &format);
+ switchedGraphicsMode = true;
+ break;
+ }
+ }
}
if (g_system->getScreenFormat().bytesPerPixel == 1) {
Commit: 2506f89717d8e1687a2c92fa921cc3e222e659ab
https://github.com/scummvm/scummvm/commit/2506f89717d8e1687a2c92fa921cc3e222e659ab
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2022-11-06T23:05:20-08:00
Commit Message:
SCI: Add scaling for Mac cursors (SCI16)
Required for Mac fonts
Changed paths:
engines/sci/graphics/cursor.cpp
diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp
index 8496376cf54..5603f078a5a 100644
--- a/engines/sci/graphics/cursor.cpp
+++ b/engines/sci/graphics/cursor.cpp
@@ -538,7 +538,25 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu
return;
}
- CursorMan.replaceCursor(macCursor);
+ if (_upscaledHires == GFX_SCREEN_UPSCALED_640x400) {
+ // Scale cursor by 2x
+ uint16 width = macCursor->getWidth() * 2;
+ uint16 height = macCursor->getHeight() * 2;
+ uint16 cursorHotspotX = macCursor->getHotspotX() * 2;
+ uint16 cursorHotspotY = macCursor->getHotspotY() * 2;
+ Common::SpanOwner<SciSpan<byte> > cursorBitmap;
+ cursorBitmap->allocate(width * height, "upscaled cursor bitmap");
+ SciSpan<const byte> sourceBitmap(macCursor->getSurface(), macCursor->getWidth() * macCursor->getHeight());
+ _screen->scale2x(sourceBitmap, *cursorBitmap, macCursor->getWidth(), macCursor->getHeight());
+ CursorMan.replaceCursor(cursorBitmap->getUnsafeDataAt(0, width * height), width, height, cursorHotspotX, cursorHotspotY, macCursor->getKeyColor());
+
+ // CursorMan.replaceCursor() does this when called with just a Graphics::Cursor
+ if (macCursor->getPalette()) {
+ CursorMan.replaceCursorPalette(macCursor->getPalette(), macCursor->getPaletteStartIndex(), macCursor->getPaletteCount());
+ }
+ } else {
+ CursorMan.replaceCursor(macCursor);
+ }
delete macCursor;
kernelShow();
Commit: 1eeb0b1f2480c5affff12555e6dc62b2395c6322
https://github.com/scummvm/scummvm/commit/1eeb0b1f2480c5affff12555e6dc62b2395c6322
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2022-11-06T23:05:20-08:00
Commit Message:
SCI: Add scaling for Mac icon bar
Required for Mac fonts.
This also makes the disabled icons appear as they did in the original.
Mac SSCI would draw the disabled pattern at high resolution after
upscaling the icon image, not before.
Changed paths:
engines/sci/graphics/maciconbar.cpp
engines/sci/graphics/maciconbar.h
diff --git a/engines/sci/graphics/maciconbar.cpp b/engines/sci/graphics/maciconbar.cpp
index 7b99bab47e1..4c8fcd1b932 100644
--- a/engines/sci/graphics/maciconbar.cpp
+++ b/engines/sci/graphics/maciconbar.cpp
@@ -35,8 +35,6 @@
namespace Sci {
GfxMacIconBar::GfxMacIconBar() {
- _lastX = 0;
-
if (g_sci->getGameId() == GID_FREDDYPHARKAS)
_inventoryIndex = 5;
else
@@ -44,6 +42,8 @@ GfxMacIconBar::GfxMacIconBar() {
_inventoryIcon = nullptr;
_allDisabled = true;
+
+ _isUpscaled = (g_sci->_gfxScreen->getUpscaledHires() == GFX_SCREEN_UPSCALED_640x400);
}
GfxMacIconBar::~GfxMacIconBar() {
@@ -54,7 +54,6 @@ void GfxMacIconBar::initIcons(uint16 count, reg_t *objs) {
// free icons and reset state in case game is restarting
freeIcons();
_iconBarItems.clear();
- _lastX = 0;
_inventoryIcon = nullptr;
_allDisabled = true;
@@ -96,16 +95,17 @@ void GfxMacIconBar::addIcon(reg_t obj) {
item.enabled = true;
- // Start after the main viewing window and add a two pixel buffer
+ // Start after last icon
+ uint16 x = _iconBarItems.empty() ? 0 : _iconBarItems.back().rect.right;
+
+ // Start below the main viewing window and add a two pixel buffer
uint16 y = g_sci->_gfxScreen->getHeight() + 2;
if (item.nonSelectedImage)
- item.rect = Common::Rect(_lastX, y, MIN<uint32>(_lastX + item.nonSelectedImage->w, 320), y + item.nonSelectedImage->h);
+ item.rect = Common::Rect(x, y, MIN<uint32>(x + item.nonSelectedImage->w, 320), y + item.nonSelectedImage->h);
else
error("Could not find a non-selected image for icon %d", iconIndex);
- _lastX += item.rect.width();
-
_iconBarItems.push_back(item);
}
@@ -124,58 +124,95 @@ void GfxMacIconBar::drawIcon(uint16 iconIndex, bool selected) {
if (isIconEnabled(iconIndex)) {
if (selected)
- drawEnabledImage(_iconBarItems[iconIndex].selectedImage, rect);
+ drawImage(_iconBarItems[iconIndex].selectedImage, rect, true);
else
- drawEnabledImage(_iconBarItems[iconIndex].nonSelectedImage, rect);
+ drawImage(_iconBarItems[iconIndex].nonSelectedImage, rect, true);
} else
- drawDisabledImage(_iconBarItems[iconIndex].nonSelectedImage, rect);
+ drawImage(_iconBarItems[iconIndex].nonSelectedImage, rect, false);
if ((iconIndex == _inventoryIndex) && _inventoryIcon) {
Common::Rect invRect = Common::Rect(0, 0, _inventoryIcon->w, _inventoryIcon->h);
invRect.moveTo(rect.left, rect.top);
invRect.translate((rect.width() - invRect.width()) / 2, (rect.height() - invRect.height()) / 2);
- if (isIconEnabled(iconIndex))
- drawEnabledImage(_inventoryIcon, invRect);
- else
- drawDisabledImage(_inventoryIcon, invRect);
+ drawImage(_inventoryIcon, invRect, isIconEnabled(iconIndex));
}
}
-void GfxMacIconBar::drawEnabledImage(Graphics::Surface *surface, const Common::Rect &rect) {
- if (surface)
- g_system->copyRectToScreen(surface->getPixels(), surface->pitch, rect.left, rect.top, rect.width(), rect.height());
-}
-
-void GfxMacIconBar::drawDisabledImage(Graphics::Surface *surface, const Common::Rect &rect) {
- if (!surface)
- return;
-
- // Add a black checkboard pattern to the image before copying it to the screen
-
- Graphics::Surface newSurf;
- newSurf.copyFrom(*surface);
-
- for (int i = 0; i < newSurf.h; i++) {
+// Add a black checkerboard pattern to an image before copying it to the screen.
+// The pattern is to be applied to the image after any upscaling occurs, so rect
+// must be the final screen coordinates.
+void GfxMacIconBar::drawDisabledPattern(Graphics::Surface &surface, const Common::Rect &rect) {
+ for (int y = 0; y < surface.h; y++) {
// Start at the next four byte boundary
int startX = 3 - ((rect.left + 3) & 3);
// Start odd rows at two bytes past that (also properly aligned)
- if ((i + rect.top) & 1)
+ if ((y + rect.top) & 1) {
startX = (startX + 2) & 3;
+ }
+
+ // Set every fourth pixel to black
+ for (int x = startX; x < surface.w; x += 4) {
+ surface.setPixel(x, y, 0);
+ }
+ }
+}
- for (int j = startX; j < newSurf.w; j += 4)
- *((byte *)newSurf.getBasePtr(j, i)) = 0;
+void GfxMacIconBar::drawImage(Graphics::Surface *surface, const Common::Rect &rect, bool enable) {
+ if (surface == nullptr) {
+ return;
}
- g_system->copyRectToScreen(newSurf.getPixels(), newSurf.pitch, rect.left, rect.top, rect.width(), rect.height());
- newSurf.free();
+ if (_isUpscaled) {
+ Common::Rect dstRect(rect.left * 2, rect.top * 2, rect.right * 2, rect.bottom * 2);
+
+ // increase _upscaleBuffer if needed
+ const uint32 upscaleSize = dstRect.width() * dstRect.height();
+ if (upscaleSize > _upscaleBuffer->size()) {
+ _upscaleBuffer.clear();
+ _upscaleBuffer->allocate(upscaleSize);
+ }
+
+ // scale2x
+ const int srcWidth = rect.width();
+ const int srcHeight = rect.height();
+ const int srcPitch = surface->pitch;
+ const byte *srcPtr = (byte *)surface->getPixels();
+ byte *dstPtr = _upscaleBuffer->getUnsafeDataAt(0, upscaleSize);
+ for (int y = 0; y < srcHeight; y++) {
+ for (int x = 0; x < srcWidth; x++) {
+ const byte color = *srcPtr++;
+ dstPtr[0] = color;
+ dstPtr[1] = color;
+ dstPtr[dstRect.width() + 0] = color;
+ dstPtr[dstRect.width() + 1] = color;
+ dstPtr += 2;
+ }
+ srcPtr += (srcPitch - srcWidth);
+ dstPtr += dstRect.width();
+ }
+
+ if (!enable) {
+ Graphics::Surface upscaleSurface;
+ upscaleSurface.init(dstRect.width(), dstRect.height(), dstRect.width(), _upscaleBuffer->getUnsafeDataAt(0, upscaleSize), surface->format);
+ drawDisabledPattern(upscaleSurface, dstRect);
+ }
+ g_system->copyRectToScreen(_upscaleBuffer->getUnsafeDataAt(0, upscaleSize), dstRect.width(), dstRect.left, dstRect.top, dstRect.width(), dstRect.height());
+ } else {
+ if (!enable) {
+ Graphics::Surface disableSurface;
+ disableSurface.copyFrom(*surface);
+ drawDisabledPattern(disableSurface, rect);
+ g_system->copyRectToScreen(disableSurface.getPixels(), disableSurface.pitch, rect.left, rect.top, rect.width(), rect.height());
+ } else {
+ g_system->copyRectToScreen(surface->getPixels(), surface->pitch, rect.left, rect.top, rect.width(), rect.height());
+ }
+ }
}
void GfxMacIconBar::drawSelectedImage(uint16 iconIndex) {
- assert(iconIndex <= _iconBarItems.size());
-
- drawEnabledImage(_iconBarItems[iconIndex].selectedImage, _iconBarItems[iconIndex].rect);
+ drawImage(_iconBarItems[iconIndex].selectedImage, _iconBarItems[iconIndex].rect, true);
}
bool GfxMacIconBar::isIconEnabled(uint16 iconIndex) const {
diff --git a/engines/sci/graphics/maciconbar.h b/engines/sci/graphics/maciconbar.h
index abbeaf610d6..8df712173d6 100644
--- a/engines/sci/graphics/maciconbar.h
+++ b/engines/sci/graphics/maciconbar.h
@@ -54,11 +54,13 @@ private:
};
Common::Array<IconBarItem> _iconBarItems;
- uint32 _lastX;
uint16 _inventoryIndex;
Graphics::Surface *_inventoryIcon;
bool _allDisabled;
+ bool _isUpscaled;
+ Common::SpanOwner<SciSpan<byte> > _upscaleBuffer;
+
Graphics::Surface *loadPict(ResourceId id);
Graphics::Surface *createImage(uint32 iconIndex, bool isSelected);
void remapColors(Graphics::Surface *surf, const byte *palette);
@@ -68,8 +70,8 @@ private:
void drawIcon(uint16 index, bool selected);
void drawSelectedImage(uint16 index);
bool isIconEnabled(uint16 index) const;
- void drawEnabledImage(Graphics::Surface *surface, const Common::Rect &rect);
- void drawDisabledImage(Graphics::Surface *surface, const Common::Rect &rect);
+ void drawDisabledPattern(Graphics::Surface &surface, const Common::Rect &rect);
+ void drawImage(Graphics::Surface *surface, const Common::Rect &rect, bool enabled);
bool pointOnIcon(uint32 iconIndex, Common::Point point);
};
Commit: 2775987cba75652859dc1c5fe7719caba672f946
https://github.com/scummvm/scummvm/commit/2775987cba75652859dc1c5fe7719caba672f946
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2022-11-06T23:05:20-08:00
Commit Message:
MACGUI: Expose font families in MacFontManager
MacFontManager didn't have a mechanism to report which fonts it loaded
from an external resource. It also requires that any fonts that aren't
built-in be explicitly registered by name by the client before they can
be used. This combination meant that a client couldn't load fonts from
an external file and use them by their properties (id / size / style).
SCI contains Mac fonts in its executable along with a table that maps
each SCI font id to a Mac font id and size. The font name isn't a part
of this since the Classic Mac Toolbox API took id / size / style as
input when drawing text.
Now MacFontManager exposes the font families it has loaded along with
their names. This allows a client to see which fonts were loaded,
register them by name, and proceed to use them with the existing API.
Changed paths:
engines/director/tests.cpp
engines/scumm/charset.cpp
graphics/fonts/macfont.cpp
graphics/fonts/macfont.h
graphics/macgui/macfontmanager.cpp
graphics/macgui/macfontmanager.h
diff --git a/engines/director/tests.cpp b/engines/director/tests.cpp
index de6cc37cb06..36dfbc1552a 100644
--- a/engines/director/tests.cpp
+++ b/engines/director/tests.cpp
@@ -154,7 +154,7 @@ void Window::testFonts() {
debug("Font: %s", name.c_str());
- Graphics::MacFontFamily font;
+ Graphics::MacFontFamily font(name);
font.load(*stream);
}
}
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index 7183b144385..e728009454e 100644
--- a/engines/scumm/charset.cpp
+++ b/engines/scumm/charset.cpp
@@ -1551,7 +1551,7 @@ CharsetRendererMac::CharsetRendererMac(ScummEngine *vm, const Common::String &fo
if (!fond)
return;
- Graphics::MacFontFamily fontFamily;
+ Graphics::MacFontFamily fontFamily(fontFamilyName);
if (!fontFamily.load(*fond)) {
delete fond;
return;
diff --git a/graphics/fonts/macfont.cpp b/graphics/fonts/macfont.cpp
index 92b9a6d48db..61b930279bf 100644
--- a/graphics/fonts/macfont.cpp
+++ b/graphics/fonts/macfont.cpp
@@ -64,7 +64,9 @@ static int getDepth(uint16 _fontType) {
return 1 << ((_fontType >> 2) & 3);
}
-MacFontFamily::MacFontFamily() {
+MacFontFamily::MacFontFamily(const Common::String &name) {
+ _name = name;
+
_ffFlags = 0;
_ffFamID = 0;
_ffFirstChar = 0;
diff --git a/graphics/fonts/macfont.h b/graphics/fonts/macfont.h
index f54312aa9d9..f04b33b5f3d 100644
--- a/graphics/fonts/macfont.h
+++ b/graphics/fonts/macfont.h
@@ -33,7 +33,7 @@ namespace Graphics {
class MacFontFamily {
public:
- MacFontFamily();
+ MacFontFamily(const Common::String &name);
~MacFontFamily();
bool load(Common::SeekableReadStream &stream);
@@ -46,9 +46,13 @@ public:
uint16 _fontID;
};
+ const Common::String &getName() { return _name; }
+ uint16 getFontFamilyId() { return _ffFamID; }
Common::Array<AsscEntry> *getAssocTable() { return &_ffAssocEntries; }
private:
+ Common::String _name;
+
// FOND
uint16 _ffFlags;
uint16 _ffFamID;
diff --git a/graphics/macgui/macfontmanager.cpp b/graphics/macgui/macfontmanager.cpp
index 667b9a8a633..324fa1caf6a 100644
--- a/graphics/macgui/macfontmanager.cpp
+++ b/graphics/macgui/macfontmanager.cpp
@@ -367,7 +367,7 @@ void MacFontManager::loadFonts(Common::MacResManager *fontFile) {
familyName = cleanFontName(familyName);
}
- Graphics::MacFontFamily *fontFamily = new MacFontFamily();
+ Graphics::MacFontFamily *fontFamily = new MacFontFamily(familyName);
fontFamily->load(*fond);
Common::Array<Graphics::MacFontFamily::AsscEntry> *assoc = fontFamily->getAssocTable();
diff --git a/graphics/macgui/macfontmanager.h b/graphics/macgui/macfontmanager.h
index f7ff03a2877..06c6fa8f86e 100644
--- a/graphics/macgui/macfontmanager.h
+++ b/graphics/macgui/macfontmanager.h
@@ -170,6 +170,8 @@ public:
void forceBuiltinFonts() { _builtInFonts = true; }
int parseSlantFromName(const Common::String &name);
+ const Common::Array<MacFontFamily *> &getFontFamilies() { return _fontFamilies; }
+
private:
void loadFontsBDF();
void loadFonts();
Commit: b578f5be7b039318a6b00875f7a659f9cb0c15fa
https://github.com/scummvm/scummvm/commit/b578f5be7b039318a6b00875f7a659f9cb0c15fa
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2022-11-06T23:05:20-08:00
Commit Message:
GRAPHICS: Expose Font leading and descent values
The leading value in Macintosh fonts is the space between lines,
defined as the space between a descent line and the ascent line
below it. Clients need this to draw text and calculate its height
as classic Macintosh did.
Changed paths:
graphics/font.cpp
graphics/font.h
graphics/fonts/macfont.h
diff --git a/graphics/font.cpp b/graphics/font.cpp
index 296bf802fe0..fbb1bffd660 100644
--- a/graphics/font.cpp
+++ b/graphics/font.cpp
@@ -31,6 +31,14 @@ int Font::getFontAscent() const {
return -1;
}
+int Font::getFontDescent() const {
+ return -1;
+}
+
+int Font::getFontLeading() const {
+ return -1;
+}
+
int Font::getKerningOffset(uint32 left, uint32 right) const {
return 0;
}
diff --git a/graphics/font.h b/graphics/font.h
index 658df0e5aa4..1b51fd8fc49 100644
--- a/graphics/font.h
+++ b/graphics/font.h
@@ -104,6 +104,24 @@ public:
*/
virtual int getFontAscent() const;
+ /**
+ * Return the descent of the font.
+ *
+ * @return Font descent in pixels. If it is unknown
+ * a value of -1 is returned.
+ */
+ virtual int getFontDescent() const;
+
+ /**
+ * Return the leading of the font.
+ * This is the distance between the descent line
+ * and the ascent line below it.
+ *
+ * @return Font leading in pixels. If it is unknown
+ * a value of -1 is returned.
+ */
+ virtual int getFontLeading() const;
+
/**
* Return the maximum width of the font.
*
diff --git a/graphics/fonts/macfont.h b/graphics/fonts/macfont.h
index f04b33b5f3d..38aa749b6e4 100644
--- a/graphics/fonts/macfont.h
+++ b/graphics/fonts/macfont.h
@@ -170,6 +170,8 @@ public:
virtual int getFontHeight() const { return _data._fRectHeight; }
virtual int getFontAscent() const { return _data._ascent; }
+ virtual int getFontDescent() const { return _data._descent; }
+ virtual int getFontLeading() const { return _data._leading; }
virtual int getMaxCharWidth() const { return _data._maxWidth; }
virtual int getCharWidth(uint32 chr) const;
virtual void drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const;
Commit: 1efdb1cb6c1b03da676b5546fc93189666596e26
https://github.com/scummvm/scummvm/commit/1efdb1cb6c1b03da676b5546fc93189666596e26
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2022-11-06T23:05:20-08:00
Commit Message:
SCI: Add support for Macintosh fonts
High-resolution native Macintosh fonts are now supported in the
following games when the game's executable is present:
- Castle of Dr. Brain
- Freddy Pharkas
- King's Quest 6
- Leisure Suit Larry 1
- Leisure Suit Larry 5
- Space Quest 1
And in these games when classicmacfonts.dat is present:
- Leisure Suit Larry 6 (floppy)
- Quest for Glory 1
Changed paths:
A engines/sci/graphics/macfont.cpp
A engines/sci/graphics/macfont.h
engines/sci/engine/kgraphics.cpp
engines/sci/graphics/controls16.cpp
engines/sci/graphics/controls16.h
engines/sci/graphics/scifont.h
engines/sci/graphics/screen.cpp
engines/sci/graphics/screen.h
engines/sci/graphics/text16.cpp
engines/sci/graphics/text16.h
engines/sci/module.mk
engines/sci/resource/resource.cpp
engines/sci/resource/resource.h
engines/sci/sci.cpp
engines/sci/sci.h
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index 785ae5bf263..239a402df3a 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -363,21 +363,29 @@ reg_t kTextSize(EngineState *s, int argc, reg_t *argv) {
int16 textWidth;
int16 textHeight;
- g_sci->_gfxText16->kernelTextSize(splitText.c_str(), languageSplitter, font, maxWidth, &textWidth, &textHeight);
-
- // One of the game texts in LB2 German contains loads of spaces in
- // its end. We trim the text here, otherwise the graphics code will
- // attempt to draw a very large window (larger than the screen) to
- // show the text, and crash.
- // Fixes bug #5710.
- if (textWidth >= g_sci->_gfxScreen->getDisplayWidth() ||
- textHeight >= g_sci->_gfxScreen->getDisplayHeight()) {
- warning("kTextSize: string would be too big to fit on screen. Trimming it");
- text.trim();
- // Copy over the trimmed string...
- s->_segMan->strcpy_(argv[1], text.c_str());
- // ...and recalculate bounding box dimensions
+ const bool useMacFonts = g_sci->hasMacFonts() && (argc < 6);
+ if (!useMacFonts) {
g_sci->_gfxText16->kernelTextSize(splitText.c_str(), languageSplitter, font, maxWidth, &textWidth, &textHeight);
+
+ // One of the game texts in LB2 German contains loads of spaces in
+ // its end. We trim the text here, otherwise the graphics code will
+ // attempt to draw a very large window (larger than the screen) to
+ // show the text, and crash.
+ // Fixes bug #5710.
+ if (textWidth >= g_sci->_gfxScreen->getDisplayWidth() ||
+ textHeight >= g_sci->_gfxScreen->getDisplayHeight()) {
+ warning("kTextSize: string would be too big to fit on screen. Trimming it");
+ text.trim();
+ // Copy over the trimmed string...
+ s->_segMan->strcpy_(argv[1], text.c_str());
+ // ...and recalculate bounding box dimensions
+ g_sci->_gfxText16->kernelTextSize(splitText.c_str(), languageSplitter, font, maxWidth, &textWidth, &textHeight);
+ }
+ } else {
+ // Mac games with native fonts always use them for sizing unless a sixth
+ // parameter is passed to indicate that SCI font sizing should be used.
+ // Only LSL5 is known to pass this parameter in Dialog:setSize.
+ g_sci->_gfxText16->macTextSize(splitText, font, g_sci->_gfxText16->GetFontId(), maxWidth, &textWidth, &textHeight);
}
debugC(kDebugLevelStrings, "GetTextSize '%s' -> %dx%d", text.c_str(), textWidth, textHeight);
diff --git a/engines/sci/graphics/controls16.cpp b/engines/sci/graphics/controls16.cpp
index e350f8dacd7..6135824fa80 100644
--- a/engines/sci/graphics/controls16.cpp
+++ b/engines/sci/graphics/controls16.cpp
@@ -328,7 +328,11 @@ void GfxControls16::kernelDrawButton(Common::Rect rect, reg_t obj, const char *t
_paint16->frameRect(rect);
rect.grow(-2);
_ports->textGreyedOutput(!(style & SCI_CONTROLS_STYLE_ENABLED));
- _text16->Box(text, languageSplitter, false, rect, SCI_TEXT16_ALIGNMENT_CENTER, fontId);
+ if (!g_sci->hasMacFonts()) {
+ _text16->Box(text, languageSplitter, false, rect, SCI_TEXT16_ALIGNMENT_CENTER, fontId);
+ } else {
+ _text16->macDraw(text, rect, SCI_TEXT16_ALIGNMENT_CENTER, fontId, _text16->GetFontId(), 0);
+ }
_ports->textGreyedOutput(false);
rect.grow(1);
if (style & SCI_CONTROLS_STYLE_SELECTED)
@@ -347,6 +351,15 @@ void GfxControls16::kernelDrawButton(Common::Rect rect, reg_t obj, const char *t
_paint16->invertRectViaXOR(rect);
else
_paint16->invertRect(rect);
+ if (g_sci->hasMacFonts()) {
+ // Mac scripts set a flag to tell the interpreter to draw white text when inverted.
+ // Note that KQ6 does not do this because it includes the PC version of the script,
+ // causing button text to disappear when clicked in the original.
+ uint16 textColor = (style & SCI_CONTROLS_STYLE_MAC_INVERTED) ? 255 : 0;
+ rect.grow(-1);
+ _text16->macDraw(text, rect, SCI_TEXT16_ALIGNMENT_CENTER, fontId, _text16->GetFontId(), textColor);
+ rect.grow(1);
+ }
_paint16->bitsShow(rect);
}
}
@@ -358,7 +371,11 @@ void GfxControls16::kernelDrawText(Common::Rect rect, reg_t obj, const char *tex
rect.grow(1);
_paint16->eraseRect(rect);
rect.grow(-1);
- _text16->Box(text, languageSplitter, false, rect, alignment, fontId);
+ if (!g_sci->hasMacFonts()) {
+ _text16->Box(text, languageSplitter, false, rect, alignment, fontId);
+ } else {
+ _text16->macDraw(text, rect, alignment, fontId, _text16->GetFontId(), 0);
+ }
if (style & SCI_CONTROLS_STYLE_SELECTED) {
_paint16->frameRect(rect);
}
diff --git a/engines/sci/graphics/controls16.h b/engines/sci/graphics/controls16.h
index 11a8ff6f783..4d030f3993f 100644
--- a/engines/sci/graphics/controls16.h
+++ b/engines/sci/graphics/controls16.h
@@ -25,9 +25,10 @@
namespace Sci {
enum controlStateFlags {
- SCI_CONTROLS_STYLE_ENABLED = 0x0001, ///< 0001 - enabled buttons
- SCI_CONTROLS_STYLE_DISABLED = 0x0004, ///< 0010 - grayed out buttons
- SCI_CONTROLS_STYLE_SELECTED = 0x0008 ///< 1000 - widgets surrounded by a frame
+ SCI_CONTROLS_STYLE_ENABLED = 0x0001, ///< enabled buttons
+ SCI_CONTROLS_STYLE_DISABLED = 0x0004, ///< grayed out buttons
+ SCI_CONTROLS_STYLE_SELECTED = 0x0008, ///< widgets surrounded by a frame
+ SCI_CONTROLS_STYLE_MAC_INVERTED = 0x0040 ///< control is inverted (mac-only for hi-res fonts)
};
// Control types and flags
diff --git a/engines/sci/graphics/macfont.cpp b/engines/sci/graphics/macfont.cpp
new file mode 100644
index 00000000000..12da36e83e9
--- /dev/null
+++ b/engines/sci/graphics/macfont.cpp
@@ -0,0 +1,161 @@
+/* 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/macresman.h"
+#include "graphics/fontman.h"
+#include "graphics/fonts/macfont.h"
+#include "graphics/macgui/macfontmanager.h"
+#include "graphics/macgui/macwindowmanager.h"
+#include "sci/graphics/macfont.h"
+
+namespace Sci {
+
+GfxMacFontManager::GfxMacFontManager(Common::MacResManager *macExecutable) :
+ _defaultFont(nullptr) {
+
+ if (macExecutable != nullptr) {
+ // Load fonts from mac executable.
+ // Use kWMModeForceBuiltinFonts to prevent MacFontManager from attempting
+ // to load fonts from classicmacfonts.dat, as we don't use them and it
+ // will produce a warning() when it's not present.
+ _usesSystemFonts = false;
+ uint32 mode = Graphics::MacGUIConstants::kWMModeForceBuiltinFonts;
+ _macFontManager = new Graphics::MacFontManager(mode, Common::Language::UNK_LANG);
+ _macFontManager->loadFonts(macExecutable);
+
+ // Register each font family that was loaded from the executable so that
+ // their Graphics::Font can be retrieved through FontManager::getFontByName().
+ const Common::Array<Graphics::MacFontFamily *> &fontFamilies = _macFontManager->getFontFamilies();
+ for (uint i = 0; i < fontFamilies.size(); ++i) {
+ _macFontManager->registerFontName(fontFamilies[i]->getName(), fontFamilies[i]->getFontFamilyId());
+ }
+
+ if (!initFromFontTable(macExecutable)) {
+ _macFonts.clear(true);
+ _defaultFont = nullptr;
+ }
+ } else {
+ // Load fonts from classicmacfonts.dat. This logs a warning if it can't be found.
+ _usesSystemFonts = true;
+ _macFontManager = new Graphics::MacFontManager(0, Common::Language::UNK_LANG);
+
+ // Load Palatino. These values were hard-coded in the interpreter in SciToMacFont.
+ const Graphics::Font *palatinoSmall = getMacFont(Graphics::kMacFontPalatino, 10);
+ const Graphics::Font *palatinoLarge = getMacFont(Graphics::kMacFontPalatino, 18);
+ if (palatinoSmall == nullptr || palatinoLarge == nullptr) {
+ return;
+ }
+
+ // Map all fonts to Palatino.
+ _defaultFont = new MacFontItem { palatinoSmall, palatinoLarge };
+ _macFonts.setVal(0, _defaultFont);
+ }
+}
+
+GfxMacFontManager::~GfxMacFontManager() {
+ for (Common::HashMap<GuiResourceId, MacFontItem *>::iterator it = _macFonts.begin(); it != _macFonts.end(); ++it) {
+ delete it->_value;
+ }
+ delete _macFontManager;
+}
+
+// The font mapping table is a small binary resource with id 128 and type `ftbl`
+bool GfxMacFontManager::initFromFontTable(Common::MacResManager *macExecutable) {
+ Common::SeekableReadStream *table = macExecutable->getResource(MKTAG('f', 't', 'b', 'l'), 128);
+ if (table == nullptr) {
+ warning("Mac font table not found in \"%s\"", macExecutable->getBaseFileName().rawString().c_str());
+ return false;
+ }
+
+ // Table header is 4 bytes followed by entries of 10 bytes each
+ uint16 defaultFontIndex = table->readUint16BE();
+ uint16 numberOfFonts = table->readUint16BE();
+ if (table->eos() || table->size() < 4 + numberOfFonts * 10) {
+ warning("Invalid mac font table in \"%s\"", macExecutable->getBaseFileName().rawString().c_str());
+ return false;
+ }
+
+ for (uint16 i = 0; i < numberOfFonts; ++i) {
+ uint16 sciFontId = table->readUint16BE();
+ if (_macFonts.contains(sciFontId)) {
+ warning("Duplicate Mac font table entry for %d in \"%s\"", sciFontId, macExecutable->getBaseFileName().rawString().c_str());
+ return false;
+ }
+ uint16 macFontId = table->readUint16BE();
+ uint16 smallFontSize = table->readUint16BE();
+ uint16 mediumFontSize = table->readUint16BE(); // large in KQ5 (not supported yet)
+ uint16 largeFontSize = table->readUint16BE();
+
+ const Graphics::Font *smallFont = getMacFont(macFontId, smallFontSize);
+ const Graphics::Font *largeFont = getMacFont(macFontId, MAX(mediumFontSize, largeFontSize));
+ if (smallFont == nullptr || largeFont == nullptr) {
+ warning("Mac font %d not found in \"%s\"", macFontId, macExecutable->getBaseFileName().rawString().c_str());
+ return false;
+ }
+
+ MacFontItem *font = new MacFontItem { smallFont, largeFont };
+ _macFonts.setVal(sciFontId, font);
+
+ if (i == defaultFontIndex) {
+ _defaultFont = font;
+ }
+ }
+
+ return true;
+}
+
+const Graphics::Font *GfxMacFontManager::getMacFont(int macFontId, int size) {
+ // Is this font in MacFontManager? This logs a warning if it isn't.
+ if (_macFontManager->getFontName(macFontId).empty()) {
+ return nullptr;
+ }
+
+ // Build a MacFont to get the full font name for this size and style (regular)
+ Graphics::MacFont macFont(macFontId, size, 0);
+ Common::String fontName = _macFontManager->getFontName(macFont);
+
+ // Get the font through the regular FontManager through which MacFontManager
+ // registered it when loading fonts. MacFontManager::getFont() does lots of
+ // extra stuff and fallback handling which we're not interested in.
+ // We just want the font if it's there and nullptr if it isn't. Our fallback
+ // behavior if we can't get the mac fonts is to use SCI fonts.
+ return FontMan.getFontByName(fontName);
+}
+
+bool GfxMacFontManager::hasFonts() {
+ return _defaultFont != nullptr;
+}
+
+bool GfxMacFontManager::usesSystemFonts() {
+ return _usesSystemFonts;
+}
+
+const Graphics::Font *GfxMacFontManager::getSmallFont(GuiResourceId sciFontId) {
+ MacFontItem *item = _macFonts.getValOrDefault(sciFontId, _defaultFont);
+ return item->smallFont;
+}
+
+const Graphics::Font *GfxMacFontManager::getLargeFont(GuiResourceId sciFontId) {
+ MacFontItem *item = _macFonts.getValOrDefault(sciFontId, _defaultFont);
+ return item->largeFont;
+}
+
+} // End of namespace Sci
diff --git a/engines/sci/graphics/macfont.h b/engines/sci/graphics/macfont.h
new file mode 100644
index 00000000000..3f9079da22f
--- /dev/null
+++ b/engines/sci/graphics/macfont.h
@@ -0,0 +1,104 @@
+/* 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 SCI_GRAPHICS_MACFONT_H
+#define SCI_GRAPHICS_MACFONT_H
+
+#include "common/hashmap.h"
+#include "sci/graphics/helpers.h" // for GuiResourceId
+
+namespace Common {
+class MacResManager;
+}
+namespace Graphics {
+class MacFontManager;
+class Font;
+}
+
+namespace Sci {
+
+/**
+ * GfxMacFontManager handles loading Mac fonts and mapping them to SCI fonts.
+ *
+ * Most Mac SCI1/1.1 games use native Mac fonts to draw their controls.
+ * This was done by altering the kernel functions used by the control scripts
+ * such as kDrawControl and kTextSize. All dialog text and buttons use these
+ * functions so this affects most text in SCI games. Scripts that draw text with
+ * kDisplay are unaffected and continue to use SCI fonts.
+ *
+ * The Mac game window could be set to three sizes: 100% (small), 150% (medium),
+ * or 200% (large). These percentages were relative to the internal resolution
+ * of the game; usually 320x200. The game's screen was stretched to the window
+ * and the Mac fonts were drawn directly to the window using Mac's Toolbox API.
+ * The Mac interpreter chose the font size based on the window size. At 200% the
+ * text was relatively high-resolution and looked quite crisp and distinct.
+ *
+ * The Mac fonts were originally included in the resource fork of the game's
+ * executable. The resource fork also contained a small table that specified
+ * the mapping of SCI font ids to Mac font ids, along with a default Mac font,
+ * and the Mac font sizes to use for the small, medium, and large window.
+ *
+ * Sierra switched to using the Palatino system font in QFG1VGA and LSL6.
+ * The font mapping table still existed, but the interpreter was hard-coded to
+ * always use Palatino values instead.
+ *
+ * GfxMacFontManager handles both cases by accepting the loaded Mac executable
+ * of games that include their own fonts. If no executable is provided then it
+ * attempts to use Palatino from classicmacfonts.dat along with the hard-coded
+ * values from Sierra's interpreter.
+ *
+ * GfxMacFontManager only exposes the small and large fonts. When Mac fonts are
+ * present, the game is upscaled to 200% and the large font is used for drawing.
+ * The small font is used for text calculations that determine the size of
+ * the text area, regardless of which font size is drawn on it.
+ *
+ * TODO: Add KQ5 support. It did things differently and it only had two window
+ * sizes. The mapping table changed and it appears to have its own sizing logic.
+ * Unfortunately, KQ5's interpreter doesn't include function names.
+ */
+class GfxMacFontManager {
+public:
+ GfxMacFontManager(Common::MacResManager *macExecutable = nullptr);
+ ~GfxMacFontManager();
+
+ bool hasFonts();
+ bool usesSystemFonts();
+ const Graphics::Font *getSmallFont(GuiResourceId sciFontId);
+ const Graphics::Font *getLargeFont(GuiResourceId sciFontId);
+
+private:
+ bool initFromFontTable(Common::MacResManager *macExecutable);
+ const Graphics::Font *getMacFont(int macFontId, int size);
+
+ struct MacFontItem {
+ const Graphics::Font *smallFont;
+ const Graphics::Font *largeFont;
+ };
+
+ bool _usesSystemFonts;
+ Graphics::MacFontManager *_macFontManager;
+ Common::HashMap<GuiResourceId, MacFontItem *> _macFonts;
+ MacFontItem *_defaultFont;
+};
+
+} // End of namespace Sci
+
+#endif
diff --git a/engines/sci/graphics/scifont.h b/engines/sci/graphics/scifont.h
index b1b764e88e6..2354c928304 100644
--- a/engines/sci/graphics/scifont.h
+++ b/engines/sci/graphics/scifont.h
@@ -22,6 +22,7 @@
#ifndef SCI_GRAPHICS_SCIFONT_H
#define SCI_GRAPHICS_SCIFONT_H
+#include "sci/resource/resource.h"
#include "sci/graphics/helpers.h"
#include "sci/util.h"
diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp
index 937e31dcd56..efc140df333 100644
--- a/engines/sci/graphics/screen.cpp
+++ b/engines/sci/graphics/screen.cpp
@@ -67,12 +67,17 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) {
if ((g_sci->getLanguage() == Common::JA_JPN) && (getSciVersion() <= SCI_VERSION_1_1))
_upscaledHires = GFX_SCREEN_UPSCALED_640x400;
- // Macintosh SCI0 games used 480x300, while the scripts were running at 320x200
if (g_sci->getPlatform() == Common::kPlatformMacintosh) {
if (getSciVersion() <= SCI_VERSION_01) {
+ // Macintosh SCI0 games used 480x300, while the scripts were running at 320x200
_upscaledHires = GFX_SCREEN_UPSCALED_480x300;
_width = 480;
_height = 300; // regular visual, priority and control map are 480x300 (this is different than other upscaled SCI games)
+ } else {
+ // Macintosh SCI1/1.1 games use hi-res native fonts
+ if (g_sci->hasMacFonts()) {
+ _upscaledHires = GFX_SCREEN_UPSCALED_640x400;
+ }
}
// Some Mac SCI1/1.1 games only take up 190 rows and do not
@@ -112,8 +117,10 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) {
break;
case GFX_SCREEN_UPSCALED_640x400:
// Police Quest 2 and Quest For Glory on PC9801 (Japanese)
- _displayWidth = 640;
- _displayHeight = 400;
+ // Mac SCI1/1.1 with hi-res Mac fonts
+ // Korean fan translations
+ _displayWidth = _scriptWidth * 2;
+ _displayHeight = _scriptHeight * 2;
for (int i = 0; i <= _scriptHeight; i++)
_upscaledHeightMapping[i] = i * 2;
for (int i = 0; i <= _scriptWidth; i++)
@@ -145,6 +152,11 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) {
_priorityScreen = (byte *)calloc(_pixels, 1);
_controlScreen = (byte *)calloc(_pixels, 1);
_displayScreen = (byte *)calloc(_displayPixels, 1);
+
+ // Create a Surface for _displayPixels so that we can draw to it from interfaces
+ // that only draw to Surfaces. Currently that's just Graphics::Font.
+ Graphics::PixelFormat format8 = Graphics::PixelFormat::createFormatCLUT8();
+ _displayScreenSurface.init(_displayWidth, _displayHeight, _displayWidth, _displayScreen, format8);
memset(&_ditheredPicColors, 0, sizeof(_ditheredPicColors));
@@ -177,22 +189,32 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) {
}
// Initialize the actual screen
- Graphics::PixelFormat format8 = Graphics::PixelFormat::createFormatCLUT8();
const Graphics::PixelFormat *format = &format8;
if (ConfMan.getBool("rgb_rendering"))
format = nullptr; // Backend's preferred mode; RGB if available
if (g_sci->hasMacIconBar()) {
// For SCI1.1 Mac games with the custom icon bar, we need to expand the screen
- // to accommodate for the icon bar. Of course, both KQ6 and QFG1 VGA differ in size.
+ // to accommodate for the icon bar. Of course, both KQ6 and Freddy Pharkas differ in size.
// We add 2 to the height of the icon bar to add a buffer between the screen and the
// icon bar (as did the original interpreter).
- if (g_sci->getGameId() == GID_KQ6)
- initGraphics(_displayWidth, _displayHeight + 26 + 2, format);
- else if (g_sci->getGameId() == GID_FREDDYPHARKAS)
- initGraphics(_displayWidth, _displayHeight + 28 + 2, format);
- else
+ int macIconBarBuffer = 0;
+ switch (g_sci->getGameId()) {
+ case GID_KQ6:
+ macIconBarBuffer = 26 + 2;
+ break;
+ case GID_FREDDYPHARKAS:
+ macIconBarBuffer = 28 + 2;
+ break;
+ default:
error("Unknown SCI1.1 Mac game");
+ }
+
+ if (_upscaledHires == GFX_SCREEN_UPSCALED_640x400) {
+ macIconBarBuffer *= 2;
+ }
+
+ initGraphics(_displayWidth, _displayHeight + macIconBarBuffer, format);
} else
initGraphics(_displayWidth, _displayHeight, format);
@@ -618,6 +640,12 @@ void GfxScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte
}
}
+// We put hi-res native Mac fonts onto an upscaled background.
+// The incoming coordinates are already hi-res.
+void GfxScreen::putHiresChar(const Graphics::Font *commonFont, int16 x, int16 y, uint16 chr, byte color) {
+ commonFont->drawChar(&_displayScreenSurface, chr, x, y, color);
+}
+
// We put hires hangul chars onto upscaled background, so we need to adjust
// coordinates. Caller gives use low-res ones.
void GfxScreen::putHangulChar(Graphics::FontKorean *commonFont, int16 x, int16 y, uint16 chr, byte color) {
diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h
index 77283fe7e2b..d99941e7057 100644
--- a/engines/sci/graphics/screen.h
+++ b/engines/sci/graphics/screen.h
@@ -26,6 +26,7 @@
#include "sci/graphics/helpers.h"
#include "sci/graphics/view.h"
+#include "graphics/font.h"
#include "graphics/sjis.h"
#include "graphics/korfont.h"
#include "graphics/pixelformat.h"
@@ -117,6 +118,7 @@ public:
}
void enableUndithering(bool flag);
+ void putHiresChar(const Graphics::Font *commonFont, int16 x, int16 y, uint16 chr, byte color);
void putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, uint16 chr, byte color);
void putHangulChar(Graphics::FontKorean *commonFont, int16 x, int16 y, uint16 chr, byte color);
@@ -196,6 +198,7 @@ private:
* Only read from this buffer for Save/ShowBits usage.
*/
byte *_displayScreen;
+ Graphics::Surface _displayScreenSurface;
// Screens for RGB mode support
byte *_displayedScreen;
diff --git a/engines/sci/graphics/text16.cpp b/engines/sci/graphics/text16.cpp
index b7e1c0cdcd2..91699fa4efe 100644
--- a/engines/sci/graphics/text16.cpp
+++ b/engines/sci/graphics/text16.cpp
@@ -22,6 +22,7 @@
#include "common/util.h"
#include "common/stack.h"
#include "common/unicode-bidi.h"
+#include "graphics/font.h"
#include "graphics/primitives.h"
#include "sci/sci.h"
@@ -29,6 +30,7 @@
#include "sci/engine/state.h"
#include "sci/graphics/cache.h"
#include "sci/graphics/coordadjuster.h"
+#include "sci/graphics/macfont.h"
#include "sci/graphics/ports.h"
#include "sci/graphics/paint16.h"
#include "sci/graphics/scifont.h"
@@ -37,8 +39,8 @@
namespace Sci {
-GfxText16::GfxText16(GfxCache *cache, GfxPorts *ports, GfxPaint16 *paint16, GfxScreen *screen)
- : _cache(cache), _ports(ports), _paint16(paint16), _screen(screen) {
+GfxText16::GfxText16(GfxCache *cache, GfxPorts *ports, GfxPaint16 *paint16, GfxScreen *screen, GfxMacFontManager *macFontManager)
+ : _cache(cache), _ports(ports), _paint16(paint16), _screen(screen), _macFontManager(macFontManager) {
init();
}
@@ -824,4 +826,199 @@ void GfxText16::kernelTextColors(int argc, reg_t *argv) {
}
}
+// This function is roughly equivalent to RTextSizeMac.
+// (SCI1.1 Mac interpreters include function names.)
+// The results of this function determine the size of SCI message boxes over
+// which macDraw() is called later. Even though the Mac interpreter would use
+// one of three font sizes for drawing, depending on the window size the user
+// had selected, these calculations always use the small font. Otherwise, the
+// size of the window would affect the size of the message box within the game,
+// instead of just the text that was drawn within it.
+void GfxText16::macTextSize(const Common::String &text, GuiResourceId sciFontId, GuiResourceId origSciFontId, int16 maxWidth, int16 *textWidth, int16 *textHeight) {
+ if (sciFontId == -1) {
+ sciFontId = origSciFontId;
+ }
+
+ // Always use the small font for calculating text size
+ const Graphics::Font *font = _macFontManager->getSmallFont(sciFontId);
+
+ // If maxWidth is negative then return the size of all characters on the same line
+ if (maxWidth < 0) {
+ *textWidth = 0;
+ for (uint i = 0; i < text.size(); ++i) {
+ *textWidth += font->getCharWidth(text[i]);
+ }
+ *textHeight = font->getFontAscent();
+ return;
+ }
+
+ // Default max width is 193, otherwise increment the specified max
+ maxWidth = (maxWidth == 0) ? 193 : (maxWidth + 1);
+
+ // Build lists of lines and widths and calculate the largest line width.
+ // The Mac interpreter did this by creating a hidden TEdit, settings its width
+ // and text, and then querying TEdit's internal structures to count the lines
+ // and find the largest. This means that Mac's own text wrapping algorithm
+ // determined kTextResult results and the resulting message box sizes.
+ // Due to the specifics of Mac's text-wrapping, it's possible for resulting
+ // lines to be larger than maxWidth. See macGetLongest().
+ Common::Array<Common::String> lines;
+ Common::Array<int16> lineWidths;
+ int16 maxLineCharCount = 0;
+ int16 maxLineWidth = 0;
+ int lineCount = 0;
+ for (uint i = 0; i < text.size(); ++i) {
+ int16 lineWidth;
+ int16 lineCharCount = macGetLongest(text, i, font, maxWidth, &lineWidth);
+
+ Common::String line;
+ for (int16 j = 0; j < lineCharCount; ++j) {
+ char ch = text[i + j];
+ if (ch == '\r' || ch == '\n') {
+ break;
+ }
+ if (ch == '\t') {
+ ch = ' ';
+ }
+ line += ch;
+ }
+ lines.push_back(line);
+ lineWidths.push_back(lineWidth);
+ maxLineCharCount = MAX(lineCharCount, maxLineCharCount);
+
+ if (lineCharCount == 0) {
+ break;
+ }
+ maxLineWidth = MAX(lineWidth, maxLineWidth);
+ lineCount++;
+ i += (lineCharCount - 1);
+ }
+
+ // Mac TEdit line widths are 1 pixel wider than the sum of their character widths.
+ // This extra pixel comes from the TEdit structure the Mac interpreter queries.
+ *textWidth = maxLineWidth + 1;
+ if (_macFontManager->usesSystemFonts()) {
+ // QFG1VGA and LSL6 add another pixel to returned widths.
+ *textWidth += 1;
+ }
+
+ // Mac TEdit height is the sum of font height and leading, which is space between lines.
+ // Leading can be zero for fonts that have spacing embedded in their glyphs.
+ *textHeight = lineCount * (font->getFontHeight() + font->getFontLeading());
+
+ if (_macFontManager->usesSystemFonts()) {
+ // QFG1VGA and LSL6 make this adjustment when the large font is used.
+ *textHeight -= (lineCount + 1);
+ }
+}
+
+// This function is roughly equivalent to RTextBoxMac.
+// (SCI1.1 Mac interpreters include function names.)
+// The main difference is that we draw each character ourselves.
+// RTextBoxMac just created a TEdit with a transparent background, set its
+// properties, and then had Mac render it on the window.
+void GfxText16::macDraw(const Common::String &text, Common::Rect rect, TextAlignment alignment, GuiResourceId sciFontId, GuiResourceId origSciFontId, int16 color) {
+ if (sciFontId == -1) {
+ sciFontId = origSciFontId;
+ }
+
+ // Always use the large font
+ const Graphics::Font *font = _macFontManager->getLargeFont(sciFontId);
+
+ if (color == -1) {
+ color = g_sci->_gfxPorts->_curPort->penClr;
+ }
+
+ // We are drawing in high resolution
+ rect.left *= 2;
+ rect.top *= 2;
+ rect.right *= 2;
+ rect.bottom *= 2;
+
+ // Draw each line of text
+ int16 maxWidth = rect.width();
+ int16 y = (g_sci->_gfxPorts->_curPort->top * 2) + rect.top;
+ for (uint i = 0; i < text.size(); ++i) {
+ int16 lineWidth;
+ int16 lineCharCount = macGetLongest(text, i, font, maxWidth, &lineWidth);
+ if (lineCharCount == 0) {
+ break;
+ }
+
+ int16 offset = 0;
+ if (alignment == SCI_TEXT16_ALIGNMENT_CENTER) {
+ offset = (maxWidth - lineWidth) / 2;
+ } else if (alignment == SCI_TEXT16_ALIGNMENT_RIGHT) {
+ offset = maxWidth - lineWidth;
+ }
+
+ // Draw each character in the line
+ int16 x = (g_sci->_gfxPorts->_curPort->left * 2) + rect.left + offset;
+ for (int16 j = 0; j < lineCharCount; ++j) {
+ char ch = text[i + j];
+ g_sci->_gfxScreen->putHiresChar(font, x, y, ch, color);
+ x += font->getCharWidth(ch);
+ }
+
+ y += font->getFontHeight() + font->getFontLeading();
+ i += (lineCharCount - 1);
+ }
+}
+
+// This function mimics classic Mac's TEdit text wrapping behavior in a style
+// similar to GfxText16::GetLongest() that we use for SCI text measurement.
+// This implementation is based on black-box reverse engineering System 7.5.5
+// behavior by inspecting the calculated TEdit widths and modding SCI games to
+// display the results of kTextSize and altering their strings to test various
+// inputs. It's possible that this Mac behavior was ROM or OS version dependent.
+// In general, line width calculations work as one would expect, except for the
+// oddity that space characters are applied to the current line and included
+// in the calculated width even if that results in widths larger than maxWidth.
+int16 GfxText16::macGetLongest(const Common::String &text, uint start, const Graphics::Font *font, int16 maxWidth, int16 *lineWidth) {
+ *lineWidth = 0;
+ int wordWidth = 0;
+ int wordStart = start;
+ char prevChar = '\0';
+ for (uint i = start; i < text.size(); ++i) {
+ char ch = text[i];
+ int charWidth = font->getCharWidth(ch);
+ if (ch == '\r') {
+ *lineWidth += wordWidth;
+ wordWidth = 0;
+ // ignore \n that follows \r
+ if (i + 1 < text.size() && text[i + 1] == '\n') {
+ ++i;
+ }
+ wordStart = i + 1;
+ return wordStart - start;
+ } else if (ch == '\n') {
+ *lineWidth += wordWidth;
+ wordWidth = 0;
+ wordStart = i + 1;
+ return wordStart - start;
+ } else if (prevChar == ' ' && ch != ' ') {
+ // start new word once a non-space is reached
+ *lineWidth += wordWidth;
+ wordWidth = charWidth;
+ wordStart = i;
+ } else {
+ // add character to word width, including spaces
+ wordWidth += charWidth;
+ }
+
+ // If the line plus the current width has reached maxWidth then we are done,
+ // unless the current character is a space. Spaces continue to be applied
+ // to the line regardless of maxWidth. This means that a line's width can
+ // be larger than maxWidth due to whitespace, resulting in a larger text box
+ // than what was requested, but that is indeed what happens in classic Mac.
+ if (*lineWidth + wordWidth >= maxWidth && ch != ' ') {
+ return wordStart - start;
+ }
+
+ prevChar = ch;
+ }
+ *lineWidth += wordWidth;
+ return text.size() - start;
+}
+
} // End of namespace Sci
diff --git a/engines/sci/graphics/text16.h b/engines/sci/graphics/text16.h
index 40e8f3d635b..833332a3dc7 100644
--- a/engines/sci/graphics/text16.h
+++ b/engines/sci/graphics/text16.h
@@ -22,6 +22,10 @@
#ifndef SCI_GRAPHICS_TEXT16_H
#define SCI_GRAPHICS_TEXT16_H
+namespace Graphics {
+class Font;
+}
+
namespace Sci {
#define SCI_TEXT16_ALIGNMENT_RIGHT -1
@@ -34,12 +38,13 @@ class GfxPorts;
class GfxPaint16;
class GfxScreen;
class GfxFont;
+class GfxMacFontManager;
/**
* Text16 class, handles text calculation and displaying of text for SCI0->SCI1.1 games
*/
class GfxText16 {
public:
- GfxText16(GfxCache *fonts, GfxPorts *ports, GfxPaint16 *paint16, GfxScreen *screen);
+ GfxText16(GfxCache *fonts, GfxPorts *ports, GfxPaint16 *paint16, GfxScreen *screen, GfxMacFontManager *macFontManager);
~GfxText16();
GuiResourceId GetFontId();
@@ -75,16 +80,20 @@ public:
void kernelTextFonts(int argc, reg_t *argv);
void kernelTextColors(int argc, reg_t *argv);
+ void macTextSize(const Common::String &text, GuiResourceId sciFontId, GuiResourceId origSciFontId, int16 maxWidth, int16 *textWidth, int16 *textHeight);
+ void macDraw(const Common::String &text, Common::Rect rect, TextAlignment alignment, GuiResourceId sciFontId, GuiResourceId origSciFontId, int16 color);
private:
void init();
bool SwitchToFont1001OnKorean(const char *text, uint16 languageSplitter);
bool SwitchToFont900OnSjis(const char *text, uint16 languageSplitter);
static bool isJapaneseNewLine(int16 curChar, int16 nextChar);
+ int16 macGetLongest(const Common::String &text, uint start, const Graphics::Font *font, int16 maxWidth, int16 *lineWidth);
GfxCache *_cache;
GfxPorts *_ports;
GfxPaint16 *_paint16;
GfxScreen *_screen;
+ GfxMacFontManager *_macFontManager; // null when not applicable
int _codeFontsCount;
GuiResourceId *_codeFonts;
diff --git a/engines/sci/module.mk b/engines/sci/module.mk
index fb4febe68f8..d72f06bee67 100644
--- a/engines/sci/module.mk
+++ b/engines/sci/module.mk
@@ -47,8 +47,9 @@ MODULE_OBJS := \
graphics/controls16.o \
graphics/coordadjuster.o \
graphics/cursor.o \
- graphics/fontsjis.o \
graphics/fontkorean.o \
+ graphics/fontsjis.o \
+ graphics/macfont.o \
graphics/maciconbar.o \
graphics/menu.o \
graphics/paint16.o \
diff --git a/engines/sci/resource/resource.cpp b/engines/sci/resource/resource.cpp
index fcaffdc8cad..1eac58640b5 100644
--- a/engines/sci/resource/resource.cpp
+++ b/engines/sci/resource/resource.cpp
@@ -3122,6 +3122,28 @@ Common::String ResourceManager::findSierraGameId(const bool isBE) {
return heap->getStringAt(offset);
}
+// Mac executables are currently used for icon bars and native fonts.
+// Eventually they should be used for native menus and possibly even splash screens.
+// For example, LSL6 can't function without native menus. (bug #11356)
+// Executables that we currently don't use are commented out.
+Common::String ResourceManager::getMacExecutableName() const {
+ switch (g_sci->getGameId()) {
+ case GID_CASTLEBRAIN: return "Castle of Dr. Brain"; // fonts, splash screen
+ case GID_FREDDYPHARKAS: return "Freddy Pharkas"; // fonts, icon bar, menu, splash screen
+ //case GID_HOYLE4: return "Hoyle"; // menu, splash screen
+ //case GID_KQ5: return "King's Quest V"; // fonts (not supported yet), splash screen
+ case GID_KQ6: return "King's Quest VI"; // fonts, icon bar, menu, splash screen
+ case GID_LSL1: return "Leisure Suit Larry 1"; // fonts, splash screen
+ case GID_LSL5: return "Leisure Suit Larry 5"; // fonts, splash screen
+ //case GID_LSL6: return "Leisure Suit Larry 6"; // menu, splash screen
+ //case GID_QFG1VGA: return "Quest for Glory"; // menu, splash screen
+ case GID_SQ1: return "Space Quest 1"; // fonts, splash screen
+ //case GID_SQ3: return "SQ3"; // menu, splash screen
+ //case GID_SQ4: return "Space Quest IV"; // splash screen
+ default: return "";
+ }
+}
+
bool ResourceManager::isKoreanMessageMap(ResourceSource *source) {
return source->getLocationName() == "message.map" && g_sci && g_sci->getLanguage() == Common::KO_KOR;
}
diff --git a/engines/sci/resource/resource.h b/engines/sci/resource/resource.h
index 57e15bb6090..5187cbd637f 100644
--- a/engines/sci/resource/resource.h
+++ b/engines/sci/resource/resource.h
@@ -644,6 +644,8 @@ protected:
void detectSciVersion();
public:
+ /** Returns the file name of the game's Mac executable. */
+ Common::String getMacExecutableName() const;
bool isKoreanMessageMap(ResourceSource *source);
private:
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index 2b413e95907..16b1455ddf0 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -54,6 +54,7 @@
#include "sci/graphics/controls16.h"
#include "sci/graphics/coordadjuster.h"
#include "sci/graphics/cursor.h"
+#include "sci/graphics/macfont.h"
#include "sci/graphics/maciconbar.h"
#include "sci/graphics/menu.h"
#include "sci/graphics/paint16.h"
@@ -99,6 +100,7 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc, SciGameId gam
_gfxScreen(nullptr),
_gfxText16(nullptr),
_gfxTransitions(nullptr),
+ _gfxMacFontManager(nullptr),
_gfxMacIconBar(nullptr),
#ifdef ENABLE_SCI32
_gfxControls32(nullptr),
@@ -246,6 +248,7 @@ SciEngine::~SciEngine() {
//_console deleted by Engine
delete _guestAdditions;
delete _features;
+ delete _gfxMacFontManager;
delete _gfxMacIconBar;
delete _eventMan;
@@ -304,6 +307,13 @@ Common::Error SciEngine::run() {
}
if (getSciVersion() < SCI_VERSION_2) {
+ // Load the Mac executable and fonts if available.
+ // If fonts are found then GfxScreen will enable upscaling.
+ if (getPlatform() == Common::kPlatformMacintosh) {
+ loadMacExecutable();
+ loadMacFonts();
+ }
+
// Initialize the game screen
_gfxScreen = new GfxScreen(_resMan);
_gfxScreen->enableUndithering(ConfMan.getBool("disable_dithering"));
@@ -354,9 +364,6 @@ Common::Error SciEngine::run() {
// Must be called after game_init(), as they use _features
_kernel->loadKernelNames(_features);
- // Load our Mac executable here for icon bar palettes and high-res fonts
- loadMacExecutable();
-
// Initialize all graphics related subsystems
initGraphics();
@@ -627,7 +634,7 @@ void SciEngine::initGraphics() {
_gfxTransitions = new GfxTransitions(_gfxScreen, _gfxPalette16);
_gfxPaint16 = new GfxPaint16(_resMan, _gamestate->_segMan, _gfxCache, _gfxPorts, _gfxCoordAdjuster, _gfxScreen, _gfxPalette16, _gfxTransitions, _audio);
_gfxAnimate = new GfxAnimate(_gamestate, _scriptPatcher, _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen, _gfxPalette16, _gfxCursor, _gfxTransitions);
- _gfxText16 = new GfxText16(_gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen);
+ _gfxText16 = new GfxText16(_gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen, _gfxMacFontManager);
_gfxControls16 = new GfxControls16(_gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen);
_gfxMenu = new GfxMenu(_eventMan, _gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen, _gfxCursor);
@@ -787,8 +794,12 @@ bool SciEngine::hasParser() const {
getGameId() == GID_LSL3 || getGameId() == GID_SQ3;
}
+bool SciEngine::hasMacFonts() const {
+ return _gfxMacFontManager != nullptr;
+}
+
bool SciEngine::hasMacIconBar() const {
- return _resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1 &&
+ return _resMan->isSci11Mac() &&
(getGameId() == GID_KQ6 || getGameId() == GID_FREDDYPHARKAS);
}
@@ -946,22 +957,7 @@ void SciEngine::updateSoundMixerVolumes() {
}
void SciEngine::loadMacExecutable() {
- if (getPlatform() != Common::kPlatformMacintosh || getSciVersion() < SCI_VERSION_1_EARLY || getSciVersion() > SCI_VERSION_1_1)
- return;
-
- Common::String filename;
-
- switch (getGameId()) {
- case GID_KQ6:
- filename = "King's Quest VI";
- break;
- case GID_FREDDYPHARKAS:
- filename = "Freddy Pharkas";
- break;
- default:
- break;
- }
-
+ Common::String filename = _resMan->getMacExecutableName();
if (filename.empty())
return;
@@ -969,9 +965,48 @@ void SciEngine::loadMacExecutable() {
// KQ6/Freddy require the executable to load their icon bar palettes
if (hasMacIconBar())
error("Could not load Mac resource fork '%s'", filename.c_str());
+ }
+}
- // TODO: Show some sort of warning dialog saying they can't get any
- // high-res Mac fonts, when we get to that point ;)
+void SciEngine::loadMacFonts() {
+ // Load Mac fonts from the appropriate place, depending on the game.
+ // If we're unable to load Mac fonts, then fall back to using SCI fonts.
+ // Mac font support was added after these games were supported, so it's
+ // important to not require that fonts be present.
+ switch (g_sci->getGameId()) {
+ case GID_CASTLEBRAIN:
+ case GID_FREDDYPHARKAS:
+ // case GID_KQ5: // not supported yet
+ case GID_KQ6:
+ case GID_LSL1:
+ case GID_LSL5:
+ case GID_SQ1:
+ // These Mac games have fonts in the resource fork of their executable
+ // along with a SCI to Mac font mapping table.
+ if (_macExecutable.hasResFork()) {
+ _gfxMacFontManager = new GfxMacFontManager(&_macExecutable);
+ if (!_gfxMacFontManager->hasFonts()) {
+ delete _gfxMacFontManager;
+ _gfxMacFontManager = nullptr;
+ }
+ } else {
+ Common::String filename = _resMan->getMacExecutableName();
+ warning("Macintosh executable \"%s\" not found, using SCI fonts", filename.c_str());
+ }
+ break;
+ case GID_LSL6:
+ case GID_QFG1VGA:
+ // These Mac games have interpreters that are hard-coded to use Palatino.
+ // Attempt to load Palatino from classicmacfonts.dat.
+ _gfxMacFontManager = new GfxMacFontManager();
+ if (!_gfxMacFontManager->hasFonts()) {
+ warning("Classic Macintosh fonts not found, using SCI fonts");
+ delete _gfxMacFontManager;
+ _gfxMacFontManager = nullptr;
+ }
+ break;
+ default:
+ break;
}
}
diff --git a/engines/sci/sci.h b/engines/sci/sci.h
index e198e5ddebc..08103db4a1c 100644
--- a/engines/sci/sci.h
+++ b/engines/sci/sci.h
@@ -66,6 +66,7 @@ class GfxControls16;
class GfxControls32;
class GfxCoordAdjuster16;
class GfxCursor;
+class GfxMacFontManager;
class GfxMacIconBar;
class GfxMenu;
class GfxPaint16;
@@ -193,7 +194,18 @@ public:
bool isBE() const;
bool hasParser() const;
+
+ /** Returns true if the game supports native Mac fonts and the fonts are available. */
+ bool hasMacFonts() const;
+
+ /** Returns true if the game is a Mac version with an icon bar on the bottom. */
bool hasMacIconBar() const;
+
+ /**
+ * Returns true if the game is a Mac version that used native Mac file dialogs
+ * for saving and restoring. These versions do not include resources for the
+ * normal save and restore screens, so the ScummVM UI must always be used.
+ */
bool hasMacSaveRestoreDialogs() const;
inline ResourceManager *getResMan() const { return _resMan; }
@@ -283,6 +295,7 @@ public:
GfxText16 *_gfxText16;
GfxTransitions *_gfxTransitions; // transitions between screens for 16-bit gfx
GfxMacIconBar *_gfxMacIconBar; // Mac Icon Bar manager
+ GfxMacFontManager *_gfxMacFontManager; // null when not applicable
SciTTS *_tts;
#ifdef ENABLE_SCI32
@@ -339,10 +352,22 @@ private:
void exitGame();
/**
- * Loads the Mac executable for SCI1 games
+ * Loads the Mac executable for SCI1/1.1 games.
+ * This function should only be called on Mac games.
+ * If the executable isn't used, or is missing but optional,
+ * then this function does nothing.
*/
void loadMacExecutable();
+ /**
+ * Loads Mac native fonts for SCI1/1.1 games that support them.
+ * This function should only be called on Mac games after loadMacExecutable()
+ * has been called. Depending on the game, fonts are loaded from either the
+ * executable or from classicmacfonts.dat. If fonts are not present, then a
+ * warning is logged and SCI fonts are used instead.
+ */
+ void loadMacFonts();
+
void initStackBaseWithSelector(Selector selector);
bool gameHasFanMadePatch();
Commit: daed465639b625ef6f16c538a039102f44d2d967
https://github.com/scummvm/scummvm/commit/daed465639b625ef6f16c538a039102f44d2d967
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2022-11-06T23:05:20-08:00
Commit Message:
SCI: Add option for high resolution Mac fonts
This adds the existing GAMEOPTION_HIGH_RESOLUTION_GRAPHICS option to
Mac games with native fonts. Default is enabled. If disabled, then the
low resolution Mac fonts are used and the game isn't upscaled.
Changed paths:
engines/sci/detection_tables.h
engines/sci/engine/kernel.cpp
engines/sci/engine/kmisc.cpp
engines/sci/graphics/macfont.h
engines/sci/graphics/screen.cpp
engines/sci/graphics/screen.h
engines/sci/graphics/text16.cpp
engines/sci/sci.cpp
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index 6235ea601f0..c6a3853ef43 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -28,6 +28,7 @@ namespace Sci {
#define GUIO_STD16_SPEECH GUIO4(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_MIDI_MODE, GAMEOPTION_RGB_RENDERING)
#define GUIO_STD16_SPEECH_GM GUIO5(GUIO_MIDIGM, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_MIDI_MODE, GAMEOPTION_RGB_RENDERING)
#define GUIO_STD16_MAC GUIO5(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_MIDI_MODE, GAMEOPTION_RGB_RENDERING, GAMEOPTION_TTS)
+#define GUIO_STD16_MAC_HIRESFONTS GUIO6(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_MIDI_MODE, GAMEOPTION_HIGH_RESOLUTION_GRAPHICS, GAMEOPTION_RGB_RENDERING, GAMEOPTION_TTS)
#define GUIO_STD16_MAC_UNDITHER GUIO6(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_MIDI_MODE, GAMEOPTION_RGB_RENDERING, GAMEOPTION_TTS)
#define GUIO_STD16_MAC_PALETTEMODS GUIO7(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_MIDI_MODE, GAMEOPTION_RGB_RENDERING, GAMEOPTION_PALETTE_MODS, GAMEOPTION_TTS)
#define GUIO_STD16_MAC_SPEECH GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_MIDI_MODE, GAMEOPTION_RGB_RENDERING)
@@ -84,7 +85,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "e1a6b6f1060f60be9dcb6d28ad7a2a20", 1168310},
{"resource.003", 0, "6c3d1bb26ad532c94046bc9ac49b5ff4", 891295},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO_STD16_MAC },
+ Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO_STD16_MAC_HIRESFONTS },
// Castle of Dr. Brain - English DOS Non-Interactive Demo
// SCI interpreter version 1.000.005
@@ -817,7 +818,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"Data1", 0, "ef7cbd62727989818f1cfae69c9fd61d", 3038236},
{"Data2", 0, "2424b418f7d52c385cea4701f529c69a", 4721476},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO_STD16_MAC },
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO_STD16_MAC_HIRESFONTS },
// Fun Seeker's Guide - English DOS
// SCI interpreter version 0.000.506
@@ -2298,7 +2299,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"Data1", 0, "a183fc0c22fcbd9be4c8800d974b5599", 3891868},
{"Data2", 0, "b3722460dfd3097a1fbaf99a21ad8ea5", 15031016},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO_STD16_MAC },
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO_STD16_MAC_HIRESFONTS },
#undef GUIO_KQ6_DEMO
#undef GUIO_KQ6_CD
@@ -2866,7 +2867,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.001", 0, "aa6f153f70f1e32d1bde465fff08eecf", 1137418},
{"resource.002", 0, "b22c616aa789ebef990290c7ffd86548", 1097477},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO_STD16_MAC },
+ Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO_STD16_MAC_HIRESFONTS },
// Larry 1 VGA Remake - English DOS Non-Interactive Demo
// SCI interpreter version 1.000.084
@@ -3286,7 +3287,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1110043},
{"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 989801},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO_STD16_MAC },
+ Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO_STD16_MAC_HIRESFONTS },
// Larry 5 - German DOS (from Tobis87)
// SCI interpreter version T.A00.196
@@ -3431,7 +3432,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"Data1", 0, "482e6bcdda3a89390d5c4bcbfb5896b4", 2754651},
{"Data2", 0, "ba0799a45076780dfbceb8fce4c549c9", 5846089},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK | ADGF_UNSTABLE, GUIO_STD16_MAC },
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK | ADGF_UNSTABLE, GUIO_STD16_MAC_HIRESFONTS },
// Crazy Nick's Software Picks: Leisure Suit Larry's Casino - English DOS (from the Leisure Suit Larry Collection)
// Executable scanning reports "1.001.029", VERSION file reports "1.000"
@@ -4729,7 +4730,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"Data1", 0, "106527ff8756e4e1a795d63d23e8b833", 1752102},
{"Data2", 0, "5cdd92033231159c6e9c71d43e9f194d", 6574490},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO_STD16_MAC },
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO_STD16_MAC_HIRESFONTS },
// Quest for Glory 2 - English Amiga
// Game version 1.109
@@ -5319,7 +5320,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "ae46e195e66df5a131917f0aa80b5669", 1242794},
{"resource.004", 0, "91d58a9eb2187c38424990afe4c12bc6", 1250949},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO_STD16_MAC },
+ Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO_STD16_MAC_HIRESFONTS },
// Space Quest 1 VGA Remake - English Non-Interactive Demo (from FRG)
// SCI interpreter version 1.000.181
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
index d49b51dde0b..073447e5aa8 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -770,7 +770,8 @@ void Kernel::loadKernelNames(GameFeatures *features) {
// In the Windows version of KQ6 CD, the empty kSetSynonyms
// function has been replaced with kPortrait. In KQ6 Mac,
// kPlayBack has been replaced by kShowMovie.
- if ((g_sci->getPlatform() == Common::kPlatformWindows) || (g_sci->forceHiresGraphics()))
+ if ((g_sci->getPlatform() == Common::kPlatformWindows) ||
+ (g_sci->getPlatform() == Common::kPlatformDOS && g_sci->forceHiresGraphics()))
_kernelNames[0x26] = "Portrait";
else if (g_sci->getPlatform() == Common::kPlatformMacintosh)
_kernelNames[0x84] = "ShowMovie";
diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp
index baee4239f30..5c961df39d3 100644
--- a/engines/sci/engine/kmisc.cpp
+++ b/engines/sci/engine/kmisc.cpp
@@ -761,8 +761,6 @@ reg_t kPlatform(EngineState *s, int argc, reg_t *argv) {
kPlatformWin311OrHigher = 7
};
- bool isWindows = g_sci->getPlatform() == Common::kPlatformWindows;
-
if (argc == 0) {
// This is called in KQ5CD with no parameters, where it seems to do some
// graphics driver check. This kernel function didn't have subfunctions
@@ -772,10 +770,9 @@ reg_t kPlatform(EngineState *s, int argc, reg_t *argv) {
return NULL_REG;
}
- if (g_sci->forceHiresGraphics()) {
- // force Windows platform, so that hires-graphics are enabled
- isWindows = true;
- }
+ // treat DOS with hires graphics as Windows so that hires graphics are enabled
+ bool isWindows = (g_sci->getPlatform() == Common::kPlatformWindows) ||
+ (g_sci->getPlatform() == Common::kPlatformDOS && g_sci->forceHiresGraphics());
uint16 operation = (argc == 0) ? 0 : argv[0].toUint16();
diff --git a/engines/sci/graphics/macfont.h b/engines/sci/graphics/macfont.h
index 3f9079da22f..41d339a3dc5 100644
--- a/engines/sci/graphics/macfont.h
+++ b/engines/sci/graphics/macfont.h
@@ -66,9 +66,10 @@ namespace Sci {
* values from Sierra's interpreter.
*
* GfxMacFontManager only exposes the small and large fonts. When Mac fonts are
- * present, the game is upscaled to 200% and the large font is used for drawing.
- * The small font is used for text calculations that determine the size of
- * the text area, regardless of which font size is drawn on it.
+ * present and high resolution graphics are enabled, the game is upscaled to
+ * 200% and the large font is used. If high resolution graphics are disabled
+ * then the small font is used with no upscaling. Either way, the small font is
+ * always used for the calculations that determine the size of the text area.
*
* TODO: Add KQ5 support. It did things differently and it only had two window
* sizes. The mapping table changed and it appears to have its own sizing logic.
diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp
index efc140df333..1c357a7d605 100644
--- a/engines/sci/graphics/screen.cpp
+++ b/engines/sci/graphics/screen.cpp
@@ -55,9 +55,11 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) {
// King's Quest 6 has hires content in the Windows version which we also
// allow to be optionally enabled in the DOS version.
- if ((g_sci->getPlatform() == Common::kPlatformWindows) || (g_sci->forceHiresGraphics())) {
- if (g_sci->getGameId() == GID_KQ6)
+ if (g_sci->getGameId() == GID_KQ6) {
+ if ((g_sci->getPlatform() == Common::kPlatformWindows) ||
+ (g_sci->getPlatform() == Common::kPlatformDOS && g_sci->forceHiresGraphics())) {
_upscaledHires = GFX_SCREEN_UPSCALED_640x440;
+ }
}
// Korean versions of games use hi-res font on upscaled version of the game.
@@ -74,8 +76,8 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) {
_width = 480;
_height = 300; // regular visual, priority and control map are 480x300 (this is different than other upscaled SCI games)
} else {
- // Macintosh SCI1/1.1 games use hi-res native fonts
- if (g_sci->hasMacFonts()) {
+ // Macintosh SCI1/1.1 games use hi-res native fonts if hi-res graphics are enabled
+ if (g_sci->hasMacFonts() && g_sci->forceHiresGraphics()) {
_upscaledHires = GFX_SCREEN_UPSCALED_640x400;
}
}
@@ -640,9 +642,10 @@ void GfxScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte
}
}
-// We put hi-res native Mac fonts onto an upscaled background.
-// The incoming coordinates are already hi-res.
-void GfxScreen::putHiresChar(const Graphics::Font *commonFont, int16 x, int16 y, uint16 chr, byte color) {
+// We put native Mac fonts onto an upscaled background if they are hires,
+// otherwise lores Mac fonts are used with no upscaling. The caller handles
+// all of this so there are no scaling adjustments to make here.
+void GfxScreen::putMacChar(const Graphics::Font *commonFont, int16 x, int16 y, uint16 chr, byte color) {
commonFont->drawChar(&_displayScreenSurface, chr, x, y, color);
}
diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h
index d99941e7057..793d4cb86b4 100644
--- a/engines/sci/graphics/screen.h
+++ b/engines/sci/graphics/screen.h
@@ -118,7 +118,7 @@ public:
}
void enableUndithering(bool flag);
- void putHiresChar(const Graphics::Font *commonFont, int16 x, int16 y, uint16 chr, byte color);
+ void putMacChar(const Graphics::Font *commonFont, int16 x, int16 y, uint16 chr, byte color);
void putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, uint16 chr, byte color);
void putHangulChar(Graphics::FontKorean *commonFont, int16 x, int16 y, uint16 chr, byte color);
diff --git a/engines/sci/graphics/text16.cpp b/engines/sci/graphics/text16.cpp
index 91699fa4efe..345bfd473f6 100644
--- a/engines/sci/graphics/text16.cpp
+++ b/engines/sci/graphics/text16.cpp
@@ -906,7 +906,8 @@ void GfxText16::macTextSize(const Common::String &text, GuiResourceId sciFontId,
// Leading can be zero for fonts that have spacing embedded in their glyphs.
*textHeight = lineCount * (font->getFontHeight() + font->getFontLeading());
- if (_macFontManager->usesSystemFonts()) {
+ if (_macFontManager->usesSystemFonts() &&
+ g_sci->_gfxScreen->getUpscaledHires() == GFX_SCREEN_UPSCALED_640x400) {
// QFG1VGA and LSL6 make this adjustment when the large font is used.
*textHeight -= (lineCount + 1);
}
@@ -922,22 +923,29 @@ void GfxText16::macDraw(const Common::String &text, Common::Rect rect, TextAlign
sciFontId = origSciFontId;
}
- // Always use the large font
- const Graphics::Font *font = _macFontManager->getLargeFont(sciFontId);
+ // Use the large font in hires mode, otherwise use the small font
+ const Graphics::Font *font;
+ uint16 scale;
+ if (g_sci->_gfxScreen->getUpscaledHires() == GFX_SCREEN_UPSCALED_640x400) {
+ font = _macFontManager->getLargeFont(sciFontId);
+ scale = 2;
+ } else {
+ font = _macFontManager->getSmallFont(sciFontId);
+ scale = 1;
+ }
if (color == -1) {
color = g_sci->_gfxPorts->_curPort->penClr;
}
- // We are drawing in high resolution
- rect.left *= 2;
- rect.top *= 2;
- rect.right *= 2;
- rect.bottom *= 2;
+ rect.left *= scale;
+ rect.top *= scale;
+ rect.right *= scale;
+ rect.bottom *= scale;
// Draw each line of text
int16 maxWidth = rect.width();
- int16 y = (g_sci->_gfxPorts->_curPort->top * 2) + rect.top;
+ int16 y = (g_sci->_gfxPorts->_curPort->top * scale) + rect.top;
for (uint i = 0; i < text.size(); ++i) {
int16 lineWidth;
int16 lineCharCount = macGetLongest(text, i, font, maxWidth, &lineWidth);
@@ -953,10 +961,10 @@ void GfxText16::macDraw(const Common::String &text, Common::Rect rect, TextAlign
}
// Draw each character in the line
- int16 x = (g_sci->_gfxPorts->_curPort->left * 2) + rect.left + offset;
+ int16 x = (g_sci->_gfxPorts->_curPort->left * scale) + rect.left + offset;
for (int16 j = 0; j < lineCharCount; ++j) {
char ch = text[i + j];
- g_sci->_gfxScreen->putHiresChar(font, x, y, ch, color);
+ g_sci->_gfxScreen->putMacChar(font, x, y, ch, color);
x += font->getCharWidth(ch);
}
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index 16b1455ddf0..9dd4167b0d6 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -289,12 +289,19 @@ Common::Error SciEngine::run() {
_scriptPatcher = new ScriptPatcher();
SegManager *segMan = new SegManager(_resMan, _scriptPatcher);
+ // Load the Mac executable and fonts if available
+ if (getSciVersion() < SCI_VERSION_2 && getPlatform() == Common::kPlatformMacintosh) {
+ loadMacExecutable();
+ loadMacFonts();
+ }
+
// Read user option for forcing hires graphics
// Only show/selectable for:
// - King's Quest 6 CD
// - King's Quest 6 CD demo
// - Gabriel Knight 1 CD
// - Police Quest 4 CD
+ // - SCI1/1.1 Mac games with hires fonts
//
// Gabriel Knight 1 on Mac is hi-res only, so it should NOT get this option.
// Confirmed by [md5] and originally by clone2727.
@@ -304,16 +311,12 @@ Common::Error SciEngine::run() {
// We need to do this, because the option's default is "true", but we don't want "true"
// for any game that does not have this option.
_forceHiresGraphics = ConfMan.getBool("enable_high_resolution_graphics");
+ } else if (hasMacFonts()) {
+ // Default to using hires Mac fonts if GUI option isn't present, as it was added later.
+ _forceHiresGraphics = true;
}
if (getSciVersion() < SCI_VERSION_2) {
- // Load the Mac executable and fonts if available.
- // If fonts are found then GfxScreen will enable upscaling.
- if (getPlatform() == Common::kPlatformMacintosh) {
- loadMacExecutable();
- loadMacFonts();
- }
-
// Initialize the game screen
_gfxScreen = new GfxScreen(_resMan);
_gfxScreen->enableUndithering(ConfMan.getBool("disable_dithering"));
More information about the Scummvm-git-logs
mailing list