diff options
Diffstat (limited to 'engines/sci/graphics')
-rw-r--r-- | engines/sci/graphics/controls16.cpp (renamed from engines/sci/graphics/controls.cpp) | 30 | ||||
-rw-r--r-- | engines/sci/graphics/controls16.h (renamed from engines/sci/graphics/controls.h) | 10 | ||||
-rw-r--r-- | engines/sci/graphics/controls32.cpp | 204 | ||||
-rw-r--r-- | engines/sci/graphics/controls32.h | 51 | ||||
-rw-r--r-- | engines/sci/graphics/coordadjuster.cpp | 16 | ||||
-rw-r--r-- | engines/sci/graphics/coordadjuster.h | 4 | ||||
-rw-r--r-- | engines/sci/graphics/cursor.cpp | 53 | ||||
-rw-r--r-- | engines/sci/graphics/cursor.h | 15 | ||||
-rw-r--r-- | engines/sci/graphics/frameout.cpp | 401 | ||||
-rw-r--r-- | engines/sci/graphics/frameout.h | 13 | ||||
-rw-r--r-- | engines/sci/graphics/palette.cpp | 9 | ||||
-rw-r--r-- | engines/sci/graphics/screen.cpp | 8 | ||||
-rw-r--r-- | engines/sci/graphics/text16.cpp | 2 | ||||
-rw-r--r-- | engines/sci/graphics/text32.cpp | 130 | ||||
-rw-r--r-- | engines/sci/graphics/text32.h | 8 | ||||
-rw-r--r-- | engines/sci/graphics/transitions.cpp | 14 | ||||
-rw-r--r-- | engines/sci/graphics/view.cpp | 5 |
17 files changed, 705 insertions, 268 deletions
diff --git a/engines/sci/graphics/controls.cpp b/engines/sci/graphics/controls16.cpp index a0750c7d3e..ab54e468d1 100644 --- a/engines/sci/graphics/controls.cpp +++ b/engines/sci/graphics/controls16.cpp @@ -36,26 +36,26 @@ #include "sci/graphics/font.h" #include "sci/graphics/screen.h" #include "sci/graphics/text16.h" -#include "sci/graphics/controls.h" +#include "sci/graphics/controls16.h" namespace Sci { -GfxControls::GfxControls(SegManager *segMan, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen) +GfxControls16::GfxControls16(SegManager *segMan, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen) : _segMan(segMan), _ports(ports), _paint16(paint16), _text16(text16), _screen(screen) { init(); } -GfxControls::~GfxControls() { +GfxControls16::~GfxControls16() { } -void GfxControls::init() { +void GfxControls16::init() { _texteditCursorVisible = false; } const char controlListUpArrow[2] = { 0x18, 0 }; const char controlListDownArrow[2] = { 0x19, 0 }; -void GfxControls::drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool isAlias) { +void GfxControls16::drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool isAlias) { Common::Rect workerRect = rect; GuiResourceId oldFontId = _text16->GetFontId(); int16 oldPenColor = _ports->_curPort->penClr; @@ -112,7 +112,7 @@ void GfxControls::drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, _text16->SetFont(oldFontId); } -void GfxControls::texteditCursorDraw(Common::Rect rect, const char *text, uint16 curPos) { +void GfxControls16::texteditCursorDraw(Common::Rect rect, const char *text, uint16 curPos) { int16 textWidth, i; if (!_texteditCursorVisible) { textWidth = 0; @@ -130,7 +130,7 @@ void GfxControls::texteditCursorDraw(Common::Rect rect, const char *text, uint16 } } -void GfxControls::texteditCursorErase() { +void GfxControls16::texteditCursorErase() { if (_texteditCursorVisible) { _paint16->invertRect(_texteditCursorRect); _paint16->bitsShow(_texteditCursorRect); @@ -139,11 +139,11 @@ void GfxControls::texteditCursorErase() { texteditSetBlinkTime(); } -void GfxControls::texteditSetBlinkTime() { +void GfxControls16::texteditSetBlinkTime() { _texteditBlinkTime = g_system->getMillis() + (30 * 1000 / 60); } -void GfxControls::kernelTexteditChange(reg_t controlObject, reg_t eventObject) { +void GfxControls16::kernelTexteditChange(reg_t controlObject, reg_t eventObject) { uint16 cursorPos = readSelectorValue(_segMan, controlObject, SELECTOR(cursor)); uint16 maxChars = readSelectorValue(_segMan, controlObject, SELECTOR(max)); reg_t textReference = readSelector(_segMan, controlObject, SELECTOR(text)); @@ -277,13 +277,13 @@ void GfxControls::kernelTexteditChange(reg_t controlObject, reg_t eventObject) { writeSelectorValue(_segMan, controlObject, SELECTOR(cursor), cursorPos); } -int GfxControls::getPicNotValid() { +int GfxControls16::getPicNotValid() { if (getSciVersion() >= SCI_VERSION_1_1) return _screen->_picNotValidSci11; return _screen->_picNotValid; } -void GfxControls::kernelDrawButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool hilite) { +void GfxControls16::kernelDrawButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool hilite) { int16 sci0EarlyPen = 0, sci0EarlyBack = 0; if (!hilite) { if (getSciVersion() == SCI_VERSION_0_EARLY) { @@ -321,7 +321,7 @@ void GfxControls::kernelDrawButton(Common::Rect rect, reg_t obj, const char *tex } } -void GfxControls::kernelDrawText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, TextAlignment alignment, int16 style, bool hilite) { +void GfxControls16::kernelDrawText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, TextAlignment alignment, int16 style, bool hilite) { if (!hilite) { rect.grow(1); _paint16->eraseRect(rect); @@ -338,7 +338,7 @@ void GfxControls::kernelDrawText(Common::Rect rect, reg_t obj, const char *text, } } -void GfxControls::kernelDrawTextEdit(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, int16 cursorPos, int16 maxChars, bool hilite) { +void GfxControls16::kernelDrawTextEdit(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, int16 cursorPos, int16 maxChars, bool hilite) { Common::Rect textRect = rect; uint16 oldFontId = _text16->GetFontId(); @@ -359,7 +359,7 @@ void GfxControls::kernelDrawTextEdit(Common::Rect rect, reg_t obj, const char *t _paint16->bitsShow(rect); } -void GfxControls::kernelDrawIcon(Common::Rect rect, reg_t obj, GuiResourceId viewId, int16 loopNo, int16 celNo, int16 priority, int16 style, bool hilite) { +void GfxControls16::kernelDrawIcon(Common::Rect rect, reg_t obj, GuiResourceId viewId, int16 loopNo, int16 celNo, int16 priority, int16 style, bool hilite) { if (!hilite) { _paint16->drawCelAndShow(viewId, loopNo, celNo, rect.left, rect.top, priority, 0); if (style & 0x20) { @@ -373,7 +373,7 @@ void GfxControls::kernelDrawIcon(Common::Rect rect, reg_t obj, GuiResourceId vie } } -void GfxControls::kernelDrawList(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 style, int16 upperPos, int16 cursorPos, bool isAlias, bool hilite) { +void GfxControls16::kernelDrawList(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 style, int16 upperPos, int16 cursorPos, bool isAlias, bool hilite) { if (!hilite) { drawListControl(rect, obj, maxChars, count, entries, fontId, upperPos, cursorPos, isAlias); rect.grow(1); diff --git a/engines/sci/graphics/controls.h b/engines/sci/graphics/controls16.h index 17e7c39318..90bd7beacb 100644 --- a/engines/sci/graphics/controls.h +++ b/engines/sci/graphics/controls16.h @@ -20,8 +20,8 @@ * */ -#ifndef SCI_GRAPHICS_CONTROLS_H -#define SCI_GRAPHICS_CONTROLS_H +#ifndef SCI_GRAPHICS_CONTROLS16_H +#define SCI_GRAPHICS_CONTROLS16_H namespace Sci { @@ -50,10 +50,10 @@ class GfxScreen; /** * Controls class, handles drawing of controls in SCI16 (SCI0-SCI1.1) games */ -class GfxControls { +class GfxControls16 { public: - GfxControls(SegManager *segMan, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen); - ~GfxControls(); + GfxControls16(SegManager *segMan, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen); + ~GfxControls16(); void kernelDrawButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool hilite); void kernelDrawText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 alignment, int16 style, bool hilite); diff --git a/engines/sci/graphics/controls32.cpp b/engines/sci/graphics/controls32.cpp new file mode 100644 index 0000000000..ad1d9e8623 --- /dev/null +++ b/engines/sci/graphics/controls32.cpp @@ -0,0 +1,204 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/system.h" + +#include "sci/sci.h" +#include "sci/event.h" +#include "sci/engine/kernel.h" +#include "sci/engine/seg_manager.h" +#include "sci/graphics/cache.h" +#include "sci/graphics/compare.h" +#include "sci/graphics/controls32.h" +#include "sci/graphics/font.h" +#include "sci/graphics/screen.h" +#include "sci/graphics/text32.h" + +namespace Sci { + +GfxControls32::GfxControls32(SegManager *segMan, GfxCache *cache, GfxScreen *screen, GfxText32 *text) + : _segMan(segMan), _cache(cache), _screen(screen), _text(text) { +} + +GfxControls32::~GfxControls32() { +} + +void GfxControls32::kernelTexteditChange(reg_t controlObject) { + SciEvent curEvent; + uint16 maxChars = 40; //readSelectorValue(_segMan, controlObject, SELECTOR(max)); // TODO + reg_t textReference = readSelector(_segMan, controlObject, SELECTOR(text)); + GfxFont *font = _cache->getFont(readSelectorValue(_segMan, controlObject, SELECTOR(font))); + Common::String text; + uint16 textSize; + bool textChanged = false; + bool textAddChar = false; + Common::Rect rect; + + if (textReference.isNull()) + error("kEditControl called on object that doesnt have a text reference"); + text = _segMan->getString(textReference); + + // TODO: Finish this + warning("kEditText ('%s')", text.c_str()); + return; + + uint16 cursorPos = 0; + //uint16 oldCursorPos = cursorPos; + bool captureEvents = true; + EventManager* eventMan = g_sci->getEventManager(); + + while (captureEvents) { + curEvent = g_sci->getEventManager()->getSciEvent(SCI_EVENT_KEYBOARD | SCI_EVENT_PEEK); + + if (curEvent.type == SCI_EVENT_NONE) { + eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event + } else { + textSize = text.size(); + + switch (curEvent.type) { + case SCI_EVENT_MOUSE_PRESS: + // TODO: Implement mouse support for cursor change + break; + case SCI_EVENT_KEYBOARD: + switch (curEvent.data) { + case SCI_KEY_BACKSPACE: + if (cursorPos > 0) { + cursorPos--; text.deleteChar(cursorPos); + textChanged = true; + } + eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event + break; + case SCI_KEY_DELETE: + if (cursorPos < textSize) { + text.deleteChar(cursorPos); + textChanged = true; + } + eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event + break; + case SCI_KEY_HOME: // HOME + cursorPos = 0; textChanged = true; + eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event + break; + case SCI_KEY_END: // END + cursorPos = textSize; textChanged = true; + eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event + break; + case SCI_KEY_LEFT: // LEFT + if (cursorPos > 0) { + cursorPos--; textChanged = true; + } + eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event + break; + case SCI_KEY_RIGHT: // RIGHT + if (cursorPos + 1 <= textSize) { + cursorPos++; textChanged = true; + } + eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event + break; + case 3: // returned in SCI1 late and newer when Control - C is pressed + if (curEvent.modifiers & SCI_KEYMOD_CTRL) { + // Control-C erases the whole line + cursorPos = 0; text.clear(); + textChanged = true; + } + eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event + break; + case SCI_KEY_UP: + case SCI_KEY_DOWN: + case SCI_KEY_ENTER: + case SCI_KEY_ESC: + case SCI_KEY_TAB: + case SCI_KEY_SHIFT_TAB: + captureEvents = false; + break; + default: + if ((curEvent.modifiers & SCI_KEYMOD_CTRL) && curEvent.data == 99) { + // Control-C in earlier SCI games (SCI0 - SCI1 middle) + // Control-C erases the whole line + cursorPos = 0; text.clear(); + textChanged = true; + } else if (curEvent.data > 31 && curEvent.data < 256 && textSize < maxChars) { + // insert pressed character + textAddChar = true; + textChanged = true; + } + eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event + break; + } + break; + } + } + + if (textChanged) { + rect = g_sci->_gfxCompare->getNSRect(controlObject); + + if (textAddChar) { + const char *textPtr = text.c_str(); + + // We check if we are really able to add the new char + uint16 textWidth = 0; + while (*textPtr) + textWidth += font->getCharWidth((byte)*textPtr++); + textWidth += font->getCharWidth(curEvent.data); + + // Does it fit? + if (textWidth >= rect.width()) { + return; + } + + text.insertChar(curEvent.data, cursorPos++); + + // Note: the following checkAltInput call might make the text + // too wide to fit, but SSCI fails to check that too. + } + + reg_t hunkId = readSelector(_segMan, controlObject, SELECTOR(bitmap)); + Common::Rect nsRect = g_sci->_gfxCompare->getNSRect(controlObject); + //texteditCursorErase(); // TODO: Cursor + + // Write back string + _segMan->strcpy(textReference, text.c_str()); + // Modify the buffer and show it + _text->createTextBitmap(controlObject, 0, 0, hunkId); + + _text->drawTextBitmap(0, 0, nsRect, controlObject); + //texteditCursorDraw(rect, text.c_str(), cursorPos); // TODO: Cursor + g_system->updateScreen(); + } else { + // TODO: Cursor + /* + if (g_system->getMillis() >= _texteditBlinkTime) { + _paint16->invertRect(_texteditCursorRect); + _paint16->bitsShow(_texteditCursorRect); + _texteditCursorVisible = !_texteditCursorVisible; + texteditSetBlinkTime(); + } + */ + } + + textAddChar = false; + textChanged = false; + g_sci->sleep(10); + } // while +} + +} // End of namespace Sci diff --git a/engines/sci/graphics/controls32.h b/engines/sci/graphics/controls32.h new file mode 100644 index 0000000000..68dca59462 --- /dev/null +++ b/engines/sci/graphics/controls32.h @@ -0,0 +1,51 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SCI_GRAPHICS_CONTROLS32_H +#define SCI_GRAPHICS_CONTROLS32_H + +namespace Sci { + +class GfxCache; +class GfxScreen; +class GfxText32; + +/** + * Controls class, handles drawing of controls in SCI32 (SCI2, SCI2.1, SCI3) games + */ +class GfxControls32 { +public: + GfxControls32(SegManager *segMan, GfxCache *cache, GfxScreen *screen, GfxText32 *text); + ~GfxControls32(); + + void kernelTexteditChange(reg_t controlObject); + +private: + SegManager *_segMan; + GfxCache *_cache; + GfxScreen *_screen; + GfxText32 *_text; +}; + +} // End of namespace Sci + +#endif diff --git a/engines/sci/graphics/coordadjuster.cpp b/engines/sci/graphics/coordadjuster.cpp index 2952d4da7b..1446888cf4 100644 --- a/engines/sci/graphics/coordadjuster.cpp +++ b/engines/sci/graphics/coordadjuster.cpp @@ -86,8 +86,8 @@ Common::Rect GfxCoordAdjuster16::pictureGetDisplayArea() { #ifdef ENABLE_SCI32 GfxCoordAdjuster32::GfxCoordAdjuster32(SegManager *segMan) : _segMan(segMan) { - scriptsRunningWidth = 0; - scriptsRunningHeight = 0; + _scriptsRunningWidth = 0; + _scriptsRunningHeight = 0; } GfxCoordAdjuster32::~GfxCoordAdjuster32() { @@ -109,18 +109,18 @@ void GfxCoordAdjuster32::kernelLocalToGlobal(int16 &x, int16 &y, reg_t planeObje } void GfxCoordAdjuster32::setScriptsResolution(uint16 width, uint16 height) { - scriptsRunningWidth = width; - scriptsRunningHeight = height; + _scriptsRunningWidth = width; + _scriptsRunningHeight = height; } void GfxCoordAdjuster32::fromDisplayToScript(int16 &y, int16 &x) { - y = ((y * scriptsRunningHeight) / g_sci->_gfxScreen->getHeight()); - x = ((x * scriptsRunningWidth) / g_sci->_gfxScreen->getWidth()); + y = ((y * _scriptsRunningHeight) / g_sci->_gfxScreen->getHeight()); + x = ((x * _scriptsRunningWidth) / g_sci->_gfxScreen->getWidth()); } void GfxCoordAdjuster32::fromScriptToDisplay(int16 &y, int16 &x) { - y = ((y * g_sci->_gfxScreen->getHeight()) / scriptsRunningHeight); - x = ((x * g_sci->_gfxScreen->getWidth()) / scriptsRunningWidth); + y = ((y * g_sci->_gfxScreen->getHeight()) / _scriptsRunningHeight); + x = ((x * g_sci->_gfxScreen->getWidth()) / _scriptsRunningWidth); } void GfxCoordAdjuster32::pictureSetDisplayArea(Common::Rect displayArea) { diff --git a/engines/sci/graphics/coordadjuster.h b/engines/sci/graphics/coordadjuster.h index 23cf79d209..63f608be6b 100644 --- a/engines/sci/graphics/coordadjuster.h +++ b/engines/sci/graphics/coordadjuster.h @@ -96,8 +96,8 @@ private: Common::Rect _pictureDisplayArea; - uint16 scriptsRunningWidth; - uint16 scriptsRunningHeight; + uint16 _scriptsRunningWidth; + uint16 _scriptsRunningHeight; }; #endif diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 50da48aaf3..52a5961070 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -59,10 +59,16 @@ GfxCursor::GfxCursor(ResourceManager *resMan, GfxPalette *palette, GfxScreen *sc _zoomColor = 0; _zoomMultiplier = 0; _cursorSurface = 0; + if (g_sci && g_sci->getGameId() == GID_KQ6 && g_sci->getPlatform() == Common::kPlatformWindows) _useOriginalKQ6WinCursors = ConfMan.getBool("windows_cursors"); else _useOriginalKQ6WinCursors = false; + + if (g_sci && g_sci->getGameId() == GID_SQ4 && getSciVersion() == SCI_VERSION_1_1) + _useSilverSQ4CDCursors = ConfMan.getBool("silver_cursors"); + else + _useSilverSQ4CDCursors = false; } GfxCursor::~GfxCursor() { @@ -125,18 +131,28 @@ void GfxCursor::kernelSetShape(GuiResourceId resourceId) { error("cursor resource %d has invalid size", resourceId); resourceData = resource->data; - // hotspot is specified for SCI1 cursors - hotspot.x = READ_LE_UINT16(resourceData); - hotspot.y = READ_LE_UINT16(resourceData + 2); - // bit 0 of resourceData[3] is set on <SCI1 games, which means center hotspot - if ((hotspot.x == 0) && (hotspot.y == 256)) - hotspot.x = hotspot.y = SCI_CURSOR_SCI0_HEIGHTWIDTH / 2; + + if (getSciVersion() <= SCI_VERSION_0_LATE) { + // SCI0 cursors contain hotspot flags, not actual hotspot coordinates. + // If bit 0 of resourceData[3] is set, the hotspot should be centered, + // otherwise it's in the top left of the mouse cursor. + hotspot.x = hotspot.y = resourceData[3] ? SCI_CURSOR_SCI0_HEIGHTWIDTH / 2 : 0; + } else { + // Cursors in newer SCI versions contain actual hotspot coordinates. + hotspot.x = READ_LE_UINT16(resourceData); + hotspot.y = READ_LE_UINT16(resourceData + 2); + } // Now find out what colors we are supposed to use colorMapping[0] = 0; // Black is hardcoded colorMapping[1] = _screen->getColorWhite(); // White is also hardcoded colorMapping[2] = SCI_CURSOR_SCI0_TRANSPARENCYCOLOR; colorMapping[3] = _palette->matchColor(170, 170, 170); // Grey + // Special case for the magnifier cursor in LB1 (bug #3487092). + // No other SCI0 game has a cursor resource of 1, so this is handled + // specifically for LB1. + if (g_sci->getGameId() == GID_LAURABOW && resourceId == 1) + colorMapping[3] = _screen->getColorWhite(); // Seek to actual data resourceData += 4; @@ -165,6 +181,11 @@ void GfxCursor::kernelSetShape(GuiResourceId resourceId) { rawBitmap = upscaledBitmap; } + if (hotspot.x >= heightWidth || hotspot.y >= heightWidth) { + error("cursor %d's hotspot (%d, %d) is out of range of the cursor's dimensions (%dx%d)", + resourceId, hotspot.x, hotspot.y, heightWidth, heightWidth); + } + CursorMan.replaceCursor(rawBitmap, heightWidth, heightWidth, hotspot.x, hotspot.y, SCI_CURSOR_SCI0_TRANSPARENCYCOLOR); kernelShow(); @@ -191,6 +212,26 @@ void GfxCursor::kernelSetView(GuiResourceId viewNum, int loopNum, int celNum, Co return; } + // Use the alternate silver cursors in SQ4 CD, if requested + if (_useSilverSQ4CDCursors) { + switch(viewNum) { + case 850: + case 852: + case 854: + case 856: + celNum = 3; + break; + case 851: + case 853: + case 855: + case 999: + celNum = 2; + break; + default: + break; + } + } + if (!_cachedCursors.contains(viewNum)) _cachedCursors[viewNum] = new GfxView(_resMan, _screen, _palette, viewNum); diff --git a/engines/sci/graphics/cursor.h b/engines/sci/graphics/cursor.h index 25109b3920..ac928f50bb 100644 --- a/engines/sci/graphics/cursor.h +++ b/engines/sci/graphics/cursor.h @@ -113,13 +113,18 @@ private: bool _isVisible; - // KQ6 Windows has different black and white cursors. If this is - // true (set from the sci_originalkq6wincursors ini setting), then - // we use these, and don't scale them by 2x like the rest of the - // graphics, like SSCI did. These look very ugly, which is why - // they aren't enabled by default. + // KQ6 Windows has different black and white cursors. If this is true (set + // from the windows_cursors ini setting), then we use these and don't scale + // them by 2x like the rest of the graphics, like SSCI did. These look very + // ugly, which is why they aren't enabled by default. bool _useOriginalKQ6WinCursors; + // The CD version of SQ4 contains a complete set of silver mouse cursors. + // If this is true (set from the silver_cursors ini setting), then we use + // these instead and replace the game's gold cursors with their silver + // equivalents. + bool _useSilverSQ4CDCursors; + // Mac versions of games use a remap list to remap their cursors Common::Array<uint16> _macCursorRemap; }; diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index a41efd6a9f..b12413ab69 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -56,17 +56,18 @@ GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAd : _segMan(segMan), _resMan(resMan), _cache(cache), _screen(screen), _palette(palette), _paint32(paint32) { _coordAdjuster = (GfxCoordAdjuster32 *)coordAdjuster; - scriptsRunningWidth = 320; - scriptsRunningHeight = 200; + _scriptsRunningWidth = 320; + _scriptsRunningHeight = 200; } GfxFrameout::~GfxFrameout() { + clear(); } void GfxFrameout::clear() { - _screenItems.clear(); + deletePlaneItems(NULL_REG); _planes.clear(); - _planePictures.clear(); + deletePlanePictures(NULL_REG); } void GfxFrameout::kernelAddPlane(reg_t object) { @@ -80,11 +81,11 @@ void GfxFrameout::kernelAddPlane(reg_t object) { // The above can be 0 in SCI3 (e.g. Phantasmagoria 2) if (tmpRunningWidth > 0 && tmpRunningHeight > 0) { - scriptsRunningWidth = tmpRunningWidth; - scriptsRunningHeight = tmpRunningHeight; + _scriptsRunningWidth = tmpRunningWidth; + _scriptsRunningHeight = tmpRunningHeight; } - _coordAdjuster->setScriptsResolution(scriptsRunningWidth, scriptsRunningHeight); + _coordAdjuster->setScriptsResolution(_scriptsRunningWidth, _scriptsRunningHeight); } newPlane.object = object; @@ -101,7 +102,7 @@ void GfxFrameout::kernelAddPlane(reg_t object) { } void GfxFrameout::kernelUpdatePlane(reg_t object) { - for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); it++) { + for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) { if (it->object == object) { // Read some information it->priority = readSelectorValue(_segMan, object, SELECTOR(priority)); @@ -118,14 +119,14 @@ void GfxFrameout::kernelUpdatePlane(reg_t object) { } it->planeRect.top = readSelectorValue(_segMan, object, SELECTOR(top)); it->planeRect.left = readSelectorValue(_segMan, object, SELECTOR(left)); - it->planeRect.bottom = readSelectorValue(_segMan, object, SELECTOR(bottom)) + 1; - it->planeRect.right = readSelectorValue(_segMan, object, SELECTOR(right)) + 1; + it->planeRect.bottom = readSelectorValue(_segMan, object, SELECTOR(bottom)); + it->planeRect.right = readSelectorValue(_segMan, object, SELECTOR(right)); Common::Rect screenRect(_screen->getWidth(), _screen->getHeight()); - it->planeRect.top = (it->planeRect.top * screenRect.height()) / scriptsRunningHeight; - it->planeRect.left = (it->planeRect.left * screenRect.width()) / scriptsRunningWidth; - it->planeRect.bottom = (it->planeRect.bottom * screenRect.height()) / scriptsRunningHeight; - it->planeRect.right = (it->planeRect.right * screenRect.width()) / scriptsRunningWidth; + it->planeRect.top = (it->planeRect.top * screenRect.height()) / _scriptsRunningHeight; + it->planeRect.left = (it->planeRect.left * screenRect.width()) / _scriptsRunningWidth; + it->planeRect.bottom = (it->planeRect.bottom * screenRect.height()) / _scriptsRunningHeight; + it->planeRect.right = (it->planeRect.right * screenRect.width()) / _scriptsRunningWidth; // We get negative left in kq7 in scrolling rooms if (it->planeRect.left < 0) { @@ -178,22 +179,23 @@ void GfxFrameout::kernelUpdatePlane(reg_t object) { } void GfxFrameout::kernelDeletePlane(reg_t object) { + deletePlaneItems(object); deletePlanePictures(object); - for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); it++) { + + for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) { if (it->object == object) { _planes.erase(it); Common::Rect planeRect; planeRect.top = readSelectorValue(_segMan, object, SELECTOR(top)); planeRect.left = readSelectorValue(_segMan, object, SELECTOR(left)); - planeRect.bottom = readSelectorValue(_segMan, object, SELECTOR(bottom)) + 1; - planeRect.right = readSelectorValue(_segMan, object, SELECTOR(right)) + 1; + planeRect.bottom = readSelectorValue(_segMan, object, SELECTOR(bottom)); + planeRect.right = readSelectorValue(_segMan, object, SELECTOR(right)); Common::Rect screenRect(_screen->getWidth(), _screen->getHeight()); - planeRect.top = (planeRect.top * screenRect.height()) / scriptsRunningHeight; - planeRect.left = (planeRect.left * screenRect.width()) / scriptsRunningWidth; - planeRect.bottom = (planeRect.bottom * screenRect.height()) / scriptsRunningHeight; - planeRect.right = (planeRect.right * screenRect.width()) / scriptsRunningWidth; - planeRect.clip(screenRect); // we need to do this, at least in gk1 on cemetary we get bottom right -> 201, 321 + planeRect.top = (planeRect.top * screenRect.height()) / _scriptsRunningHeight; + planeRect.left = (planeRect.left * screenRect.width()) / _scriptsRunningWidth; + planeRect.bottom = (planeRect.bottom * screenRect.height()) / _scriptsRunningHeight; + planeRect.right = (planeRect.right * screenRect.width()) / _scriptsRunningWidth; // Blackout removed plane rect _paint32->fillRect(planeRect, 0); return; @@ -213,12 +215,15 @@ void GfxFrameout::addPlanePicture(reg_t object, GuiResourceId pictureId, uint16 } void GfxFrameout::deletePlanePictures(reg_t object) { - for (PlanePictureList::iterator it = _planePictures.begin(); it != _planePictures.end(); it++) { - if (it->object == object) { + PlanePictureList::iterator it = _planePictures.begin(); + + while (it != _planePictures.end()) { + if (it->object == object || object.isNull()) { + delete it->pictureCels; delete it->picture; - _planePictures.erase(it); - deletePlanePictures(object); - return; + it = _planePictures.erase(it); + } else { + ++it; } } } @@ -271,6 +276,29 @@ void GfxFrameout::kernelDeleteScreenItem(reg_t object) { } _screenItems.remove(itemEntry); + delete itemEntry; +} + +void GfxFrameout::deletePlaneItems(reg_t planeObject) { + FrameoutList::iterator listIterator = _screenItems.begin(); + + while (listIterator != _screenItems.end()) { + bool objectMatches = false; + if (!planeObject.isNull()) { + reg_t itemPlane = readSelector(_segMan, (*listIterator)->object, SELECTOR(plane)); + objectMatches = (planeObject == itemPlane); + } else { + objectMatches = true; + } + + if (objectMatches) { + FrameoutEntry *itemEntry = *listIterator; + listIterator = _screenItems.erase(listIterator); + delete itemEntry; + } else { + ++listIterator; + } + } } FrameoutEntry *GfxFrameout::findScreenItem(reg_t object) { @@ -329,37 +357,149 @@ void GfxFrameout::sortPlanes() { Common::sort(_planes.begin(), _planes.end(), planeSortHelper); } -void GfxFrameout::kernelFrameout() { - if (g_sci->_robotDecoder->isVideoLoaded()) { - bool skipVideo = false; - RobotDecoder *videoDecoder = g_sci->_robotDecoder; - uint16 x = videoDecoder->getPos().x; - uint16 y = videoDecoder->getPos().y; +int16 GfxFrameout::upscaleHorizontalCoordinate(int16 coordinate) { + return ((coordinate * _screen->getWidth()) / _scriptsRunningWidth); +} - if (videoDecoder->hasDirtyPalette()) - videoDecoder->setSystemPalette(); +int16 GfxFrameout::upscaleVerticalCoordinate(int16 coordinate) { + return ((coordinate * _screen->getHeight()) / _scriptsRunningHeight); +} - while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) { - if (videoDecoder->needsUpdate()) { - const Graphics::Surface *frame = videoDecoder->decodeNextFrame(); - if (frame) { - g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h); +Common::Rect GfxFrameout::upscaleRect(Common::Rect &rect) { + rect.top = (rect.top * _scriptsRunningHeight) / _screen->getHeight(); + rect.left = (rect.left * _scriptsRunningWidth) / _screen->getWidth(); + rect.bottom = (rect.bottom * _scriptsRunningHeight) / _screen->getHeight(); + rect.right = (rect.right * _scriptsRunningWidth) / _screen->getWidth(); - if (videoDecoder->hasDirtyPalette()) - videoDecoder->setSystemPalette(); + return rect; +} - g_system->updateScreen(); - } +void GfxFrameout::showVideo() { + bool skipVideo = false; + RobotDecoder *videoDecoder = g_sci->_robotDecoder; + uint16 x = videoDecoder->getPos().x; + uint16 y = videoDecoder->getPos().y; + + if (videoDecoder->hasDirtyPalette()) + videoDecoder->setSystemPalette(); + + while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) { + if (videoDecoder->needsUpdate()) { + const Graphics::Surface *frame = videoDecoder->decodeNextFrame(); + if (frame) { + g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h); + + if (videoDecoder->hasDirtyPalette()) + videoDecoder->setSystemPalette(); + + g_system->updateScreen(); } + } - Common::Event event; - while (g_system->getEventManager()->pollEvent(event)) { - if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP) - skipVideo = true; + Common::Event event; + while (g_system->getEventManager()->pollEvent(event)) { + if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP) + skipVideo = true; + } + + g_system->delayMillis(10); + } +} + +void GfxFrameout::createPlaneItemList(reg_t planeObject, FrameoutList &itemList) { + // Copy screen items of the current frame to the list of items to be drawn + for (FrameoutList::iterator listIterator = _screenItems.begin(); listIterator != _screenItems.end(); listIterator++) { + reg_t itemPlane = readSelector(_segMan, (*listIterator)->object, SELECTOR(plane)); + if (planeObject == itemPlane) { + kernelUpdateScreenItem((*listIterator)->object); // TODO: Why is this necessary? + itemList.push_back(*listIterator); + } + } + + for (PlanePictureList::iterator pictureIt = _planePictures.begin(); pictureIt != _planePictures.end(); pictureIt++) { + if (pictureIt->object == planeObject) { + GfxPicture *planePicture = pictureIt->picture; + // Allocate memory for picture cels + pictureIt->pictureCels = new FrameoutEntry[planePicture->getSci32celCount()]; + + // Add following cels to the itemlist + FrameoutEntry *picEntry = pictureIt->pictureCels; + int planePictureCels = planePicture->getSci32celCount(); + for (int pictureCelNr = 0; pictureCelNr < planePictureCels; pictureCelNr++) { + picEntry->celNo = pictureCelNr; + picEntry->object = NULL_REG; + picEntry->picture = planePicture; + picEntry->y = planePicture->getSci32celY(pictureCelNr); + picEntry->x = planePicture->getSci32celX(pictureCelNr); + picEntry->picStartX = pictureIt->startX; + picEntry->picStartY = pictureIt->startY; + + picEntry->priority = planePicture->getSci32celPriority(pictureCelNr); + + itemList.push_back(picEntry); + picEntry++; } + } + } + + // Now sort our itemlist + Common::sort(itemList.begin(), itemList.end(), sortHelper); +} - g_system->delayMillis(10); +bool GfxFrameout::isPictureOutOfView(FrameoutEntry *itemEntry, Common::Rect planeRect, int16 planeOffsetX, int16 planeOffsetY) { + // Out of view horizontally (sanity checks) + int16 pictureCelStartX = itemEntry->picStartX + itemEntry->x; + int16 pictureCelEndX = pictureCelStartX + itemEntry->picture->getSci32celWidth(itemEntry->celNo); + int16 planeStartX = planeOffsetX; + int16 planeEndX = planeStartX + planeRect.width(); + if (pictureCelEndX < planeStartX) + return true; + if (pictureCelStartX > planeEndX) + return true; + + // Out of view vertically (sanity checks) + int16 pictureCelStartY = itemEntry->picStartY + itemEntry->y; + int16 pictureCelEndY = pictureCelStartY + itemEntry->picture->getSci32celHeight(itemEntry->celNo); + int16 planeStartY = planeOffsetY; + int16 planeEndY = planeStartY + planeRect.height(); + if (pictureCelEndY < planeStartY) + return true; + if (pictureCelStartY > planeEndY) + return true; + + return false; +} + +void GfxFrameout::drawPicture(FrameoutEntry *itemEntry, int16 planeOffsetX, int16 planeOffsetY, bool planePictureMirrored) { + int16 pictureOffsetX = planeOffsetX; + int16 pictureX = itemEntry->x; + if ((planeOffsetX) || (itemEntry->picStartX)) { + if (planeOffsetX <= itemEntry->picStartX) { + pictureX += itemEntry->picStartX - planeOffsetX; + pictureOffsetX = 0; + } else { + pictureOffsetX = planeOffsetX - itemEntry->picStartX; + } + } + + int16 pictureOffsetY = planeOffsetY; + int16 pictureY = itemEntry->y; + if ((planeOffsetY) || (itemEntry->picStartY)) { + if (planeOffsetY <= itemEntry->picStartY) { + pictureY += itemEntry->picStartY - planeOffsetY; + pictureOffsetY = 0; + } else { + pictureOffsetY = planeOffsetY - itemEntry->picStartY; } + } + + itemEntry->picture->drawSci32Vga(itemEntry->celNo, pictureX, itemEntry->y, pictureOffsetX, pictureOffsetY, planePictureMirrored); + // warning("picture cel %d %d", itemEntry->celNo, itemEntry->priority); +} + +void GfxFrameout::kernelFrameout() { + if (g_sci->_robotDecoder->isVideoLoaded()) { + showVideo(); return; } @@ -383,7 +523,8 @@ void GfxFrameout::kernelFrameout() { // There is a race condition lurking in SQ6, which causes the game to hang in the intro, when teleporting to Polysorbate LX. // Since I first wrote the patch, the race has stopped occurring for me though. // I'll leave this for investigation later, when someone can reproduce. - if (it->pictureId == 0xffff) + //if (it->pictureId == 0xffff) // FIXME: This is what SSCI does, and fixes the intro of LSL7, but breaks the dialogs in GK1 (adds black boxes) + if (it->planeBack) _paint32->fillRect(it->planeRect, it->planeBack); GuiResourceId planeMainPictureId = it->pictureId; @@ -393,43 +534,7 @@ void GfxFrameout::kernelFrameout() { FrameoutList itemList; - // Copy screen items of the current frame to the list of items to be drawn - for (FrameoutList::iterator listIterator = _screenItems.begin(); listIterator != _screenItems.end(); listIterator++) { - reg_t itemPlane = readSelector(_segMan, (*listIterator)->object, SELECTOR(plane)); - if (planeObject == itemPlane) { - kernelUpdateScreenItem((*listIterator)->object); // TODO: Why is this necessary? - itemList.push_back(*listIterator); - } - } - - for (PlanePictureList::iterator pictureIt = _planePictures.begin(); pictureIt != _planePictures.end(); pictureIt++) { - if (pictureIt->object == planeObject) { - GfxPicture *planePicture = pictureIt->picture; - // Allocate memory for picture cels - pictureIt->pictureCels = new FrameoutEntry[planePicture->getSci32celCount()]; - - // Add following cels to the itemlist - FrameoutEntry *picEntry = pictureIt->pictureCels; - int planePictureCels = planePicture->getSci32celCount(); - for (int pictureCelNr = 0; pictureCelNr < planePictureCels; pictureCelNr++) { - picEntry->celNo = pictureCelNr; - picEntry->object = NULL_REG; - picEntry->picture = planePicture; - picEntry->y = planePicture->getSci32celY(pictureCelNr); - picEntry->x = planePicture->getSci32celX(pictureCelNr); - picEntry->picStartX = pictureIt->startX; - picEntry->picStartY = pictureIt->startY; - - picEntry->priority = planePicture->getSci32celPriority(pictureCelNr); - - itemList.push_back(picEntry); - picEntry++; - } - } - } - - // Now sort our itemlist - Common::sort(itemList.begin(), itemList.end(), sortHelper); + createPlaneItemList(planeObject, itemList); // warning("Plane %s", _segMan->getObjectName(planeObject)); @@ -438,69 +543,24 @@ void GfxFrameout::kernelFrameout() { if (itemEntry->object.isNull()) { // Picture cel data - itemEntry->y = ((itemEntry->y * _screen->getHeight()) / scriptsRunningHeight); - itemEntry->x = ((itemEntry->x * _screen->getWidth()) / scriptsRunningWidth); - itemEntry->picStartX = ((itemEntry->picStartX * _screen->getWidth()) / scriptsRunningWidth); - itemEntry->picStartY = ((itemEntry->picStartY * _screen->getHeight()) / scriptsRunningHeight); - - // Out of view horizontally (sanity checks) - int16 pictureCelStartX = itemEntry->picStartX + itemEntry->x; - int16 pictureCelEndX = pictureCelStartX + itemEntry->picture->getSci32celWidth(itemEntry->celNo); - int16 planeStartX = it->planeOffsetX; - int16 planeEndX = planeStartX + it->planeRect.width(); - if (pictureCelEndX < planeStartX) - continue; - if (pictureCelStartX > planeEndX) - continue; - - // Out of view vertically (sanity checks) - int16 pictureCelStartY = itemEntry->picStartY + itemEntry->y; - int16 pictureCelEndY = pictureCelStartY + itemEntry->picture->getSci32celHeight(itemEntry->celNo); - int16 planeStartY = it->planeOffsetY; - int16 planeEndY = planeStartY + it->planeRect.height(); - if (pictureCelEndY < planeStartY) - continue; - if (pictureCelStartY > planeEndY) - continue; + itemEntry->x = upscaleHorizontalCoordinate(itemEntry->x); + itemEntry->y = upscaleVerticalCoordinate(itemEntry->y); + itemEntry->picStartX = upscaleHorizontalCoordinate(itemEntry->picStartX); + itemEntry->picStartY = upscaleVerticalCoordinate(itemEntry->picStartY); - int16 pictureOffsetX = it->planeOffsetX; - int16 pictureX = itemEntry->x; - if ((it->planeOffsetX) || (itemEntry->picStartX)) { - if (it->planeOffsetX <= itemEntry->picStartX) { - pictureX += itemEntry->picStartX - it->planeOffsetX; - pictureOffsetX = 0; - } else { - pictureOffsetX = it->planeOffsetX - itemEntry->picStartX; - } - } - - int16 pictureOffsetY = it->planeOffsetY; - int16 pictureY = itemEntry->y; - if ((it->planeOffsetY) || (itemEntry->picStartY)) { - if (it->planeOffsetY <= itemEntry->picStartY) { - pictureY += itemEntry->picStartY - it->planeOffsetY; - pictureOffsetY = 0; - } else { - pictureOffsetY = it->planeOffsetY - itemEntry->picStartY; - } - } - - itemEntry->picture->drawSci32Vga(itemEntry->celNo, pictureX, itemEntry->y, pictureOffsetX, pictureOffsetY, it->planePictureMirrored); -// warning("picture cel %d %d", itemEntry->celNo, itemEntry->priority); - - } else if (itemEntry->viewId != 0xFFFF) { - GfxView *view = _cache->getView(itemEntry->viewId); - -// warning("view %s %04x:%04x", _segMan->getObjectName(itemEntry->object), PRINT_REG(itemEntry->object)); - - if (view->isSci2Hires()) { + if (!isPictureOutOfView(itemEntry, it->planeRect, it->planeOffsetX, it->planeOffsetY)) + drawPicture(itemEntry, it->planeOffsetX, it->planeOffsetY, it->planePictureMirrored); + } else { + GfxView *view = (itemEntry->viewId != 0xFFFF) ? _cache->getView(itemEntry->viewId) : NULL; + + if (view && view->isSci2Hires()) { int16 dummyX = 0; view->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x); view->adjustToUpscaledCoordinates(itemEntry->z, dummyX); } else if (getSciVersion() == SCI_VERSION_2_1) { - itemEntry->y = (itemEntry->y * _screen->getHeight()) / scriptsRunningHeight; - itemEntry->x = (itemEntry->x * _screen->getWidth()) / scriptsRunningWidth; - itemEntry->z = (itemEntry->z * _screen->getHeight()) / scriptsRunningHeight; + itemEntry->x = upscaleHorizontalCoordinate(itemEntry->x); + itemEntry->y = upscaleVerticalCoordinate(itemEntry->y); + itemEntry->z = upscaleVerticalCoordinate(itemEntry->z); } // Adjust according to current scroll position @@ -511,33 +571,33 @@ void GfxFrameout::kernelFrameout() { if (useInsetRect) { itemEntry->celRect.top = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inTop)); itemEntry->celRect.left = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inLeft)); - itemEntry->celRect.bottom = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inBottom)) + 1; - itemEntry->celRect.right = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inRight)) + 1; - if (view->isSci2Hires()) { + itemEntry->celRect.bottom = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inBottom)); + itemEntry->celRect.right = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inRight)); + if (view && view->isSci2Hires()) { view->adjustToUpscaledCoordinates(itemEntry->celRect.top, itemEntry->celRect.left); view->adjustToUpscaledCoordinates(itemEntry->celRect.bottom, itemEntry->celRect.right); } itemEntry->celRect.translate(itemEntry->x, itemEntry->y); // TODO: maybe we should clip the cels rect with this, i'm not sure // the only currently known usage is game menu of gk1 - } else { - if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) - view->getCelRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->celRect); - else - view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX, itemEntry->scaleY, itemEntry->celRect); + } else if (view) { + if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) + view->getCelRect(itemEntry->loopNo, itemEntry->celNo, + itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->celRect); + else + view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo, + itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX, + itemEntry->scaleY, itemEntry->celRect); Common::Rect nsRect = itemEntry->celRect; // Translate back to actual coordinate within scrollable plane nsRect.translate(it->planeOffsetX, it->planeOffsetY); - if (view->isSci2Hires()) { + if (view && view->isSci2Hires()) { view->adjustBackUpscaledCoordinates(nsRect.top, nsRect.left); view->adjustBackUpscaledCoordinates(nsRect.bottom, nsRect.right); } else if (getSciVersion() == SCI_VERSION_2_1) { - nsRect.top = (nsRect.top * scriptsRunningHeight) / _screen->getHeight(); - nsRect.left = (nsRect.left * scriptsRunningWidth) / _screen->getWidth(); - nsRect.bottom = (nsRect.bottom * scriptsRunningHeight) / _screen->getHeight(); - nsRect.right = (nsRect.right * scriptsRunningWidth) / _screen->getWidth(); + nsRect = upscaleRect(nsRect); } if (g_sci->getGameId() == GID_PHANTASMAGORIA2) { @@ -552,7 +612,7 @@ void GfxFrameout::kernelFrameout() { int16 screenHeight = _screen->getHeight(); int16 screenWidth = _screen->getWidth(); - if (view->isSci2Hires()) { + if (view && view->isSci2Hires()) { screenHeight = _screen->getDisplayHeight(); screenWidth = _screen->getDisplayWidth(); } @@ -565,7 +625,8 @@ void GfxFrameout::kernelFrameout() { Common::Rect clipRect, translatedClipRect; clipRect = itemEntry->celRect; - if (view->isSci2Hires()) { + + if (view && view->isSci2Hires()) { clipRect.clip(it->upscaledPlaneClipRect); translatedClipRect = clipRect; translatedClipRect.translate(it->upscaledPlaneRect.left, it->upscaledPlaneRect.top); @@ -575,16 +636,20 @@ void GfxFrameout::kernelFrameout() { translatedClipRect.translate(it->planeRect.left, it->planeRect.top); } - if (!clipRect.isEmpty()) { - if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) - view->draw(itemEntry->celRect, clipRect, translatedClipRect, itemEntry->loopNo, itemEntry->celNo, 255, 0, view->isSci2Hires()); - else - view->drawScaled(itemEntry->celRect, clipRect, translatedClipRect, itemEntry->loopNo, itemEntry->celNo, 255, itemEntry->scaleX, itemEntry->scaleY); + if (view) { + if (!clipRect.isEmpty()) { + if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) + view->draw(itemEntry->celRect, clipRect, translatedClipRect, + itemEntry->loopNo, itemEntry->celNo, 255, 0, view->isSci2Hires()); + else + view->drawScaled(itemEntry->celRect, clipRect, translatedClipRect, + itemEntry->loopNo, itemEntry->celNo, 255, itemEntry->scaleX, itemEntry->scaleY); + } } - } else { - // Most likely a text entry + + // Draw text, if it exists if (lookupSelector(_segMan, itemEntry->object, SELECTOR(text), NULL, NULL) == kSelectorVariable) { - g_sci->_gfxText32->drawTextBitmap(itemEntry->object); + g_sci->_gfxText32->drawTextBitmap(itemEntry->x, itemEntry->y, it->planeRect, itemEntry->object); } } } diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index 160c343b05..8c3cc261d5 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -94,6 +94,7 @@ public: void kernelAddScreenItem(reg_t object); void kernelUpdateScreenItem(reg_t object); void kernelDeleteScreenItem(reg_t object); + void deletePlaneItems(reg_t planeObject); FrameoutEntry *findScreenItem(reg_t object); int16 kernelGetHighPlanePri(); void kernelAddPicAt(reg_t planeObj, GuiResourceId pictureId, int16 pictureX, int16 pictureY); @@ -104,6 +105,14 @@ public: void clear(); private: + void showVideo(); + void createPlaneItemList(reg_t planeObject, FrameoutList &itemList); + bool isPictureOutOfView(FrameoutEntry *itemEntry, Common::Rect planeRect, int16 planeOffsetX, int16 planeOffsetY); + void drawPicture(FrameoutEntry *itemEntry, int16 planeOffsetX, int16 planeOffsetY, bool planePictureMirrored); + int16 upscaleHorizontalCoordinate(int16 coordinate); + int16 upscaleVerticalCoordinate(int16 coordinate); + Common::Rect upscaleRect(Common::Rect &rect); + SegManager *_segMan; ResourceManager *_resMan; GfxCoordAdjuster32 *_coordAdjuster; @@ -118,8 +127,8 @@ private: void sortPlanes(); - uint16 scriptsRunningWidth; - uint16 scriptsRunningHeight; + uint16 _scriptsRunningWidth; + uint16 _scriptsRunningHeight; }; } // End of namespace Sci diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index b52af38675..47d1647c6c 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -709,6 +709,13 @@ bool GfxPalette::palVaryLoadTargetPalette(GuiResourceId resourceId) { } void GfxPalette::palVaryInstallTimer() { + // Remove any possible leftover palVary timer callbacks. + // This happens for example in QFG1VGA, when sleeping at Erana's place + // (bug #3439240) - the nighttime to daytime effect clashes with the + // scene transition effect, as we load scene images too quickly for + // the SCI scripts in that case (also refer to kernelPalVaryInit). + palVaryRemoveTimer(); + int16 ticks = _palVaryTicks > 0 ? _palVaryTicks : 1; // Call signal increase every [ticks] g_sci->getTimerManager()->installTimerProc(&palVaryCallback, 1000000 / 60 * ticks, this, "sciPalette"); @@ -966,7 +973,7 @@ void GfxPalette::loadMacIconBarPalette() { } bool GfxPalette::colorIsFromMacClut(byte index) { - return index != 0 && _macClut && (_macClut[index * 3] != 0 || _macClut[index * 3 + 1] != 0 || _macClut[index * 3 + 1] != 0); + return index != 0 && _macClut && (_macClut[index * 3] != 0 || _macClut[index * 3 + 1] != 0 || _macClut[index * 3 + 2] != 0); } #ifdef ENABLE_SCI32 diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 6469bc0cb3..4020518b72 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -438,7 +438,7 @@ void GfxScreen::bitsSaveScreen(Common::Rect rect, byte *screen, uint16 screenWid screen += (rect.top * screenWidth) + rect.left; for (y = rect.top; y < rect.bottom; y++) { - memcpy(memoryPtr, (void*)screen, width); memoryPtr += width; + memcpy(memoryPtr, (void *)screen, width); memoryPtr += width; screen += screenWidth; } } @@ -458,7 +458,7 @@ void GfxScreen::bitsSaveDisplayScreen(Common::Rect rect, byte *&memoryPtr) { } for (y = rect.top; y < rect.bottom; y++) { - memcpy(memoryPtr, (void*)screen, width); memoryPtr += width; + memcpy(memoryPtr, (void *)screen, width); memoryPtr += width; screen += _displayWidth; } } @@ -503,7 +503,7 @@ void GfxScreen::bitsRestoreScreen(Common::Rect rect, byte *&memoryPtr, byte *scr screen += (rect.top * screenWidth) + rect.left; for (y = rect.top; y < rect.bottom; y++) { - memcpy((void*) screen, memoryPtr, width); memoryPtr += width; + memcpy((void *) screen, memoryPtr, width); memoryPtr += width; screen += screenWidth; } } @@ -523,7 +523,7 @@ void GfxScreen::bitsRestoreDisplayScreen(Common::Rect rect, byte *&memoryPtr) { } for (y = rect.top; y < rect.bottom; y++) { - memcpy((void*) screen, memoryPtr, width); memoryPtr += width; + memcpy((void *) screen, memoryPtr, width); memoryPtr += width; screen += _displayWidth; } } diff --git a/engines/sci/graphics/text16.cpp b/engines/sci/graphics/text16.cpp index 84547d9828..7eaa0168b8 100644 --- a/engines/sci/graphics/text16.cpp +++ b/engines/sci/graphics/text16.cpp @@ -100,7 +100,7 @@ int16 GfxText16::CodeProcessing(const char *&text, GuiResourceId orgFontId, int1 // cX -> sets textColor to _textColors[X-1] curCode = textCode[0]; curCodeParm = textCode[1]; - if (isdigit(static_cast<unsigned char>(curCodeParm))) { + if (Common::isDigit(curCodeParm)) { curCodeParm -= '0'; } else { curCodeParm = -1; diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp index 029030165d..7894c7109c 100644 --- a/engines/sci/graphics/text32.cpp +++ b/engines/sci/graphics/text32.cpp @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/engines/sci/graphics/text16.cpp $ - * $Id: text16.cpp 55178 2011-01-08 23:16:44Z thebluegr $ - * */ #include "common/util.h" @@ -41,6 +38,10 @@ namespace Sci { #define BITMAP_HEADER_SIZE 46 +#define SCI_TEXT32_ALIGNMENT_RIGHT -1 +#define SCI_TEXT32_ALIGNMENT_CENTER 1 +#define SCI_TEXT32_ALIGNMENT_LEFT 0 + GfxText32::GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen) : _segMan(segMan), _cache(fonts), _screen(screen) { } @@ -48,7 +49,7 @@ GfxText32::GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen) GfxText32::~GfxText32() { } -reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxHeight) { +reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t prevHunk) { reg_t stringObject = readSelector(_segMan, textObject, SELECTOR(text)); // The object in the text selector of the item can be either a raw string @@ -58,13 +59,21 @@ reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxH stringObject = readSelector(_segMan, stringObject, SELECTOR(data)); Common::String text = _segMan->getString(stringObject); - GfxFont *font = _cache->getFont(readSelectorValue(_segMan, textObject, SELECTOR(font))); + // HACK: The character offsets of the up and down arrow buttons are off by one + // in GK1, for some unknown reason. Fix them here. + if (text.size() == 1 && (text[0] == 29 || text[0] == 30)) { + text.setChar(text[0] + 1, 0); + } + GuiResourceId fontId = readSelectorValue(_segMan, textObject, SELECTOR(font)); + GfxFont *font = _cache->getFont(fontId); bool dimmed = readSelectorValue(_segMan, textObject, SELECTOR(dimmed)); + int16 alignment = readSelectorValue(_segMan, textObject, SELECTOR(mode)); uint16 foreColor = readSelectorValue(_segMan, textObject, SELECTOR(fore)); + uint16 backColor = readSelectorValue(_segMan, textObject, SELECTOR(back)); - Common::Rect planeRect = getPlaneRect(textObject); - uint16 width = planeRect.width() + 1; - uint16 height = planeRect.height() + 1; + Common::Rect nsRect = g_sci->_gfxCompare->getNSRect(textObject); + uint16 width = nsRect.width() + 1; + uint16 height = nsRect.height() + 1; // Limit rectangle dimensions, if requested if (maxWidth > 0) @@ -79,24 +88,74 @@ reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxH } int entrySize = width * height + BITMAP_HEADER_SIZE; - reg_t memoryId = _segMan->allocateHunkEntry("TextBitmap()", entrySize); - writeSelector(_segMan, textObject, SELECTOR(bitmap), memoryId); + reg_t memoryId = NULL_REG; + if (prevHunk.isNull()) { + memoryId = _segMan->allocateHunkEntry("TextBitmap()", entrySize); + writeSelector(_segMan, textObject, SELECTOR(bitmap), memoryId); + } else { + memoryId = prevHunk; + } byte *memoryPtr = _segMan->getHunkPointer(memoryId); - memset(memoryPtr, 0, entrySize); + + if (prevHunk.isNull()) + memset(memoryPtr, 0, BITMAP_HEADER_SIZE); + byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE; + memset(bitmap, backColor, width * height); + + // Save totalWidth, totalHeight + WRITE_LE_UINT16(memoryPtr, width); + WRITE_LE_UINT16(memoryPtr + 2, height); int16 charCount = 0; uint16 curX = 0, curY = 0; const char *txt = text.c_str(); + int16 textWidth, textHeight, totalHeight = 0, offsetX = 0, offsetY = 0; + uint16 start = 0; + + // Calculate total text height + while (*txt) { + charCount = GetLongest(txt, width, font); + if (charCount == 0) + break; + + Width(txt, 0, (int16)strlen(txt), fontId, textWidth, textHeight, true); + + totalHeight += textHeight; + txt += charCount; + while (*txt == ' ') + txt++; // skip over breaking spaces + } + + txt = text.c_str(); + // Draw text in buffer while (*txt) { charCount = GetLongest(txt, width, font); if (charCount == 0) break; + Width(txt, start, charCount, fontId, textWidth, textHeight, true); + + switch (alignment) { + case SCI_TEXT32_ALIGNMENT_RIGHT: + offsetX = width - textWidth; + break; + case SCI_TEXT32_ALIGNMENT_CENTER: + // Center text both horizontally and vertically + offsetX = (width - textWidth) / 2; + offsetY = (height - totalHeight) / 2; + break; + case SCI_TEXT32_ALIGNMENT_LEFT: + offsetX = 0; + break; + + default: + warning("Invalid alignment %d used in TextBox()", alignment); + } for (int i = 0; i < charCount; i++) { unsigned char curChar = txt[i]; - font->drawToBuffer(curChar, curY, curX, foreColor, dimmed, bitmap, width, height); + font->drawToBuffer(curChar, curY + offsetY, curX + offsetX, foreColor, dimmed, bitmap, width, height); curX += font->getCharWidth(curChar); } @@ -114,13 +173,18 @@ void GfxText32::disposeTextBitmap(reg_t hunkId) { _segMan->freeHunkEntry(hunkId); } -void GfxText32::drawTextBitmap(reg_t textObject) { +void GfxText32::drawTextBitmap(int16 x, int16 y, Common::Rect planeRect, reg_t textObject) { reg_t hunkId = readSelector(_segMan, textObject, SELECTOR(bitmap)); + uint16 backColor = readSelectorValue(_segMan, textObject, SELECTOR(back)); // Sanity check: Check if the hunk is set. If not, either the game scripts // didn't set it, or an old saved game has been loaded, where it wasn't set. if (hunkId.isNull()) return; + // Negative coordinates indicate that text shouldn't be displayed + if (x < 0 || y < 0) + return; + byte *memoryPtr = _segMan->getHunkPointer(hunkId); if (!memoryPtr) @@ -129,46 +193,28 @@ void GfxText32::drawTextBitmap(reg_t textObject) { byte *surface = memoryPtr + BITMAP_HEADER_SIZE; int curByte = 0; - Common::Rect nsRect = g_sci->_gfxCompare->getNSRect(textObject); - Common::Rect planeRect = getPlaneRect(textObject); - uint16 x = readSelectorValue(_segMan, textObject, SELECTOR(x)); - uint16 y = readSelectorValue(_segMan, textObject, SELECTOR(y)); + uint16 skipColor = readSelectorValue(_segMan, textObject, SELECTOR(skip)); uint16 textX = planeRect.left + x; uint16 textY = planeRect.top + y; - uint16 width = nsRect.width() + 1; - uint16 height = nsRect.height() + 1; + // Get totalWidth, totalHeight + uint16 width = READ_LE_UINT16(memoryPtr); + uint16 height = READ_LE_UINT16(memoryPtr + 2); // Upscale the coordinates/width if the fonts are already upscaled if (_screen->fontIsUpscaled()) { textX = textX * _screen->getDisplayWidth() / _screen->getWidth(); textY = textY * _screen->getDisplayHeight() / _screen->getHeight(); - width = width * _screen->getDisplayWidth() / _screen->getWidth(); - height = height * _screen->getDisplayHeight() / _screen->getHeight(); } for (int curY = 0; curY < height; curY++) { for (int curX = 0; curX < width; curX++) { byte pixel = surface[curByte++]; - if (pixel) + if (pixel != skipColor && pixel != backColor) _screen->putFontPixel(textY, curX + textX, curY, pixel); } } } -Common::Rect GfxText32::getPlaneRect(reg_t textObject) { - Common::Rect planeRect(0, 0, _screen->getWidth(), _screen->getHeight()); - - reg_t planeObject = readSelector(_segMan, textObject, SELECTOR(plane)); - if (!planeObject.isNull()) { - planeRect.top = readSelectorValue(_segMan, planeObject, SELECTOR(top)); - planeRect.left = readSelectorValue(_segMan, planeObject, SELECTOR(left)); - planeRect.bottom = readSelectorValue(_segMan, planeObject, SELECTOR(bottom)); - planeRect.right = readSelectorValue(_segMan, planeObject, SELECTOR(right)); - } - - return planeRect; -} - int16 GfxText32::GetLongest(const char *text, int16 maxWidth, GfxFont *font) { uint16 curChar = 0; int16 maxChars = 0, curCharCount = 0; @@ -251,6 +297,10 @@ int16 GfxText32::Size(Common::Rect &rect, const char *text, GuiResourceId fontId int16 maxTextWidth = 0, textWidth; int16 totalHeight = 0, textHeight; + // Adjust maxWidth if we're using an upscaled font + if (_screen->fontIsUpscaled()) + maxWidth = maxWidth * _screen->getDisplayWidth() / _screen->getWidth(); + rect.top = rect.left = 0; GfxFont *font = _cache->getFont(fontId); @@ -277,6 +327,14 @@ int16 GfxText32::Size(Common::Rect &rect, const char *text, GuiResourceId fontId rect.bottom = totalHeight; rect.right = maxWidth ? maxWidth : MIN(rect.right, maxTextWidth); } + + // Adjust the width/height if we're using an upscaled font + // for the scripts + if (_screen->fontIsUpscaled()) { + rect.right = rect.right * _screen->getWidth() / _screen->getDisplayWidth(); + rect.bottom = rect.bottom * _screen->getHeight() / _screen->getDisplayHeight(); + } + return rect.right; } diff --git a/engines/sci/graphics/text32.h b/engines/sci/graphics/text32.h index dfcbf63ccf..3505de85eb 100644 --- a/engines/sci/graphics/text32.h +++ b/engines/sci/graphics/text32.h @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/engines/sci/graphics/text16.h $ - * $Id: text16.h 55178 2011-01-08 23:16:44Z thebluegr $ - * */ #ifndef SCI_GRAPHICS_TEXT32_H @@ -35,9 +32,9 @@ class GfxText32 { public: GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen); ~GfxText32(); - reg_t createTextBitmap(reg_t textObject, uint16 maxWidth = 0, uint16 maxHeight = 0); + reg_t createTextBitmap(reg_t textObject, uint16 maxWidth = 0, uint16 maxHeight = 0, reg_t prevHunk = NULL_REG); void disposeTextBitmap(reg_t hunkId); - void drawTextBitmap(reg_t textObject); + void drawTextBitmap(int16 x, int16 y, Common::Rect planeRect, reg_t textObject); int16 GetLongest(const char *text, int16 maxWidth, GfxFont *font); void kernelTextSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight); @@ -46,7 +43,6 @@ private: int16 Size(Common::Rect &rect, const char *text, GuiResourceId fontId, int16 maxWidth); void Width(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight, bool restoreFont); void StringWidth(const char *str, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight); - Common::Rect getPlaneRect(reg_t textObject); SegManager *_segMan; GfxCache *_cache; diff --git a/engines/sci/graphics/transitions.cpp b/engines/sci/graphics/transitions.cpp index d047eb10a1..b385c2c1db 100644 --- a/engines/sci/graphics/transitions.cpp +++ b/engines/sci/graphics/transitions.cpp @@ -52,8 +52,8 @@ static const GfxTransitionTranslateEntry oldTransitionIDs[] = { { 3, SCI_TRANSITIONS_STRAIGHT_FROM_LEFT, false }, { 4, SCI_TRANSITIONS_STRAIGHT_FROM_BOTTOM, false }, { 5, SCI_TRANSITIONS_STRAIGHT_FROM_TOP, false }, - { 6, SCI_TRANSITIONS_DIAGONALROLL_FROMCENTER, false }, - { 7, SCI_TRANSITIONS_DIAGONALROLL_TOCENTER, false }, + { 6, SCI_TRANSITIONS_DIAGONALROLL_TOCENTER, false }, + { 7, SCI_TRANSITIONS_DIAGONALROLL_FROMCENTER, false }, { 8, SCI_TRANSITIONS_BLOCKS, false }, { 9, SCI_TRANSITIONS_VERTICALROLL_TOCENTER, false }, { 10, SCI_TRANSITIONS_HORIZONTALROLL_TOCENTER, false }, @@ -295,12 +295,12 @@ void GfxTransitions::fadeOut() { int16 stepNr, colorNr; // Sierra did not fade in/out color 255 for sci1.1, but they used it in // several pictures (e.g. qfg3 demo/intro), so the fading looked weird - int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 256 : 255; + int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 255 : 254; g_system->getPaletteManager()->grabPalette(oldPalette, 0, 256); for (stepNr = 100; stepNr >= 0; stepNr -= 10) { - for (colorNr = 1; colorNr < tillColorNr; colorNr++) { + for (colorNr = 1; colorNr <= tillColorNr; colorNr++) { if (_palette->colorIsFromMacClut(colorNr)) { workPalette[colorNr * 3 + 0] = oldPalette[colorNr * 3]; workPalette[colorNr * 3 + 1] = oldPalette[colorNr * 3 + 1]; @@ -311,7 +311,7 @@ void GfxTransitions::fadeOut() { workPalette[colorNr * 3 + 2] = oldPalette[colorNr * 3 + 2] * stepNr / 100; } } - g_system->getPaletteManager()->setPalette(workPalette + 3, 1, 254); + g_system->getPaletteManager()->setPalette(workPalette + 3, 1, tillColorNr); g_sci->getEngineState()->wait(2); } } @@ -322,10 +322,10 @@ void GfxTransitions::fadeIn() { int16 stepNr; // Sierra did not fade in/out color 255 for sci1.1, but they used it in // several pictures (e.g. qfg3 demo/intro), so the fading looked weird - int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 256 : 255; + int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 255 : 254; for (stepNr = 0; stepNr <= 100; stepNr += 10) { - _palette->kernelSetIntensity(1, tillColorNr, stepNr, true); + _palette->kernelSetIntensity(1, tillColorNr + 1, stepNr, true); g_sci->getEngineState()->wait(2); } } diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index e095cde697..a77bcccc52 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -432,10 +432,11 @@ void unpackCelData(byte *inBuffer, byte *celBitmap, byte clearColor, int pixelCo // Skip the next YYYYY pixels (i.e. transparency) if (literalPos && isMacSci11ViewData) { - // KQ6/Freddy Pharkas use byte lengths, all others use uint16 + // KQ6/Freddy Pharkas/Slater use byte lengths, all others use uint16 // The SCI devs must have realized that a max of 255 pixels wide // was not very good for 320 or 640 width games. - bool hasByteLengths = (g_sci->getGameId() == GID_KQ6 || g_sci->getGameId() == GID_FREDDYPHARKAS); + bool hasByteLengths = (g_sci->getGameId() == GID_KQ6 || g_sci->getGameId() == GID_FREDDYPHARKAS + || g_sci->getGameId() == GID_SLATER); // compression for SCI1.1+ Mac while (pixelNr < pixelCount) { |