aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/graphics
diff options
context:
space:
mode:
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.cpp204
-rw-r--r--engines/sci/graphics/controls32.h51
-rw-r--r--engines/sci/graphics/coordadjuster.cpp16
-rw-r--r--engines/sci/graphics/coordadjuster.h4
-rw-r--r--engines/sci/graphics/cursor.cpp53
-rw-r--r--engines/sci/graphics/cursor.h15
-rw-r--r--engines/sci/graphics/frameout.cpp401
-rw-r--r--engines/sci/graphics/frameout.h13
-rw-r--r--engines/sci/graphics/palette.cpp9
-rw-r--r--engines/sci/graphics/screen.cpp8
-rw-r--r--engines/sci/graphics/text16.cpp2
-rw-r--r--engines/sci/graphics/text32.cpp130
-rw-r--r--engines/sci/graphics/text32.h8
-rw-r--r--engines/sci/graphics/transitions.cpp14
-rw-r--r--engines/sci/graphics/view.cpp5
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) {