From 24e57808aa946ad38379b43ca205af6ef151c66a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 29 Apr 2012 20:26:05 +0300 Subject: SCI: Add a hack to fix the cursor colors in Longbow (bug #3489101) --- engines/sci/graphics/cursor.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 71f4598afc..14ffa69f91 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -148,11 +148,13 @@ void GfxCursor::kernelSetShape(GuiResourceId resourceId) { 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. + // TODO: Figure out if the grey color is hardcoded + // HACK for the magnifier cursor in LB1, fixes its color (bug #3487092) if (g_sci->getGameId() == GID_LAURABOW && resourceId == 1) colorMapping[3] = _screen->getColorWhite(); + // HACK for Longbow cursors, fixes the shade of grey they're using (bug #3489101) + if (g_sci->getGameId() == GID_LONGBOW) + colorMapping[3] = _palette->matchColor(223, 223, 223); // Light Grey // Seek to actual data resourceData += 4; -- cgit v1.2.3 From c424c22f19a050b1a2ee421e80172f7dda571dac Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 11 May 2012 12:54:06 +0300 Subject: SCI: Fix bug #3040625 - "SCI: ECOQUEST French/German: Speech balloon graphic glitch" This bug is caused by the fact that the sprites in that scene and the speech bubble share the same priority, so we compensate for that with a workaround --- engines/sci/graphics/view.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index a77bcccc52..4e5c4da8b2 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -720,6 +720,19 @@ void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const bitmap += (clipRect.top - rect.top) * celWidth + (clipRect.left - rect.left); + // WORKAROUND: EcoQuest French and German draw the fish and anemone sprites + // with priority 15 in scene 440. Afterwards, a dialog is shown on top of + // these sprites with priority 15 as well. This is undefined behavior + // actually, as the sprites and dialog share the same priority, so in our + // implementation the sprites get drawn incorrectly on top of the dialog. + // Perhaps this worked by mistake in SSCI because of subtle differences in + // how sprites are drawn. We compensate for this by resetting the priority + // of all sprites that have a priority of 15 in scene 440 to priority 14, + // so that the speech bubble can be drawn correctly on top of them. Fixes + // bug #3040625. + if (g_sci->getGameId() == GID_ECOQUEST && g_sci->getEngineState()->currentRoomNumber() == 440 && priority == 15) + priority = 14; + if (!_EGAmapping) { for (y = 0; y < height; y++, bitmap += celWidth) { for (x = 0; x < width; x++) { -- cgit v1.2.3 From 398d0ffceffc2dc1241b3f667c180573c288ccbf Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 14 May 2012 02:30:15 +0300 Subject: SCI: Check for object visibility, if an object defines it Fixes the inventory in GK1 --- engines/sci/graphics/frameout.cpp | 10 ++++++++++ engines/sci/graphics/frameout.h | 1 + 2 files changed, 11 insertions(+) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index b12413ab69..42b51e409d 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -237,6 +237,7 @@ void GfxFrameout::kernelAddScreenItem(reg_t object) { memset(itemEntry, 0, sizeof(FrameoutEntry)); itemEntry->object = object; itemEntry->givenOrderNr = _screenItems.size(); + itemEntry->visible = true; _screenItems.push_back(itemEntry); kernelUpdateScreenItem(object); @@ -266,6 +267,11 @@ void GfxFrameout::kernelUpdateScreenItem(reg_t object) { itemEntry->signal = readSelectorValue(_segMan, object, SELECTOR(signal)); itemEntry->scaleX = readSelectorValue(_segMan, object, SELECTOR(scaleX)); itemEntry->scaleY = readSelectorValue(_segMan, object, SELECTOR(scaleY)); + itemEntry->visible = true; + + // Check if the entry can be hidden + if (lookupSelector(_segMan, object, SELECTOR(visible), NULL, NULL) != kSelectorNone) + itemEntry->visible = readSelectorValue(_segMan, object, SELECTOR(visible)); } void GfxFrameout::kernelDeleteScreenItem(reg_t object) { @@ -433,6 +439,7 @@ void GfxFrameout::createPlaneItemList(reg_t planeObject, FrameoutList &itemList) picEntry->x = planePicture->getSci32celX(pictureCelNr); picEntry->picStartX = pictureIt->startX; picEntry->picStartY = pictureIt->startY; + picEntry->visible = true; picEntry->priority = planePicture->getSci32celPriority(pictureCelNr); @@ -541,6 +548,9 @@ void GfxFrameout::kernelFrameout() { for (FrameoutList::iterator listIterator = itemList.begin(); listIterator != itemList.end(); listIterator++) { FrameoutEntry *itemEntry = *listIterator; + if (!itemEntry->visible) + continue; + if (itemEntry->object.isNull()) { // Picture cel data itemEntry->x = upscaleHorizontalCoordinate(itemEntry->x); diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index 8c3cc261d5..a3d686c592 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -60,6 +60,7 @@ struct FrameoutEntry { GfxPicture *picture; int16 picStartX; int16 picStartY; + bool visible; }; typedef Common::List FrameoutList; -- cgit v1.2.3 From 6b38731d393cdc85937c74b301df5f3b3de5af9e Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 14 May 2012 11:04:58 +0300 Subject: SCI: Implement savegame deletion functionality in SCI32 This is based on two kernel functions, kMakeSaveCatName and kMakeSaveFileName --- engines/sci/graphics/text32.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp index 7894c7109c..cd24ca5a99 100644 --- a/engines/sci/graphics/text32.cpp +++ b/engines/sci/graphics/text32.cpp @@ -187,8 +187,11 @@ void GfxText32::drawTextBitmap(int16 x, int16 y, Common::Rect planeRect, reg_t t byte *memoryPtr = _segMan->getHunkPointer(hunkId); - if (!memoryPtr) - error("Attempt to draw an invalid text bitmap"); + if (!memoryPtr) { + // Happens when restoring in some SCI32 games + warning("Attempt to draw an invalid text bitmap"); + return; + } byte *surface = memoryPtr + BITMAP_HEADER_SIZE; -- cgit v1.2.3 From 6cda15ba8e57891471c53449433385f5992bce3a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 21 May 2012 01:29:30 +0300 Subject: SCI: Added two new debug commands, plane_list and plane_items These can be used to debug drawn items in SCI32 --- engines/sci/graphics/frameout.cpp | 51 +++++++++++++++++++++++++++++++++++++++ engines/sci/graphics/frameout.h | 2 ++ 2 files changed, 53 insertions(+) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 42b51e409d..709a708d8b 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -31,6 +31,7 @@ #include "graphics/surface.h" #include "sci/sci.h" +#include "sci/console.h" #include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" @@ -677,4 +678,54 @@ void GfxFrameout::kernelFrameout() { g_sci->getEngineState()->_throttleTrigger = true; } +void GfxFrameout::printPlaneList(Console *con) { + for (PlaneList::const_iterator it = _planes.begin(); it != _planes.end(); ++it) { + PlaneEntry p = *it; + Common::String curPlaneName = _segMan->getObjectName(p.object); + Common::Rect r = p.upscaledPlaneRect; + Common::Rect cr = p.upscaledPlaneClipRect; + + con->DebugPrintf("%04x:%04x (%s): prio %d, lastprio %d, offsetX %d, offsetY %d, pic %d, mirror %d, back %d\n", + PRINT_REG(p.object), curPlaneName.c_str(), + (int16)p.priority, (int16)p.lastPriority, + p.planeOffsetX, p.planeOffsetY, p.pictureId, + p.planePictureMirrored, p.planeBack); + con->DebugPrintf(" rect: (%d, %d, %d, %d), clip rect: (%d, %d, %d, %d)\n", + r.left, r.top, r.right, r.bottom, + cr.left, cr.top, cr.right, cr.bottom); + + if (p.pictureId != 0xffff && p.pictureId != 0xfffe) { + con->DebugPrintf("Pictures:\n"); + + for (PlanePictureList::iterator pictureIt = _planePictures.begin(); pictureIt != _planePictures.end(); pictureIt++) { + if (pictureIt->object == p.object) { + con->DebugPrintf(" Picture %d: x %d, y %d\n", pictureIt->pictureId, pictureIt->startX, pictureIt->startY); + } + } + } + } +} + +void GfxFrameout::printPlaneItemList(Console *con, reg_t planeObject) { + for (FrameoutList::iterator listIterator = _screenItems.begin(); listIterator != _screenItems.end(); listIterator++) { + FrameoutEntry *e = *listIterator; + reg_t itemPlane = readSelector(_segMan, e->object, SELECTOR(plane)); + + if (planeObject == itemPlane) { + Common::String curItemName = _segMan->getObjectName(e->object); + Common::Rect icr = e->celRect; + GuiResourceId picId = e->picture ? e->picture->getResourceId() : 0; + + con->DebugPrintf("%d: %04x:%04x (%s), view %d, loop %d, cel %d, x %d, y %d, z %d, " + "signal %d, scale signal %d, scaleX %d, scaleY %d, rect (%d, %d, %d, %d), " + "pic %d, picX %d, picY %d, visible %d\n", + e->givenOrderNr, PRINT_REG(e->object), curItemName.c_str(), + e->viewId, e->loopNo, e->celNo, e->x, e->y, e->z, + e->signal, e->scaleSignal, e->scaleX, e->scaleY, + icr.left, icr.top, icr.right, icr.bottom, + picId, e->picStartX, e->picStartY, e->visible); + } + } +} + } // End of namespace Sci diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index a3d686c592..ec4de62c0a 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -104,6 +104,8 @@ public: void addPlanePicture(reg_t object, GuiResourceId pictureId, uint16 startX, uint16 startY = 0); void deletePlanePictures(reg_t object); void clear(); + void printPlaneList(Console *con); + void printPlaneItemList(Console *con, reg_t planeObject); private: void showVideo(); -- cgit v1.2.3 From de3f6a19ed6ca98ad152f5038c1db1f70f2c72ed Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 7 Jun 2012 11:26:32 +0300 Subject: SCI: Initial implementation of kScrollWindow, used in some SCI21 games This is used in LSL6 hires and SQ6. This initial implementation is hackish and only works in SQ6 (nothing is shown in LSL6) --- engines/sci/graphics/frameout.cpp | 45 +++++++++++++++++++++++++++++++++++++++ engines/sci/graphics/frameout.h | 25 ++++++++++++++++++++++ engines/sci/graphics/text32.cpp | 39 +++++++++++++++++++++++++++++---- engines/sci/graphics/text32.h | 6 +++++- 4 files changed, 110 insertions(+), 5 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 709a708d8b..450581000b 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -59,6 +59,9 @@ GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAd _coordAdjuster = (GfxCoordAdjuster32 *)coordAdjuster; _scriptsRunningWidth = 320; _scriptsRunningHeight = 200; + _curScrollText = -1; + _showScrollText = false; + _maxScrollTexts = 0; } GfxFrameout::~GfxFrameout() { @@ -69,6 +72,46 @@ void GfxFrameout::clear() { deletePlaneItems(NULL_REG); _planes.clear(); deletePlanePictures(NULL_REG); + clearScrollTexts(); +} + +void GfxFrameout::clearScrollTexts() { + _scrollTexts.clear(); + _curScrollText = -1; +} + +void GfxFrameout::addScrollTextEntry(Common::String &text, reg_t kWindow, uint16 x, uint16 y, bool replace) { + //reg_t bitmapHandle = g_sci->_gfxText32->createScrollTextBitmap(text, kWindow); + // HACK: We set the container dimensions manually + reg_t bitmapHandle = g_sci->_gfxText32->createScrollTextBitmap(text, kWindow, 480, 70); + ScrollTextEntry textEntry; + textEntry.bitmapHandle = bitmapHandle; + textEntry.kWindow = kWindow; + textEntry.x = x; + textEntry.y = y; + if (!replace || _scrollTexts.size() == 0) { + if (_scrollTexts.size() > _maxScrollTexts) { + _scrollTexts.remove_at(0); + _curScrollText--; + } + _scrollTexts.push_back(textEntry); + _curScrollText++; + } else { + _scrollTexts.pop_back(); + _scrollTexts.push_back(textEntry); + } +} + +void GfxFrameout::showCurrentScrollText() { + if (!_showScrollText || _curScrollText < 0) + return; + + uint16 size = (uint16)_scrollTexts.size(); + if (size > 0) { + assert(_curScrollText < size); + ScrollTextEntry textEntry = _scrollTexts[_curScrollText]; + g_sci->_gfxText32->drawScrollTextBitmap(textEntry.kWindow, textEntry.bitmapHandle, textEntry.x, textEntry.y); + } } void GfxFrameout::kernelAddPlane(reg_t object) { @@ -673,6 +716,8 @@ void GfxFrameout::kernelFrameout() { } } + showCurrentScrollText(); + _screen->copyToScreen(); g_sci->getEngineState()->_throttleTrigger = true; diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index ec4de62c0a..2d2ca6546c 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -76,6 +76,15 @@ struct PlanePictureEntry { typedef Common::List PlanePictureList; +struct ScrollTextEntry { + reg_t bitmapHandle; + reg_t kWindow; + uint16 x; + uint16 y; +}; + +typedef Common::Array ScrollTextList; + class GfxCache; class GfxCoordAdjuster32; class GfxPaint32; @@ -104,6 +113,18 @@ public: void addPlanePicture(reg_t object, GuiResourceId pictureId, uint16 startX, uint16 startY = 0); void deletePlanePictures(reg_t object); void clear(); + + // Scroll text functions + void addScrollTextEntry(Common::String &text, reg_t kWindow, uint16 x, uint16 y, bool replace); + void showCurrentScrollText(); + void initScrollText(uint16 maxItems) { _maxScrollTexts = maxItems; } + void clearScrollTexts(); + void firstScrollText() { if (_scrollTexts.size() > 0) _curScrollText = 0; } + void lastScrollText() { if (_scrollTexts.size() > 0) _curScrollText = _scrollTexts.size() - 1; } + void prevScrollText() { if (_curScrollText > 0) _curScrollText--; } + void nextScrollText() { if (_curScrollText + 1 < (uint16)_scrollTexts.size()) _curScrollText++; } + void toggleScrollText(bool show) { _showScrollText = show; } + void printPlaneList(Console *con); void printPlaneItemList(Console *con, reg_t planeObject); @@ -127,6 +148,10 @@ private: FrameoutList _screenItems; PlaneList _planes; PlanePictureList _planePictures; + ScrollTextList _scrollTexts; + int16 _curScrollText; + bool _showScrollText; + uint16 _maxScrollTexts; void sortPlanes(); diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp index cd24ca5a99..8ac9582535 100644 --- a/engines/sci/graphics/text32.cpp +++ b/engines/sci/graphics/text32.cpp @@ -49,9 +49,12 @@ GfxText32::GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen) GfxText32::~GfxText32() { } +reg_t GfxText32::createScrollTextBitmap(Common::String text, reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t prevHunk) { + return createTextBitmapInternal(text, textObject, maxWidth, maxHeight, prevHunk); + +} 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 // or a Str object. In the latter case, we need to access the object's data // selector to get the raw string. @@ -59,6 +62,11 @@ reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxH stringObject = readSelector(_segMan, stringObject, SELECTOR(data)); Common::String text = _segMan->getString(stringObject); + + return createTextBitmapInternal(text, textObject, maxWidth, maxHeight, prevHunk); +} + +reg_t GfxText32::createTextBitmapInternal(Common::String &text, reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t prevHunk) { // 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)) { @@ -91,7 +99,11 @@ reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxH reg_t memoryId = NULL_REG; if (prevHunk.isNull()) { memoryId = _segMan->allocateHunkEntry("TextBitmap()", entrySize); - writeSelector(_segMan, textObject, SELECTOR(bitmap), memoryId); + + // Scroll text objects have no bitmap selector! + ObjVarRef varp; + if (lookupSelector(_segMan, textObject, SELECTOR(bitmap), &varp, NULL) == kSelectorVariable) + writeSelector(_segMan, textObject, SELECTOR(bitmap), memoryId); } else { memoryId = prevHunk; } @@ -175,6 +187,24 @@ void GfxText32::disposeTextBitmap(reg_t hunkId) { void GfxText32::drawTextBitmap(int16 x, int16 y, Common::Rect planeRect, reg_t textObject) { reg_t hunkId = readSelector(_segMan, textObject, SELECTOR(bitmap)); + drawTextBitmapInternal(x, y, planeRect, textObject, hunkId); +} + +void GfxText32::drawScrollTextBitmap(reg_t textObject, reg_t hunkId, uint16 x, uint16 y) { + /*reg_t plane = readSelector(_segMan, textObject, SELECTOR(plane)); + Common::Rect planeRect; + planeRect.top = readSelectorValue(_segMan, plane, SELECTOR(top)); + planeRect.left = readSelectorValue(_segMan, plane, SELECTOR(left)); + planeRect.bottom = readSelectorValue(_segMan, plane, SELECTOR(bottom)); + planeRect.right = readSelectorValue(_segMan, plane, SELECTOR(right)); + + drawTextBitmapInternal(x, y, planeRect, textObject, hunkId);*/ + + // HACK: we pretty much ignore the plane rect and x, y... + drawTextBitmapInternal(0, 0, Common::Rect(20, 390, 600, 460), textObject, hunkId); +} + +void GfxText32::drawTextBitmapInternal(int16 x, int16 y, Common::Rect planeRect, reg_t textObject, reg_t hunkId) { 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. @@ -188,8 +218,9 @@ void GfxText32::drawTextBitmap(int16 x, int16 y, Common::Rect planeRect, reg_t t byte *memoryPtr = _segMan->getHunkPointer(hunkId); if (!memoryPtr) { - // Happens when restoring in some SCI32 games - warning("Attempt to draw an invalid text bitmap"); + // Happens when restoring in some SCI32 games (e.g. SQ6). + // Commented out to reduce console spam + //warning("Attempt to draw an invalid text bitmap"); return; } diff --git a/engines/sci/graphics/text32.h b/engines/sci/graphics/text32.h index 3505de85eb..ce78003fdf 100644 --- a/engines/sci/graphics/text32.h +++ b/engines/sci/graphics/text32.h @@ -33,13 +33,17 @@ public: GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen); ~GfxText32(); reg_t createTextBitmap(reg_t textObject, uint16 maxWidth = 0, uint16 maxHeight = 0, reg_t prevHunk = NULL_REG); - void disposeTextBitmap(reg_t hunkId); + reg_t createScrollTextBitmap(Common::String text, reg_t textObject, uint16 maxWidth = 0, uint16 maxHeight = 0, reg_t prevHunk = NULL_REG); void drawTextBitmap(int16 x, int16 y, Common::Rect planeRect, reg_t textObject); + void drawScrollTextBitmap(reg_t textObject, reg_t hunkId, uint16 x, uint16 y); + void disposeTextBitmap(reg_t hunkId); int16 GetLongest(const char *text, int16 maxWidth, GfxFont *font); void kernelTextSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight); private: + reg_t createTextBitmapInternal(Common::String &text, reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t hunkId); + void drawTextBitmapInternal(int16 x, int16 y, Common::Rect planeRect, reg_t textObject, reg_t hunkId); 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); -- cgit v1.2.3 From a643981a385b20ef71a4d1987965f5d1b73fdadc Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 8 Jun 2012 11:57:43 +0300 Subject: SCI: Handle resource ID -1 when setting the palVary resource Fixes several wrong colors in SQ6 --- engines/sci/graphics/palette.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 47d1647c6c..ea154c5037 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -698,7 +698,7 @@ void GfxPalette::palVaryInit() { } bool GfxPalette::palVaryLoadTargetPalette(GuiResourceId resourceId) { - _palVaryResourceId = resourceId; + _palVaryResourceId = (resourceId != 65535) ? resourceId : -1; Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false); if (palResource) { // Load and initialize destination palette -- cgit v1.2.3 From 66af2cf1d729e5944641ab203f3d36761fdff132 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 9 Jun 2012 12:12:44 +0300 Subject: SCI: Handle translucent text planes Fixes the incorrect flood fill in the Rada Drums screen in GK1 --- engines/sci/graphics/frameout.cpp | 23 ++++++++++++++--------- engines/sci/graphics/text32.cpp | 9 ++++++--- 2 files changed, 20 insertions(+), 12 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 450581000b..a5bd8ba48e 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -53,6 +53,11 @@ namespace Sci { // TODO/FIXME: This is all guesswork +enum SciSpeciaPlanelPictureCodes { + kPlaneTranslucent = 0xfffe, // -2 + kPlanePlainColored = 0xffff // -1 +}; + GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxCache *cache, GfxScreen *screen, GfxPalette *palette, GfxPaint32 *paint32) : _segMan(segMan), _resMan(resMan), _cache(cache), _screen(screen), _palette(palette), _paint32(paint32) { @@ -137,7 +142,7 @@ void GfxFrameout::kernelAddPlane(reg_t object) { newPlane.lastPriority = 0xFFFF; // hidden newPlane.planeOffsetX = 0; newPlane.planeOffsetY = 0; - newPlane.pictureId = 0xFFFF; + newPlane.pictureId = kPlanePlainColored; newPlane.planePictureMirrored = false; newPlane.planeBack = 0; _planes.push_back(newPlane); @@ -155,7 +160,8 @@ void GfxFrameout::kernelUpdatePlane(reg_t object) { if (lastPictureId != it->pictureId) { // picture got changed, load new picture deletePlanePictures(object); - if ((it->pictureId != 0xFFFF) && (it->pictureId != 0xFFFE)) { + // Draw the plane's picture if it's not a translucent/plane colored frame + if ((it->pictureId != kPlanePlainColored) && (it->pictureId != kPlaneTranslucent)) { // SQ6 gives us a bad picture number for the control menu if (_resMan->testResource(ResourceId(kResourceTypePic, it->pictureId))) addPlanePicture(object, it->pictureId, 0); @@ -248,6 +254,9 @@ void GfxFrameout::kernelDeletePlane(reg_t object) { } void GfxFrameout::addPlanePicture(reg_t object, GuiResourceId pictureId, uint16 startX, uint16 startY) { + if (pictureId == kPlanePlainColored || pictureId == kPlaneTranslucent) // sanity check + return; + PlanePictureEntry newPicture; newPicture.object = object; newPicture.pictureId = pictureId; @@ -574,21 +583,17 @@ 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) // FIXME: This is what SSCI does, and fixes the intro of LSL7, but breaks the dialogs in GK1 (adds black boxes) - if (it->planeBack) + //if (it->pictureId == kPlanePlainColored) // FIXME: This is what SSCI does, and fixes the intro of LSL7, but breaks the dialogs in GK1 (adds black boxes) + if (it->pictureId == kPlanePlainColored && it->planeBack) _paint32->fillRect(it->planeRect, it->planeBack); - GuiResourceId planeMainPictureId = it->pictureId; - _coordAdjuster->pictureSetDisplayArea(it->planeRect); - _palette->drewPicture(planeMainPictureId); + _palette->drewPicture(it->pictureId); FrameoutList itemList; createPlaneItemList(planeObject, itemList); -// warning("Plane %s", _segMan->getObjectName(planeObject)); - for (FrameoutList::iterator listIterator = itemList.begin(); listIterator != itemList.end(); listIterator++) { FrameoutEntry *itemEntry = *listIterator; diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp index 8ac9582535..7907809c91 100644 --- a/engines/sci/graphics/text32.cpp +++ b/engines/sci/graphics/text32.cpp @@ -205,7 +205,7 @@ void GfxText32::drawScrollTextBitmap(reg_t textObject, reg_t hunkId, uint16 x, u } void GfxText32::drawTextBitmapInternal(int16 x, int16 y, Common::Rect planeRect, reg_t textObject, reg_t hunkId) { - uint16 backColor = readSelectorValue(_segMan, textObject, SELECTOR(back)); + int16 backColor = (int16)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()) @@ -227,7 +227,7 @@ void GfxText32::drawTextBitmapInternal(int16 x, int16 y, Common::Rect planeRect, byte *surface = memoryPtr + BITMAP_HEADER_SIZE; int curByte = 0; - uint16 skipColor = readSelectorValue(_segMan, textObject, SELECTOR(skip)); + int16 skipColor = (int16)readSelectorValue(_segMan, textObject, SELECTOR(skip)); uint16 textX = planeRect.left + x; uint16 textY = planeRect.top + y; // Get totalWidth, totalHeight @@ -240,10 +240,13 @@ void GfxText32::drawTextBitmapInternal(int16 x, int16 y, Common::Rect planeRect, textY = textY * _screen->getDisplayHeight() / _screen->getHeight(); } + bool translucent = (skipColor == -1 && backColor == -1); + for (int curY = 0; curY < height; curY++) { for (int curX = 0; curX < width; curX++) { byte pixel = surface[curByte++]; - if (pixel != skipColor && pixel != backColor) + if ((!translucent && pixel != skipColor && pixel != backColor) || + (translucent && pixel != 0xFF)) _screen->putFontPixel(textY, curX + textX, curY, pixel); } } -- cgit v1.2.3 From dc11d223cdb156dd71300a8535cb5ab0940180c1 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 9 Jun 2012 15:36:36 +0300 Subject: SCI: Initial implementation of AddLine, UpdateLine, DeleteLine --- engines/sci/graphics/frameout.cpp | 63 +++++++++++++++++++++++++++++++++++++++ engines/sci/graphics/frameout.h | 15 ++++++++++ 2 files changed, 78 insertions(+) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index a5bd8ba48e..db49497b6b 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -281,6 +281,56 @@ void GfxFrameout::deletePlanePictures(reg_t object) { } } +// Provides the same functionality as kGraph(DrawLine) +reg_t GfxFrameout::addPlaneLine(reg_t object, Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control) { + for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) { + if (it->object == object) { + PlaneLineEntry line; + line.hunkId = _segMan->allocateHunkEntry("PlaneLine()", 1); // we basically use this for a unique ID + line.startPoint = startPoint; + line.endPoint = endPoint; + line.color = color; + line.priority = priority; + line.control = control; + it->lines.push_back(line); + return line.hunkId; + } + } + + return NULL_REG; +} + +void GfxFrameout::updatePlaneLine(reg_t object, reg_t hunkId, Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control) { + for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) { + if (it->object == object) { + for (PlaneLineList::iterator it2 = it->lines.begin(); it2 != it->lines.end(); ++it2) { + if (it2->hunkId == hunkId) { + it2->startPoint = startPoint; + it2->endPoint = endPoint; + it2->color = color; + it2->priority = priority; + it2->control = control; + return; + } + } + } + } +} + +void GfxFrameout::deletePlaneLine(reg_t object, reg_t hunkId) { + for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) { + if (it->object == object) { + for (PlaneLineList::iterator it2 = it->lines.begin(); it2 != it->lines.end(); ++it2) { + if (it2->hunkId == hunkId) { + _segMan->freeHunkEntry(hunkId); + it2 = it->lines.erase(it2); + return; + } + } + } + } +} + void GfxFrameout::kernelAddScreenItem(reg_t object) { // Ignore invalid items if (!_segMan->isObject(object)) @@ -567,6 +617,19 @@ void GfxFrameout::kernelFrameout() { for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); it++) { reg_t planeObject = it->object; + + // Draw any plane lines, if they exist + // These are drawn on invisible planes as well. (e.g. "invisiblePlane" in LSL6 hires) + // FIXME: Lines aren't always drawn (e.g. when the narrator speaks in LSL6 hires). + // Perhaps something is painted over them? + for (PlaneLineList::iterator it2 = it->lines.begin(); it2 != it->lines.end(); ++it2) { + Common::Point startPoint = it2->startPoint; + Common::Point endPoint = it2->endPoint; + _coordAdjuster->kernelLocalToGlobal(startPoint.x, startPoint.y, it->object); + _coordAdjuster->kernelLocalToGlobal(endPoint.x, endPoint.y, it->object); + _screen->drawLine(startPoint, endPoint, it2->color, it2->priority, it2->control); + } + uint16 planeLastPriority = it->lastPriority; // Update priority here, sq6 sets it w/o UpdatePlane diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index 2d2ca6546c..0d80a68f1d 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -27,6 +27,17 @@ namespace Sci { class GfxPicture; +struct PlaneLineEntry { + reg_t hunkId; + Common::Point startPoint; + Common::Point endPoint; + byte color; + byte priority; + byte control; +}; + +typedef Common::List PlaneLineList; + struct PlaneEntry { reg_t object; uint16 priority; @@ -40,6 +51,7 @@ struct PlaneEntry { Common::Rect upscaledPlaneClipRect; bool planePictureMirrored; byte planeBack; + PlaneLineList lines; }; typedef Common::List PlaneList; @@ -112,6 +124,9 @@ public: void addPlanePicture(reg_t object, GuiResourceId pictureId, uint16 startX, uint16 startY = 0); void deletePlanePictures(reg_t object); + reg_t addPlaneLine(reg_t object, Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control); + void updatePlaneLine(reg_t object, reg_t hunkId, Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control); + void deletePlaneLine(reg_t object, reg_t hunkId); void clear(); // Scroll text functions -- cgit v1.2.3 From 425926ed7ebde1fa77f3874498a6f285af75ac08 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 15 Jun 2012 11:33:28 +0300 Subject: SCI: Limit floodfill hack to GK1 Fixes the intro of LSL7 and the inventory screen in PQ4 --- engines/sci/graphics/frameout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index db49497b6b..dff332458a 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -647,7 +647,7 @@ void GfxFrameout::kernelFrameout() { // 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 == kPlanePlainColored) // FIXME: This is what SSCI does, and fixes the intro of LSL7, but breaks the dialogs in GK1 (adds black boxes) - if (it->pictureId == kPlanePlainColored && it->planeBack) + if (it->pictureId == kPlanePlainColored && (it->planeBack || g_sci->getGameId() != GID_GK1)) _paint32->fillRect(it->planeRect, it->planeBack); _coordAdjuster->pictureSetDisplayArea(it->planeRect); -- cgit v1.2.3 From 084c1259fc5c185ec66001708f623d03675bf6f5 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 16 Jun 2012 02:36:17 +0200 Subject: SCI: Get rid of casts on OSystem::copyRectToScreen calls. --- engines/sci/graphics/frameout.cpp | 2 +- engines/sci/graphics/maciconbar.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index dff332458a..7a9c7ba281 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -496,7 +496,7 @@ void GfxFrameout::showVideo() { 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); + g_system->copyRectToScreen(frame->pixels, frame->pitch, x, y, frame->w, frame->h); if (videoDecoder->hasDirtyPalette()) videoDecoder->setSystemPalette(); diff --git a/engines/sci/graphics/maciconbar.cpp b/engines/sci/graphics/maciconbar.cpp index 7ecba5a24d..dfb50b0edb 100644 --- a/engines/sci/graphics/maciconbar.cpp +++ b/engines/sci/graphics/maciconbar.cpp @@ -129,7 +129,7 @@ void GfxMacIconBar::drawIcon(uint16 iconIndex, bool selected) { void GfxMacIconBar::drawEnabledImage(Graphics::Surface *surface, const Common::Rect &rect) { if (surface) - g_system->copyRectToScreen((byte *)surface->pixels, surface->pitch, rect.left, rect.top, rect.width(), rect.height()); + g_system->copyRectToScreen(surface->pixels, surface->pitch, rect.left, rect.top, rect.width(), rect.height()); } void GfxMacIconBar::drawDisabledImage(Graphics::Surface *surface, const Common::Rect &rect) { @@ -153,7 +153,7 @@ void GfxMacIconBar::drawDisabledImage(Graphics::Surface *surface, const Common:: *((byte *)newSurf.getBasePtr(j, i)) = 0; } - g_system->copyRectToScreen((byte *)newSurf.pixels, newSurf.pitch, rect.left, rect.top, rect.width(), rect.height()); + g_system->copyRectToScreen(newSurf.pixels, newSurf.pitch, rect.left, rect.top, rect.width(), rect.height()); newSurf.free(); } -- cgit v1.2.3 From 7b646e5c62c37b5a593994d1e27a79c62fecd501 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 16 Jun 2012 03:19:34 +0200 Subject: SCI: Get rid of casts on CursorManager::replaceCursor calls. --- engines/sci/graphics/cursor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 14ffa69f91..ce77cf6ed3 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -411,7 +411,7 @@ void GfxCursor::refreshPosition() { } } - CursorMan.replaceCursor((const byte *)_cursorSurface, cursorCelInfo->width, cursorCelInfo->height, cursorHotspot.x, cursorHotspot.y, cursorCelInfo->clearKey); + CursorMan.replaceCursor(_cursorSurface, cursorCelInfo->width, cursorCelInfo->height, cursorHotspot.x, cursorHotspot.y, cursorCelInfo->clearKey); } } -- cgit v1.2.3 From 2b50824133ced47f1d8fb6407a1e0212a7eeb41c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 18 Jun 2012 05:21:59 +0300 Subject: SCI: Add setter/getter methods to reg_t's No functionality change has been made with this commit. This avoids setting and getting the reg_t members directly, and is the basis of any future work on large SCI3 scripts (larger than 64KB) --- engines/sci/graphics/animate.cpp | 2 +- engines/sci/graphics/menu.cpp | 8 ++++---- engines/sci/graphics/paint16.cpp | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index 983e697481..ee28c5ca31 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -723,7 +723,7 @@ void GfxAnimate::printAnimateList(Console *con) { const AnimateList::iterator end = _list.end(); for (it = _list.begin(); it != end; ++it) { - Script *scr = _s->_segMan->getScriptIfLoaded(it->object.segment); + Script *scr = _s->_segMan->getScriptIfLoaded(it->object.getSegment()); int16 scriptNo = scr ? scr->getScriptNumber() : -1; con->DebugPrintf("%04x:%04x (%s), script %d, view %d (%d, %d), pal %d, " diff --git a/engines/sci/graphics/menu.cpp b/engines/sci/graphics/menu.cpp index 47f34cf99d..bfecc296a2 100644 --- a/engines/sci/graphics/menu.cpp +++ b/engines/sci/graphics/menu.cpp @@ -219,7 +219,7 @@ void GfxMenu::kernelAddEntry(Common::String title, Common::String content, reg_t } } itemEntry->textVmPtr = contentVmPtr; - itemEntry->textVmPtr.offset += beginPos; + itemEntry->textVmPtr.incOffset(beginPos); if (rightAlignedPos) { rightAlignedPos++; @@ -297,13 +297,13 @@ void GfxMenu::kernelSetAttribute(uint16 menuId, uint16 itemId, uint16 attributeI // We assume here that no script ever creates a separatorLine dynamically break; case SCI_MENU_ATTRIBUTE_KEYPRESS: - itemEntry->keyPress = tolower(value.offset); + itemEntry->keyPress = tolower(value.getOffset()); itemEntry->keyModifier = 0; // TODO: Find out how modifier is handled - debug("setAttr keypress %X %X", value.segment, value.offset); + debug("setAttr keypress %X %X", value.getSegment(), value.getOffset()); break; case SCI_MENU_ATTRIBUTE_TAG: - itemEntry->tag = value.offset; + itemEntry->tag = value.getOffset(); break; default: // Happens when loading a game in LSL3 - attribute 1A diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index c951f3349d..89f3625e2c 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -491,10 +491,10 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) { // processing codes in argv while (argc > 0) { displayArg = argv[0]; - if (displayArg.segment) - displayArg.offset = 0xFFFF; + if (displayArg.getSegment()) + displayArg.setOffset(0xFFFF); argc--; argv++; - switch (displayArg.offset) { + switch (displayArg.getOffset()) { case SCI_DISPLAY_MOVEPEN: _ports->moveTo(argv[0].toUint16(), argv[1].toUint16()); argc -= 2; argv += 2; @@ -547,9 +547,9 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) { if (!(g_sci->getGameId() == GID_LONGBOW && g_sci->isDemo()) && !(g_sci->getGameId() == GID_QFG1 && g_sci->isDemo()) && !(g_sci->getGameId() == GID_PQ2)) - error("Unknown kDisplay argument %d", displayArg.offset); + error("Unknown kDisplay argument %d", displayArg.getOffset()); - if (displayArg.offset == SCI_DISPLAY_DUMMY2) { + if (displayArg.getOffset() == SCI_DISPLAY_DUMMY2) { if (!argc) error("No parameter left for kDisplay(115)"); argc--; argv++; -- cgit v1.2.3 From 221ee34926927693182f835a4404eca17bdb1943 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 20 Jun 2012 04:25:20 +0300 Subject: SCI: Don't attempt to draw line feed characters in SCI32 Fixes junk in the about dialogs in PQ4 --- engines/sci/graphics/text32.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp index 7907809c91..e0f16e7265 100644 --- a/engines/sci/graphics/text32.cpp +++ b/engines/sci/graphics/text32.cpp @@ -165,10 +165,25 @@ reg_t GfxText32::createTextBitmapInternal(Common::String &text, reg_t textObject warning("Invalid alignment %d used in TextBox()", alignment); } + unsigned char curChar; + for (int i = 0; i < charCount; i++) { - unsigned char curChar = txt[i]; - font->drawToBuffer(curChar, curY + offsetY, curX + offsetX, foreColor, dimmed, bitmap, width, height); - curX += font->getCharWidth(curChar); + curChar = txt[i]; + + switch (curChar) { + case 0x0A: + case 0x0D: + case 0: + case 0x9781: // this one is used by SQ4/japanese as line break as well + break; + case 0x7C: + warning("Code processing isn't implemented in SCI32"); + break; + default: + font->drawToBuffer(curChar, curY + offsetY, curX + offsetX, foreColor, dimmed, bitmap, width, height); + curX += font->getCharWidth(curChar); + break; + } } curX = 0; -- cgit v1.2.3 From ea4260529783f80db0abde70c6b1723cf3c6f720 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 20 Jun 2012 10:55:24 +0300 Subject: SCI: Remove multibyte character processing code from SCI32 There are no Japanese/PC-98 SCI32 games, so this code is not needed --- engines/sci/graphics/text32.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp index e0f16e7265..f14ae2ef0b 100644 --- a/engines/sci/graphics/text32.cpp +++ b/engines/sci/graphics/text32.cpp @@ -165,7 +165,7 @@ reg_t GfxText32::createTextBitmapInternal(Common::String &text, reg_t textObject warning("Invalid alignment %d used in TextBox()", alignment); } - unsigned char curChar; + byte curChar; for (int i = 0; i < charCount; i++) { curChar = txt[i]; @@ -174,7 +174,6 @@ reg_t GfxText32::createTextBitmapInternal(Common::String &text, reg_t textObject case 0x0A: case 0x0D: case 0: - case 0x9781: // this one is used by SQ4/japanese as line break as well break; case 0x7C: warning("Code processing isn't implemented in SCI32"); @@ -317,7 +316,7 @@ void GfxText32::StringWidth(const char *str, GuiResourceId fontId, int16 &textWi } void GfxText32::Width(const char *text, int16 from, int16 len, GuiResourceId fontId, int16 &textWidth, int16 &textHeight, bool restoreFont) { - uint16 curChar; + byte curChar; textWidth = 0; textHeight = 0; GfxFont *font = _cache->getFont(fontId); @@ -329,7 +328,6 @@ void GfxText32::Width(const char *text, int16 from, int16 len, GuiResourceId fon switch (curChar) { case 0x0A: case 0x0D: - case 0x9781: // this one is used by SQ4/japanese as line break as well textHeight = MAX (textHeight, font->getHeight()); break; case 0x7C: -- cgit v1.2.3 From 08124396035e8fd0996c9d347be3d606a58ecd1f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 22 Jun 2012 09:31:51 +0300 Subject: SCI: Simplify the SCI32 coordinate adjustment code --- engines/sci/graphics/frameout.cpp | 57 +++++++++++---------------------------- engines/sci/graphics/frameout.h | 6 ----- 2 files changed, 16 insertions(+), 47 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 7a9c7ba281..0681102863 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -62,8 +62,6 @@ 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; _curScrollText = -1; _showScrollText = false; _maxScrollTexts = 0; @@ -129,12 +127,12 @@ void GfxFrameout::kernelAddPlane(reg_t object) { uint16 tmpRunningHeight = readSelectorValue(_segMan, object, SELECTOR(resY)); // The above can be 0 in SCI3 (e.g. Phantasmagoria 2) - if (tmpRunningWidth > 0 && tmpRunningHeight > 0) { - _scriptsRunningWidth = tmpRunningWidth; - _scriptsRunningHeight = tmpRunningHeight; + if (tmpRunningWidth == 0 && tmpRunningHeight == 0) { + tmpRunningWidth = 320; + tmpRunningHeight = 200; } - _coordAdjuster->setScriptsResolution(_scriptsRunningWidth, _scriptsRunningHeight); + _coordAdjuster->setScriptsResolution(tmpRunningWidth, tmpRunningHeight); } newPlane.object = object; @@ -172,11 +170,8 @@ void GfxFrameout::kernelUpdatePlane(reg_t object) { 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; + _coordAdjuster->fromScriptToDisplay(it->planeRect.top, it->planeRect.left); + _coordAdjuster->fromScriptToDisplay(it->planeRect.bottom, it->planeRect.right); // We get negative left in kq7 in scrolling rooms if (it->planeRect.left < 0) { @@ -241,11 +236,9 @@ void GfxFrameout::kernelDeletePlane(reg_t object) { 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; + _coordAdjuster->fromScriptToDisplay(planeRect.top, planeRect.left); + _coordAdjuster->fromScriptToDisplay(planeRect.bottom, planeRect.right); + // Blackout removed plane rect _paint32->fillRect(planeRect, 0); return; @@ -466,23 +459,6 @@ void GfxFrameout::sortPlanes() { Common::sort(_planes.begin(), _planes.end(), planeSortHelper); } -int16 GfxFrameout::upscaleHorizontalCoordinate(int16 coordinate) { - return ((coordinate * _screen->getWidth()) / _scriptsRunningWidth); -} - -int16 GfxFrameout::upscaleVerticalCoordinate(int16 coordinate) { - return ((coordinate * _screen->getHeight()) / _scriptsRunningHeight); -} - -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(); - - return rect; -} - void GfxFrameout::showVideo() { bool skipVideo = false; RobotDecoder *videoDecoder = g_sci->_robotDecoder; @@ -665,10 +641,8 @@ void GfxFrameout::kernelFrameout() { if (itemEntry->object.isNull()) { // Picture cel data - itemEntry->x = upscaleHorizontalCoordinate(itemEntry->x); - itemEntry->y = upscaleVerticalCoordinate(itemEntry->y); - itemEntry->picStartX = upscaleHorizontalCoordinate(itemEntry->picStartX); - itemEntry->picStartY = upscaleVerticalCoordinate(itemEntry->picStartY); + _coordAdjuster->fromScriptToDisplay(itemEntry->y, itemEntry->x); + _coordAdjuster->fromScriptToDisplay(itemEntry->picStartY, itemEntry->picStartX); if (!isPictureOutOfView(itemEntry, it->planeRect, it->planeOffsetX, it->planeOffsetY)) drawPicture(itemEntry, it->planeOffsetX, it->planeOffsetY, it->planePictureMirrored); @@ -680,9 +654,9 @@ void GfxFrameout::kernelFrameout() { view->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x); view->adjustToUpscaledCoordinates(itemEntry->z, dummyX); } else if (getSciVersion() == SCI_VERSION_2_1) { - itemEntry->x = upscaleHorizontalCoordinate(itemEntry->x); - itemEntry->y = upscaleVerticalCoordinate(itemEntry->y); - itemEntry->z = upscaleVerticalCoordinate(itemEntry->z); + _coordAdjuster->fromScriptToDisplay(itemEntry->y, itemEntry->x); + int16 tmpVal = 0; + _coordAdjuster->fromScriptToDisplay(itemEntry->z, tmpVal); } // Adjust according to current scroll position @@ -719,7 +693,8 @@ void GfxFrameout::kernelFrameout() { view->adjustBackUpscaledCoordinates(nsRect.top, nsRect.left); view->adjustBackUpscaledCoordinates(nsRect.bottom, nsRect.right); } else if (getSciVersion() == SCI_VERSION_2_1) { - nsRect = upscaleRect(nsRect); + _coordAdjuster->fromDisplayToScript(nsRect.top, nsRect.left); + _coordAdjuster->fromDisplayToScript(nsRect.bottom, nsRect.right); } if (g_sci->getGameId() == GID_PHANTASMAGORIA2) { diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index 0d80a68f1d..ecaf450d89 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -148,9 +148,6 @@ private: 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; @@ -169,9 +166,6 @@ private: uint16 _maxScrollTexts; void sortPlanes(); - - uint16 _scriptsRunningWidth; - uint16 _scriptsRunningHeight; }; } // End of namespace Sci -- cgit v1.2.3 From 547fdfe12a3b999473304925bf80ae1afda5f8d6 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 22 Jun 2012 09:43:44 +0300 Subject: SCI: Further cleanup of the frame drawing code --- engines/sci/graphics/frameout.cpp | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 0681102863..265a175e66 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -648,15 +648,14 @@ void GfxFrameout::kernelFrameout() { drawPicture(itemEntry, it->planeOffsetX, it->planeOffsetY, it->planePictureMirrored); } else { GfxView *view = (itemEntry->viewId != 0xFFFF) ? _cache->getView(itemEntry->viewId) : NULL; - + int16 dummyX = 0; + 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) { _coordAdjuster->fromScriptToDisplay(itemEntry->y, itemEntry->x); - int16 tmpVal = 0; - _coordAdjuster->fromScriptToDisplay(itemEntry->z, tmpVal); + _coordAdjuster->fromScriptToDisplay(itemEntry->z, dummyX); } // Adjust according to current scroll position @@ -707,17 +706,9 @@ void GfxFrameout::kernelFrameout() { g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect); } - int16 screenHeight = _screen->getHeight(); - int16 screenWidth = _screen->getWidth(); - if (view && view->isSci2Hires()) { - screenHeight = _screen->getDisplayHeight(); - screenWidth = _screen->getDisplayWidth(); - } - - if (itemEntry->celRect.bottom < 0 || itemEntry->celRect.top >= screenHeight) - continue; - - if (itemEntry->celRect.right < 0 || itemEntry->celRect.left >= screenWidth) + // FIXME: When does this happen, and why? + if (itemEntry->celRect.bottom < 0 || itemEntry->celRect.top >= _screen->getDisplayHeight() || + itemEntry->celRect.right < 0 || itemEntry->celRect.left >= _screen->getDisplayWidth()) continue; Common::Rect clipRect, translatedClipRect; -- cgit v1.2.3 From d757b5b94a0b180ce8e2e59617898a322f8ee0d5 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 4 Jul 2012 01:01:35 +0300 Subject: SCI: Update some version checks in kernelFrameout() to work with SCI3 too --- engines/sci/graphics/frameout.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 265a175e66..5703579b1e 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -653,7 +653,7 @@ void GfxFrameout::kernelFrameout() { if (view && view->isSci2Hires()) { view->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x); view->adjustToUpscaledCoordinates(itemEntry->z, dummyX); - } else if (getSciVersion() == SCI_VERSION_2_1) { + } else if (getSciVersion() >= SCI_VERSION_2_1) { _coordAdjuster->fromScriptToDisplay(itemEntry->y, itemEntry->x); _coordAdjuster->fromScriptToDisplay(itemEntry->z, dummyX); } @@ -691,7 +691,7 @@ void GfxFrameout::kernelFrameout() { if (view && view->isSci2Hires()) { view->adjustBackUpscaledCoordinates(nsRect.top, nsRect.left); view->adjustBackUpscaledCoordinates(nsRect.bottom, nsRect.right); - } else if (getSciVersion() == SCI_VERSION_2_1) { + } else if (getSciVersion() >= SCI_VERSION_2_1) { _coordAdjuster->fromDisplayToScript(nsRect.top, nsRect.left); _coordAdjuster->fromDisplayToScript(nsRect.bottom, nsRect.right); } -- cgit v1.2.3 From 5d3e22ae4f5fcf6c7717eb9e50767b3fbb5a10f8 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 4 Jul 2012 02:17:27 +0300 Subject: SCI: Some cleanup of the warnings in the SCI32 plane manipulation code --- engines/sci/graphics/frameout.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 5703579b1e..450460023c 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -326,8 +326,10 @@ void GfxFrameout::deletePlaneLine(reg_t object, reg_t hunkId) { void GfxFrameout::kernelAddScreenItem(reg_t object) { // Ignore invalid items - if (!_segMan->isObject(object)) + if (!_segMan->isObject(object)) { + warning("kernelAddScreenItem: Attempt to add an invalid object (%04x:%04x)", PRINT_REG(object)); return; + } FrameoutEntry *itemEntry = new FrameoutEntry(); memset(itemEntry, 0, sizeof(FrameoutEntry)); @@ -341,8 +343,10 @@ void GfxFrameout::kernelAddScreenItem(reg_t object) { void GfxFrameout::kernelUpdateScreenItem(reg_t object) { // Ignore invalid items - if (!_segMan->isObject(object)) + if (!_segMan->isObject(object)) { + warning("kernelUpdateScreenItem: Attempt to update an invalid object (%04x:%04x)", PRINT_REG(object)); return; + } FrameoutEntry *itemEntry = findScreenItem(object); if (!itemEntry) { @@ -372,10 +376,9 @@ void GfxFrameout::kernelUpdateScreenItem(reg_t object) { void GfxFrameout::kernelDeleteScreenItem(reg_t object) { FrameoutEntry *itemEntry = findScreenItem(object); - if (!itemEntry) { - warning("kernelDeleteScreenItem: invalid object %04x:%04x", PRINT_REG(object)); + // If the item could not be found, it may already have been deleted + if (!itemEntry) return; - } _screenItems.remove(itemEntry); delete itemEntry; -- cgit v1.2.3 From 243ea1fa290a919d5f0a07094782465f0ba08d7e Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 4 Jul 2012 02:20:39 +0300 Subject: SCI: Add a check for invalid clip rectangles Happens in QFG4, when starting a battle --- engines/sci/graphics/frameout.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 450460023c..5b857fe3d8 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -722,6 +722,9 @@ void GfxFrameout::kernelFrameout() { translatedClipRect = clipRect; translatedClipRect.translate(it->upscaledPlaneRect.left, it->upscaledPlaneRect.top); } else { + // QFG4 passes invalid rectangles when a battle is starting + if (!clipRect.isValidRect()) + continue; clipRect.clip(it->planeClipRect); translatedClipRect = clipRect; translatedClipRect.translate(it->planeRect.left, it->planeRect.top); -- cgit v1.2.3 From fb215929efaefdf0b75521caab8a86e93181c5b2 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 5 Jul 2012 13:42:00 +0300 Subject: SCI: Some updates to SCI32 kernel graphics functions - Added a stub for kSetScroll, which sets the target picture immediately for now - Added an initial stub of kPalCycle (doesn't work correctly yet) - Adjusted the signatures of kUpdateLine and kDeleteLine for LSL6 - Unmapped kSetHotRectangles again, with updated information on how it is used in Phantasmagoria --- engines/sci/graphics/frameout.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 5b857fe3d8..31ad7a50aa 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -294,6 +294,10 @@ reg_t GfxFrameout::addPlaneLine(reg_t object, Common::Point startPoint, Common:: } void GfxFrameout::updatePlaneLine(reg_t object, reg_t hunkId, Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control) { + // Check if we're asked to update a line that was never added + if (object.isNull()) + return; + for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) { if (it->object == object) { for (PlaneLineList::iterator it2 = it->lines.begin(); it2 != it->lines.end(); ++it2) { @@ -311,6 +315,10 @@ void GfxFrameout::updatePlaneLine(reg_t object, reg_t hunkId, Common::Point star } void GfxFrameout::deletePlaneLine(reg_t object, reg_t hunkId) { + // Check if we're asked to delete a line that was never added (happens during the intro of LSL6) + if (object.isNull()) + return; + for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) { if (it->object == object) { for (PlaneLineList::iterator it2 = it->lines.begin(); it2 != it->lines.end(); ++it2) { -- cgit v1.2.3 From 112f03390d308af60d9c5f5e9f29c30988d2e968 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 5 Jul 2012 14:05:26 +0300 Subject: SCI: Fix typo --- engines/sci/graphics/frameout.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 31ad7a50aa..20b8a241aa 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -295,7 +295,7 @@ reg_t GfxFrameout::addPlaneLine(reg_t object, Common::Point startPoint, Common:: void GfxFrameout::updatePlaneLine(reg_t object, reg_t hunkId, Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control) { // Check if we're asked to update a line that was never added - if (object.isNull()) + if (hunkId.isNull()) return; for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) { @@ -316,7 +316,7 @@ void GfxFrameout::updatePlaneLine(reg_t object, reg_t hunkId, Common::Point star void GfxFrameout::deletePlaneLine(reg_t object, reg_t hunkId) { // Check if we're asked to delete a line that was never added (happens during the intro of LSL6) - if (object.isNull()) + if (hunkId.isNull()) return; for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) { -- cgit v1.2.3 From 75137862967cd18a87dec16a6a322f9f97d54202 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 6 Jul 2012 12:11:12 +0300 Subject: SCI: Add a hack to handle the internal script resolution in Phantasmagoria --- engines/sci/graphics/frameout.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 20b8a241aa..defc55edb2 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -131,6 +131,20 @@ void GfxFrameout::kernelAddPlane(reg_t object) { tmpRunningWidth = 320; tmpRunningHeight = 200; } + + // HACK: Game scripts in Phantasmagoria 1 seem to use a very odd internal + // resolution, or some other extra calculation is taking place. + // Changing the internal script dimensions to these odd values fixes + // object positioning, but makes the interface picture slightly bigger, + // thus there is a small gap between the room picture and the interface + // edges, plus a couple of pixels of the picture are cut off in the + // bottom. + // FIXME: Find how to properly handle the script dimensions in + // Phantasmagoria. This can't be right. + if (g_sci->getGameId() == GID_PHANTASMAGORIA) { + tmpRunningWidth = 325; + tmpRunningHeight = 213; + } _coordAdjuster->setScriptsResolution(tmpRunningWidth, tmpRunningHeight); } -- cgit v1.2.3 From e4378d5bac1b2467190e21333a037a6af34bba52 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 6 Jul 2012 13:17:04 +0300 Subject: SCI: Better handling for Phantasmagoria's odd screen size Still not right, as the width isn't set --- engines/sci/graphics/frameout.cpp | 13 +++---------- engines/sci/graphics/screen.cpp | 7 +++++++ 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index defc55edb2..b13c7f4dce 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -132,18 +132,11 @@ void GfxFrameout::kernelAddPlane(reg_t object) { tmpRunningHeight = 200; } - // HACK: Game scripts in Phantasmagoria 1 seem to use a very odd internal - // resolution, or some other extra calculation is taking place. - // Changing the internal script dimensions to these odd values fixes - // object positioning, but makes the interface picture slightly bigger, - // thus there is a small gap between the room picture and the interface - // edges, plus a couple of pixels of the picture are cut off in the - // bottom. - // FIXME: Find how to properly handle the script dimensions in - // Phantasmagoria. This can't be right. + // HACK: Phantasmagoria 1 sets a window size of 630x450. + // We can't set a width of 630, as that messes up the pitch, so we hack + // the internal script width here if (g_sci->getGameId() == GID_PHANTASMAGORIA) { tmpRunningWidth = 325; - tmpRunningHeight = 213; } _coordAdjuster->setScriptsResolution(tmpRunningWidth, tmpRunningHeight); diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 4020518b72..3030fb4386 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -97,6 +97,13 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { break; } + // Phantasmagoria 1 sets a window area of 630x450 + if (g_sci->getGameId() == GID_PHANTASMAGORIA) { + // TODO: Also set width to 630 (can't be set right now, as it messes up + // the pitch). For now, a hack has been placed in GfxFrameout::kernelAddPlane() + _height = 450; + } + _displayPixels = _displayWidth * _displayHeight; _visualScreen = (byte *)calloc(_pixels, 1); _priorityScreen = (byte *)calloc(_pixels, 1); -- cgit v1.2.3 From 10b3fdf2478dce3712de6213678f54335d5c46a0 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 8 Jul 2012 16:10:40 +0300 Subject: SCI: Show information for correct file naming in the QFG4 import room This information is shown in previous QFG versions, but it had to be placed in a SCI32 graphics function in order to be shown in QFG4 too --- engines/sci/graphics/frameout.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index b13c7f4dce..cb56e24de9 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -117,6 +117,8 @@ void GfxFrameout::showCurrentScrollText() { } } +extern void showScummVMDialog(const Common::String &message); + void GfxFrameout::kernelAddPlane(reg_t object) { PlaneEntry newPlane; @@ -142,6 +144,19 @@ void GfxFrameout::kernelAddPlane(reg_t object) { _coordAdjuster->setScriptsResolution(tmpRunningWidth, tmpRunningHeight); } + // Import of QfG character files dialog is shown in QFG4. + // Display additional popup information before letting user use it. + // For the SCI0-SCI1.1 version of this, check kDrawControl(). + if (g_sci->inQfGImportRoom() && !strcmp(_segMan->getObjectName(object), "DSPlane")) { + showScummVMDialog("Characters saved inside ScummVM are shown " + "automatically. Character files saved in the original " + "interpreter need to be put inside ScummVM's saved games " + "directory and a prefix needs to be added depending on which " + "game it was saved in: 'qfg1-' for Quest for Glory 1, 'qfg2-' " + "for Quest for Glory 2, 'qfg3-' for Quest for Glory 3. " + "Example: 'qfg2-thief.sav'."); + } + newPlane.object = object; newPlane.priority = readSelectorValue(_segMan, object, SELECTOR(priority)); newPlane.lastPriority = 0xFFFF; // hidden -- cgit v1.2.3 From 1a90ca5ecd9eeaaca3b6de79dd940e9b29e472aa Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 16 Jul 2012 11:49:50 +0300 Subject: SCI: Handle all negative priority values. Fixes graphics in the SQ6 demo --- engines/sci/graphics/frameout.cpp | 17 ++++++----------- engines/sci/graphics/frameout.h | 4 ++-- 2 files changed, 8 insertions(+), 13 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index cb56e24de9..fedae2eb6f 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -159,7 +159,7 @@ void GfxFrameout::kernelAddPlane(reg_t object) { newPlane.object = object; newPlane.priority = readSelectorValue(_segMan, object, SELECTOR(priority)); - newPlane.lastPriority = 0xFFFF; // hidden + newPlane.lastPriority = -1; // hidden newPlane.planeOffsetX = 0; newPlane.planeOffsetY = 0; newPlane.pictureId = kPlanePlainColored; @@ -465,15 +465,10 @@ bool sortHelper(const FrameoutEntry* entry1, const FrameoutEntry* entry2) { } bool planeSortHelper(const PlaneEntry &entry1, const PlaneEntry &entry2) { -// SegManager *segMan = g_sci->getEngineState()->_segMan; - -// uint16 plane1Priority = readSelectorValue(segMan, entry1, SELECTOR(priority)); -// uint16 plane2Priority = readSelectorValue(segMan, entry2, SELECTOR(priority)); - - if (entry1.priority == 0xffff) + if (entry1.priority < 0) return true; - if (entry2.priority == 0xffff) + if (entry2.priority < 0) return false; return entry1.priority < entry2.priority; @@ -639,13 +634,13 @@ void GfxFrameout::kernelFrameout() { _screen->drawLine(startPoint, endPoint, it2->color, it2->priority, it2->control); } - uint16 planeLastPriority = it->lastPriority; + int16 planeLastPriority = it->lastPriority; // Update priority here, sq6 sets it w/o UpdatePlane - uint16 planePriority = it->priority = readSelectorValue(_segMan, planeObject, SELECTOR(priority)); + int16 planePriority = it->priority = readSelectorValue(_segMan, planeObject, SELECTOR(priority)); it->lastPriority = planePriority; - if (planePriority == 0xffff) { // Plane currently not meant to be shown + if (planePriority < 0) { // Plane currently not meant to be shown // If plane was shown before, delete plane rect if (planePriority != planeLastPriority) _paint32->fillRect(it->planeRect, 0); diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index ecaf450d89..5fd2824224 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -40,8 +40,8 @@ typedef Common::List PlaneLineList; struct PlaneEntry { reg_t object; - uint16 priority; - uint16 lastPriority; + int16 priority; + int16 lastPriority; int16 planeOffsetX; int16 planeOffsetY; GuiResourceId pictureId; -- cgit v1.2.3 From bd281928cb6e87cfb7175189cafd2b25991f3e01 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 24 Jul 2012 03:53:44 +0300 Subject: SCI: Initial implementation of kRemapColors(kRemapByPercent) Fixes some graphics glitches in the QFG4 demo and the menus of QFG4, by implementing one of the transparency effects used mainly in SCI32. Many thanks to fuzzie for her debugging info on QFG4 demo and to wjp for his great help on the dissassembly --- engines/sci/graphics/palette.cpp | 23 +++++++++++++++++++++++ engines/sci/graphics/palette.h | 9 +++++++++ engines/sci/graphics/view.cpp | 10 ++++++++-- 3 files changed, 40 insertions(+), 2 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index ea154c5037..f16d607a29 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -100,6 +100,9 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen) default: error("GfxPalette: Unknown view type"); } + + _remapOn = false; + _remappingPercent = 0; } GfxPalette::~GfxPalette() { @@ -329,6 +332,26 @@ void GfxPalette::set(Palette *newPalette, bool force, bool forceRealMerge) { } } +bool GfxPalette::isRemapColor(byte color) { + // TODO: Expand this for SCI32 (more than one remap color can be set). + // Now, it is assumed that colors 253 and 254 are the remap colors. + return _remapOn && (color == 253 || color == 254); +} + +byte GfxPalette::remapColor(byte color) { + assert(_remapOn); + + // TODO: Change this to use a table instead, like the original. + if (_remappingPercent) { + byte r = _sysPalette.colors[color].r * _remappingPercent / 100; + byte g = _sysPalette.colors[color].g * _remappingPercent / 100; + byte b = _sysPalette.colors[color].b * _remappingPercent / 100; + return kernelFindColor(r, g, b); + } else { + return color; + } +} + bool GfxPalette::insert(Palette *newPalette, Palette *destPalette) { bool paletteChanged = false; diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index a9ea1c32de..5b9ae9e016 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -53,6 +53,11 @@ public: void getSys(Palette *pal); uint16 getTotalColorCount() const { return _totalScreenColors; } + void toggleRemap(bool remap) { _remapOn = remap; } + void setRemappingPercent(uint16 percent) { _remappingPercent = percent; } + bool isRemapColor(byte color); + byte remapColor(byte color); + void setOnScreen(); void copySysPaletteToScreen(); @@ -123,6 +128,10 @@ private: int _palVarySignal; uint16 _totalScreenColors; + bool _remapOn; + uint16 _remappingBaseR, _remappingBaseG, _remappingBaseB; + uint16 _remappingPercent; + void loadMacIconBarPalette(); byte *_macClut; diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index 4e5c4da8b2..ae135d141c 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -741,8 +741,14 @@ void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const const int x2 = clipRectTranslated.left + x; const int y2 = clipRectTranslated.top + y; if (!upscaledHires) { - if (priority >= _screen->getPriority(x2, y2)) - _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0); + if (priority >= _screen->getPriority(x2, y2)) { + if (!_palette->isRemapColor(palette->mapping[color])) { + _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0); + } else { + byte remappedColor = _palette->remapColor(_screen->getVisual(x2, y2)); + _screen->putPixel(x2, y2, drawMask, remappedColor, priority, 0); + } + } } else { // UpscaledHires means view is hires and is supposed to // get drawn onto lowres screen. -- cgit v1.2.3 From 3d395545cb1514ba4a07a785e58782462a3b1a94 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 24 Jul 2012 04:07:08 +0300 Subject: SCI: Remove unused variables --- engines/sci/graphics/palette.h | 1 - 1 file changed, 1 deletion(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 5b9ae9e016..6774094810 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -129,7 +129,6 @@ private: uint16 _totalScreenColors; bool _remapOn; - uint16 _remappingBaseR, _remappingBaseG, _remappingBaseB; uint16 _remappingPercent; void loadMacIconBarPalette(); -- cgit v1.2.3 From 6f351302040be620aa039a7c605f3c23463b27db Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 24 Jul 2012 22:34:03 +0300 Subject: SCI: More work on color remapping More transparency/color mapping effects are now working (e.g. the flashlight at the Gedde tomb in GK1, the rays of light at Schloss Ritter in GK1, the torch in the QFG4 demo and the shadows in QFG4, PQ4 and KQ7) --- engines/sci/graphics/palette.cpp | 64 ++++++++++++++++++++++++++++++++-------- engines/sci/graphics/palette.h | 12 +++++--- engines/sci/graphics/view.cpp | 9 ++++-- 3 files changed, 66 insertions(+), 19 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index f16d607a29..b5154ef860 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -102,7 +102,7 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen) } _remapOn = false; - _remappingPercent = 0; + resetRemapping(); } GfxPalette::~GfxPalette() { @@ -332,24 +332,62 @@ void GfxPalette::set(Palette *newPalette, bool force, bool forceRealMerge) { } } -bool GfxPalette::isRemapColor(byte color) { - // TODO: Expand this for SCI32 (more than one remap color can be set). - // Now, it is assumed that colors 253 and 254 are the remap colors. - return _remapOn && (color == 253 || color == 254); +bool GfxPalette::isRemapMask(byte color) { + return (_remapOn && (color >= _remappingMaskFrom && color <= _remappingMaskTo)); +} + +void GfxPalette::resetRemapping() { + _remappingMaskFrom = 0; + _remappingMaskTo = 0; + _remappingPercentToSet = 0; + + for (int i = 0; i < 256; i++) { + _remappingTable[i] = i; + } +} + +void GfxPalette::setRemappingPercent(byte color, byte percent) { + // We need to defer the setup of the remapping table until something is + // shown on screen, otherwise kernelFindColor() won't find correct + // colors. The actual setup of the remapping table will be performed in + // remapColor(). + _remappingPercentToSet = percent; + + if (_remappingMaskFrom > color || _remappingMaskFrom == 0) + _remappingMaskFrom = color; + if (_remappingMaskTo < color) + _remappingMaskTo = color; +} + +void GfxPalette::setRemappingRange(byte color, byte from, byte to, byte base) { + for (int i = from; i <= to; i++) { + _remappingTable[i] = i + base; + } + + if (_remappingMaskFrom > color || _remappingMaskFrom == 0) + _remappingMaskFrom = color; + if (_remappingMaskTo < color) + _remappingMaskTo = color; } byte GfxPalette::remapColor(byte color) { assert(_remapOn); - // TODO: Change this to use a table instead, like the original. - if (_remappingPercent) { - byte r = _sysPalette.colors[color].r * _remappingPercent / 100; - byte g = _sysPalette.colors[color].g * _remappingPercent / 100; - byte b = _sysPalette.colors[color].b * _remappingPercent / 100; - return kernelFindColor(r, g, b); - } else { - return color; + // Check if we need to set remapping by percent. This can only be + // performed when something is shown on screen, so that the screen + // palette is set up and kernelFindColor() can work correctly. + if (_remappingPercentToSet) { + for (int i = 0; i < 256; i++) { + byte r = _sysPalette.colors[i].r * _remappingPercentToSet / 100; + byte g = _sysPalette.colors[i].g * _remappingPercentToSet / 100; + byte b = _sysPalette.colors[i].b * _remappingPercentToSet / 100; + _remappingTable[i] = kernelFindColor(r, g, b); + } + + _remappingPercentToSet = 0; } + + return _remappingTable[color]; } bool GfxPalette::insert(Palette *newPalette, Palette *destPalette) { diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 6774094810..372f3c7090 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -53,9 +53,11 @@ public: void getSys(Palette *pal); uint16 getTotalColorCount() const { return _totalScreenColors; } - void toggleRemap(bool remap) { _remapOn = remap; } - void setRemappingPercent(uint16 percent) { _remappingPercent = percent; } - bool isRemapColor(byte color); + void toggleRemapping(bool remap) { _remapOn = remap; } + void resetRemapping(); + void setRemappingPercent(byte color, byte percent); + void setRemappingRange(byte color, byte from, byte to, byte base); + bool isRemapMask(byte color); byte remapColor(byte color); void setOnScreen(); @@ -129,7 +131,9 @@ private: uint16 _totalScreenColors; bool _remapOn; - uint16 _remappingPercent; + byte _remappingTable[256]; + uint16 _remappingMaskFrom, _remappingMaskTo; + uint16 _remappingPercentToSet; void loadMacIconBarPalette(); byte *_macClut; diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index ae135d141c..f68ed1443a 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -742,7 +742,7 @@ void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const const int y2 = clipRectTranslated.top + y; if (!upscaledHires) { if (priority >= _screen->getPriority(x2, y2)) { - if (!_palette->isRemapColor(palette->mapping[color])) { + if (!_palette->isRemapMask(palette->mapping[color])) { _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0); } else { byte remappedColor = _palette->remapColor(_screen->getVisual(x2, y2)); @@ -857,7 +857,12 @@ void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect, const int x2 = clipRectTranslated.left + x; const int y2 = clipRectTranslated.top + y; if (color != clearKey && priority >= _screen->getPriority(x2, y2)) { - _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0); + if (!_palette->isRemapMask(palette->mapping[color])) { + _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0); + } else { + byte remappedColor = _palette->remapColor(_screen->getVisual(x2, y2)); + _screen->putPixel(x2, y2, drawMask, remappedColor, priority, 0); + } } } } -- cgit v1.2.3 From fe3fb1873c60e7ed21c573e09030bd6d0a5018cb Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 24 Jul 2012 22:54:37 +0300 Subject: SCI: Cleanup of the palette remapping code --- engines/sci/graphics/palette.cpp | 5 +++++ engines/sci/graphics/palette.h | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index b5154ef860..5a551bab2c 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -337,6 +337,7 @@ bool GfxPalette::isRemapMask(byte color) { } void GfxPalette::resetRemapping() { + _remapOn = false; _remappingMaskFrom = 0; _remappingMaskTo = 0; _remappingPercentToSet = 0; @@ -347,6 +348,8 @@ void GfxPalette::resetRemapping() { } void GfxPalette::setRemappingPercent(byte color, byte percent) { + _remapOn = true; + // We need to defer the setup of the remapping table until something is // shown on screen, otherwise kernelFindColor() won't find correct // colors. The actual setup of the remapping table will be performed in @@ -360,6 +363,8 @@ void GfxPalette::setRemappingPercent(byte color, byte percent) { } void GfxPalette::setRemappingRange(byte color, byte from, byte to, byte base) { + _remapOn = true; + for (int i = from; i <= to; i++) { _remappingTable[i] = i + base; } diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 372f3c7090..134ade5e36 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -53,7 +53,6 @@ public: void getSys(Palette *pal); uint16 getTotalColorCount() const { return _totalScreenColors; } - void toggleRemapping(bool remap) { _remapOn = remap; } void resetRemapping(); void setRemappingPercent(byte color, byte percent); void setRemappingRange(byte color, byte from, byte to, byte base); -- cgit v1.2.3 From 37b209dac14bea6b8f08c3ee3f66e3d5772652bb Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 24 Jul 2012 22:55:34 +0300 Subject: SCI: Refresh remapping by percent whenever the screen palette changes --- engines/sci/graphics/palette.cpp | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 5a551bab2c..cb5c0fe614 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -350,10 +350,10 @@ void GfxPalette::resetRemapping() { void GfxPalette::setRemappingPercent(byte color, byte percent) { _remapOn = true; - // We need to defer the setup of the remapping table until something is - // shown on screen, otherwise kernelFindColor() won't find correct + // We need to defer the setup of the remapping table every time the screen + // palette is changed, so that kernelFindColor() can find the correct // colors. The actual setup of the remapping table will be performed in - // remapColor(). + // copySysPaletteToScreen(). _remappingPercentToSet = percent; if (_remappingMaskFrom > color || _remappingMaskFrom == 0) @@ -377,21 +377,6 @@ void GfxPalette::setRemappingRange(byte color, byte from, byte to, byte base) { byte GfxPalette::remapColor(byte color) { assert(_remapOn); - - // Check if we need to set remapping by percent. This can only be - // performed when something is shown on screen, so that the screen - // palette is set up and kernelFindColor() can work correctly. - if (_remappingPercentToSet) { - for (int i = 0; i < 256; i++) { - byte r = _sysPalette.colors[i].r * _remappingPercentToSet / 100; - byte g = _sysPalette.colors[i].g * _remappingPercentToSet / 100; - byte b = _sysPalette.colors[i].b * _remappingPercentToSet / 100; - _remappingTable[i] = kernelFindColor(r, g, b); - } - - _remappingPercentToSet = 0; - } - return _remappingTable[color]; } @@ -557,6 +542,16 @@ void GfxPalette::copySysPaletteToScreen() { } } + // Check if we need to reset remapping by percent with the new colors. + if (_remappingPercentToSet) { + for (int i = 0; i < 256; i++) { + byte r = _sysPalette.colors[i].r * _remappingPercentToSet / 100; + byte g = _sysPalette.colors[i].g * _remappingPercentToSet / 100; + byte b = _sysPalette.colors[i].b * _remappingPercentToSet / 100; + _remappingTable[i] = kernelFindColor(r, g, b); + } + } + g_system->getPaletteManager()->setPalette(bpal, 0, 256); } -- cgit v1.2.3 From 537b1969bf896ee4e72e9d042e4b7f41c921d38c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 25 Jul 2012 00:58:16 +0300 Subject: SCI: Rewrite the color remapping code to support simultaneous effects Fixes the torch in the full version of QFG4 --- engines/sci/graphics/palette.cpp | 43 ++++++++++++++++++++-------------------- engines/sci/graphics/palette.h | 17 ++++++++++++---- engines/sci/graphics/view.cpp | 8 ++++---- 3 files changed, 38 insertions(+), 30 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index cb5c0fe614..9b8618c0ef 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -143,8 +143,9 @@ void GfxPalette::createFromData(byte *data, int bytesLeft, Palette *paletteOut) memset(paletteOut, 0, sizeof(Palette)); // Setup 1:1 mapping - for (colorNo = 0; colorNo < 256; colorNo++) + for (colorNo = 0; colorNo < 256; colorNo++) { paletteOut->mapping[colorNo] = colorNo; + } if (bytesLeft < 37) { // This happens when loading palette of picture 0 in sq5 - the resource is broken and doesn't contain a full @@ -332,18 +333,26 @@ void GfxPalette::set(Palette *newPalette, bool force, bool forceRealMerge) { } } -bool GfxPalette::isRemapMask(byte color) { - return (_remapOn && (color >= _remappingMaskFrom && color <= _remappingMaskTo)); +byte GfxPalette::remapColor(byte remappedColor, byte screenColor) { + assert(_remapOn); + if (_remappingType[remappedColor] == kRemappingByRange) + return _remappingByRange[screenColor]; + else if (_remappingType[remappedColor] == kRemappingByPercent) + return _remappingByPercent[screenColor]; + else + error("remapColor(): Color %d isn't remapped", remappedColor); + + return 0; // should never reach here } void GfxPalette::resetRemapping() { _remapOn = false; - _remappingMaskFrom = 0; - _remappingMaskTo = 0; _remappingPercentToSet = 0; for (int i = 0; i < 256; i++) { - _remappingTable[i] = i; + _remappingType[i] = kRemappingNone; + _remappingByPercent[i] = i; + _remappingByRange[i] = i; } } @@ -356,28 +365,17 @@ void GfxPalette::setRemappingPercent(byte color, byte percent) { // copySysPaletteToScreen(). _remappingPercentToSet = percent; - if (_remappingMaskFrom > color || _remappingMaskFrom == 0) - _remappingMaskFrom = color; - if (_remappingMaskTo < color) - _remappingMaskTo = color; + _remappingType[color] = kRemappingByPercent; } void GfxPalette::setRemappingRange(byte color, byte from, byte to, byte base) { _remapOn = true; for (int i = from; i <= to; i++) { - _remappingTable[i] = i + base; + _remappingByRange[i] = i + base; } - if (_remappingMaskFrom > color || _remappingMaskFrom == 0) - _remappingMaskFrom = color; - if (_remappingMaskTo < color) - _remappingMaskTo = color; -} - -byte GfxPalette::remapColor(byte color) { - assert(_remapOn); - return _remappingTable[color]; + _remappingType[color] = kRemappingByRange; } bool GfxPalette::insert(Palette *newPalette, Palette *destPalette) { @@ -548,7 +546,7 @@ void GfxPalette::copySysPaletteToScreen() { byte r = _sysPalette.colors[i].r * _remappingPercentToSet / 100; byte g = _sysPalette.colors[i].g * _remappingPercentToSet / 100; byte b = _sysPalette.colors[i].b * _remappingPercentToSet / 100; - _remappingTable[i] = kernelFindColor(r, g, b); + _remappingByPercent[i] = kernelFindColor(r, g, b); } } @@ -1060,8 +1058,9 @@ bool GfxPalette::loadClut(uint16 clutId) { memset(&pal, 0, sizeof(Palette)); // Setup 1:1 mapping - for (int i = 0; i < 256; i++) + for (int i = 0; i < 256; i++) { pal.mapping[i] = i; + } // Now load in the palette for (int i = 1; i <= 236; i++) { diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 134ade5e36..9898315897 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -31,6 +31,12 @@ namespace Sci { class ResourceManager; class GfxScreen; +enum ColorRemappingType { + kRemappingNone = 0, + kRemappingByRange = 1, + kRemappingByPercent = 2 +}; + /** * Palette class, handles palette operations like changing intensity, setting up the palette, merging different palettes */ @@ -56,8 +62,10 @@ public: void resetRemapping(); void setRemappingPercent(byte color, byte percent); void setRemappingRange(byte color, byte from, byte to, byte base); - bool isRemapMask(byte color); - byte remapColor(byte color); + bool isRemapped(byte color) const { + return _remapOn && (_remappingType[color] != kRemappingNone); + } + byte remapColor(byte remappedColor, byte screenColor); void setOnScreen(); void copySysPaletteToScreen(); @@ -130,8 +138,9 @@ private: uint16 _totalScreenColors; bool _remapOn; - byte _remappingTable[256]; - uint16 _remappingMaskFrom, _remappingMaskTo; + ColorRemappingType _remappingType[256]; + byte _remappingByPercent[256]; + byte _remappingByRange[256]; uint16 _remappingPercentToSet; void loadMacIconBarPalette(); diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index f68ed1443a..36aaae9232 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -742,10 +742,10 @@ void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const const int y2 = clipRectTranslated.top + y; if (!upscaledHires) { if (priority >= _screen->getPriority(x2, y2)) { - if (!_palette->isRemapMask(palette->mapping[color])) { + if (!_palette->isRemapped(palette->mapping[color])) { _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0); } else { - byte remappedColor = _palette->remapColor(_screen->getVisual(x2, y2)); + byte remappedColor = _palette->remapColor(palette->mapping[color], _screen->getVisual(x2, y2)); _screen->putPixel(x2, y2, drawMask, remappedColor, priority, 0); } } @@ -857,10 +857,10 @@ void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect, const int x2 = clipRectTranslated.left + x; const int y2 = clipRectTranslated.top + y; if (color != clearKey && priority >= _screen->getPriority(x2, y2)) { - if (!_palette->isRemapMask(palette->mapping[color])) { + if (!_palette->isRemapped(palette->mapping[color])) { _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0); } else { - byte remappedColor = _palette->remapColor(_screen->getVisual(x2, y2)); + byte remappedColor = _palette->remapColor(palette->mapping[color], _screen->getVisual(x2, y2)); _screen->putPixel(x2, y2, drawMask, remappedColor, priority, 0); } } -- cgit v1.2.3 From 797dbfe506d5273c0385997401aa32524995df33 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 25 Jul 2012 01:16:13 +0300 Subject: SCI: Set the RemapByPercent palette initially This needs to be performed because the screen palette might not change after the call. Fixes the display of the bat in the character selection screen in the full version of QFG4 --- engines/sci/graphics/palette.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 9b8618c0ef..68104b0ac8 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -361,10 +361,17 @@ void GfxPalette::setRemappingPercent(byte color, byte percent) { // We need to defer the setup of the remapping table every time the screen // palette is changed, so that kernelFindColor() can find the correct - // colors. The actual setup of the remapping table will be performed in - // copySysPaletteToScreen(). + // colors. Set it once here, in case the palette stays the same and update + // it on each palette change by copySysPaletteToScreen(). _remappingPercentToSet = percent; + for (int i = 0; i < 256; i++) { + byte r = _sysPalette.colors[i].r * _remappingPercentToSet / 100; + byte g = _sysPalette.colors[i].g * _remappingPercentToSet / 100; + byte b = _sysPalette.colors[i].b * _remappingPercentToSet / 100; + _remappingByPercent[i] = kernelFindColor(r, g, b); + } + _remappingType[color] = kRemappingByPercent; } -- cgit v1.2.3 From dc8d9f4c9f7498f501b567262d0e90229b973e6e Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 25 Jul 2012 21:11:45 +0200 Subject: SCI: Fix delete[] formatting. --- engines/sci/graphics/font.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/font.cpp b/engines/sci/graphics/font.cpp index fcdd057509..30184cc091 100644 --- a/engines/sci/graphics/font.cpp +++ b/engines/sci/graphics/font.cpp @@ -54,7 +54,7 @@ GfxFontFromResource::GfxFontFromResource(ResourceManager *resMan, GfxScreen *scr } GfxFontFromResource::~GfxFontFromResource() { - delete []_chars; + delete[] _chars; _resMan->unlockResource(_resource); } -- cgit v1.2.3 From c0beaf2337bdadc8b18425c9a38182ba30910174 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 26 Jul 2012 11:05:50 +0300 Subject: SCI: Differentiate between screen width and pitch This properly addresses the odd screen width (630) in Phantasmagoria 1 --- engines/sci/graphics/frameout.cpp | 36 +++++++++++-------------- engines/sci/graphics/screen.cpp | 55 +++++++++++++++++++++------------------ engines/sci/graphics/screen.h | 1 + 3 files changed, 46 insertions(+), 46 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index fedae2eb6f..0098728e5d 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -125,23 +125,17 @@ void GfxFrameout::kernelAddPlane(reg_t object) { if (_planes.empty()) { // There has to be another way for sierra sci to do this or maybe script resolution is compiled into // interpreter (TODO) - uint16 tmpRunningWidth = readSelectorValue(_segMan, object, SELECTOR(resX)); - uint16 tmpRunningHeight = readSelectorValue(_segMan, object, SELECTOR(resY)); + uint16 scriptWidth = readSelectorValue(_segMan, object, SELECTOR(resX)); + uint16 scriptHeight = readSelectorValue(_segMan, object, SELECTOR(resY)); - // The above can be 0 in SCI3 (e.g. Phantasmagoria 2) - if (tmpRunningWidth == 0 && tmpRunningHeight == 0) { - tmpRunningWidth = 320; - tmpRunningHeight = 200; - } - - // HACK: Phantasmagoria 1 sets a window size of 630x450. - // We can't set a width of 630, as that messes up the pitch, so we hack - // the internal script width here - if (g_sci->getGameId() == GID_PHANTASMAGORIA) { - tmpRunningWidth = 325; + // Phantasmagoria 2 doesn't specify a script width/height + if (g_sci->getGameId() == GID_PHANTASMAGORIA2) { + scriptWidth = 640; + scriptHeight = 480; } - _coordAdjuster->setScriptsResolution(tmpRunningWidth, tmpRunningHeight); + assert(scriptWidth > 0 && scriptHeight > 0); + _coordAdjuster->setScriptsResolution(scriptWidth, scriptHeight); } // Import of QfG character files dialog is shown in QFG4. @@ -704,13 +698,13 @@ void GfxFrameout::kernelFrameout() { // 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 (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); + 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 diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 3030fb4386..246b6bfff9 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -53,23 +53,35 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { #ifdef ENABLE_SCI32 // GK1 Mac uses a 640x480 resolution too - if (g_sci->getGameId() == GID_GK1 && g_sci->getPlatform() == Common::kPlatformMacintosh) - _upscaledHires = GFX_SCREEN_UPSCALED_640x480; + if (g_sci->getPlatform() == Common::kPlatformMacintosh) { + if (g_sci->getGameId() == GID_GK1) + _upscaledHires = GFX_SCREEN_UPSCALED_640x480; + } #endif if (_resMan->detectHires()) { _width = 640; + _pitch = 640; _height = 480; } else { _width = 320; + _pitch = 320; _height = getLowResScreenHeight(); } +#ifdef ENABLE_SCI32 + // Phantasmagoria 1 sets a window area of 630x450 + if (g_sci->getGameId() == GID_PHANTASMAGORIA) { + _width = 630; + _height = 450; + } +#endif + // Japanese versions of games use hi-res font on upscaled version of the game. if ((g_sci->getLanguage() == Common::JA_JPN) && (getSciVersion() <= SCI_VERSION_1_1)) _upscaledHires = GFX_SCREEN_UPSCALED_640x400; - _pixels = _width * _height; + _pixels = _pitch * _height; switch (_upscaledHires) { case GFX_SCREEN_UPSCALED_640x400: @@ -91,19 +103,12 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { _upscaledMapping[i] = (i * 12) / 5; break; default: - _displayWidth = _width; + _displayWidth = _pitch; _displayHeight = _height; memset(&_upscaledMapping, 0, sizeof(_upscaledMapping) ); break; } - // Phantasmagoria 1 sets a window area of 630x450 - if (g_sci->getGameId() == GID_PHANTASMAGORIA) { - // TODO: Also set width to 630 (can't be set right now, as it messes up - // the pitch). For now, a hack has been placed in GfxFrameout::kernelAddPlane() - _height = 450; - } - _displayPixels = _displayWidth * _displayHeight; _visualScreen = (byte *)calloc(_pixels, 1); _priorityScreen = (byte *)calloc(_pixels, 1); @@ -214,7 +219,7 @@ byte GfxScreen::getDrawingMask(byte color, byte prio, byte control) { } void GfxScreen::putPixel(int x, int y, byte drawMask, byte color, byte priority, byte control) { - int offset = y * _width + x; + int offset = y * _pitch + x; if (drawMask & GFX_SCREEN_MASK_VISUAL) { _visualScreen[offset] = color; @@ -247,7 +252,7 @@ void GfxScreen::putFontPixel(int startingY, int x, int y, byte color) { // Do not scale ourselves, but put it on the display directly putPixelOnDisplay(x, y + startingY, color); } else { - int offset = (startingY + y) * _width + x; + int offset = (startingY + y) * _pitch + x; _visualScreen[offset] = color; if (!_upscaledHires) { @@ -349,19 +354,19 @@ void GfxScreen::putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, u } byte GfxScreen::getVisual(int x, int y) { - return _visualScreen[y * _width + x]; + return _visualScreen[y * _pitch + x]; } byte GfxScreen::getPriority(int x, int y) { - return _priorityScreen[y * _width + x]; + return _priorityScreen[y * _pitch + x]; } byte GfxScreen::getControl(int x, int y) { - return _controlScreen[y * _width + x]; + return _controlScreen[y * _pitch + x]; } byte GfxScreen::isFillMatch(int16 x, int16 y, byte screenMask, byte t_color, byte t_pri, byte t_con, bool isEGA) { - int offset = y * _width + x; + int offset = y * _pitch + x; byte match = 0; if (screenMask & GFX_SCREEN_MASK_VISUAL) { @@ -422,14 +427,14 @@ void GfxScreen::bitsSave(Common::Rect rect, byte mask, byte *memoryPtr) { memcpy(memoryPtr, (void *)&mask, sizeof(mask)); memoryPtr += sizeof(mask); if (mask & GFX_SCREEN_MASK_VISUAL) { - bitsSaveScreen(rect, _visualScreen, _width, memoryPtr); + bitsSaveScreen(rect, _visualScreen, _pitch, memoryPtr); bitsSaveDisplayScreen(rect, memoryPtr); } if (mask & GFX_SCREEN_MASK_PRIORITY) { - bitsSaveScreen(rect, _priorityScreen, _width, memoryPtr); + bitsSaveScreen(rect, _priorityScreen, _pitch, memoryPtr); } if (mask & GFX_SCREEN_MASK_CONTROL) { - bitsSaveScreen(rect, _controlScreen, _width, memoryPtr); + bitsSaveScreen(rect, _controlScreen, _pitch, memoryPtr); } if (mask & GFX_SCREEN_MASK_DISPLAY) { if (!_upscaledHires) @@ -482,14 +487,14 @@ void GfxScreen::bitsRestore(byte *memoryPtr) { memcpy((void *)&mask, memoryPtr, sizeof(mask)); memoryPtr += sizeof(mask); if (mask & GFX_SCREEN_MASK_VISUAL) { - bitsRestoreScreen(rect, memoryPtr, _visualScreen, _width); + bitsRestoreScreen(rect, memoryPtr, _visualScreen, _pitch); bitsRestoreDisplayScreen(rect, memoryPtr); } if (mask & GFX_SCREEN_MASK_PRIORITY) { - bitsRestoreScreen(rect, memoryPtr, _priorityScreen, _width); + bitsRestoreScreen(rect, memoryPtr, _priorityScreen, _pitch); } if (mask & GFX_SCREEN_MASK_CONTROL) { - bitsRestoreScreen(rect, memoryPtr, _controlScreen, _width); + bitsRestoreScreen(rect, memoryPtr, _controlScreen, _pitch); } if (mask & GFX_SCREEN_MASK_DISPLAY) { if (!_upscaledHires) @@ -567,7 +572,7 @@ void GfxScreen::dither(bool addToFlag) { if (!_unditheringEnabled) { // Do dithering on visual and display-screen for (y = 0; y < _height; y++) { - for (x = 0; x < _width; x++) { + for (x = 0; x < _pitch; x++) { color = *visualPtr; if (color & 0xF0) { color ^= color << 4; @@ -592,7 +597,7 @@ void GfxScreen::dither(bool addToFlag) { memset(&_ditheredPicColors, 0, sizeof(_ditheredPicColors)); // Do dithering on visual screen and put decoded but undithered byte onto display-screen for (y = 0; y < _height; y++) { - for (x = 0; x < _width; x++) { + for (x = 0; x < _pitch; x++) { color = *visualPtr; if (color & 0xF0) { color ^= color << 4; diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h index 73ea596ba1..01fb899edb 100644 --- a/engines/sci/graphics/screen.h +++ b/engines/sci/graphics/screen.h @@ -132,6 +132,7 @@ public: private: uint16 _width; + uint16 _pitch; uint16 _height; uint _pixels; uint16 _displayWidth; -- cgit v1.2.3 From fb35c7f46f986a22235638e2946ba8492e735109 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 16 Aug 2012 13:30:32 -0400 Subject: VIDEO: Remove setSystemPalette() --- engines/sci/graphics/frameout.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index fedae2eb6f..0056f6c78b 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -28,6 +28,7 @@ #include "common/system.h" #include "common/textconsole.h" #include "engines/engine.h" +#include "graphics/palette.h" #include "graphics/surface.h" #include "sci/sci.h" @@ -494,7 +495,7 @@ void GfxFrameout::showVideo() { uint16 y = videoDecoder->getPos().y; if (videoDecoder->hasDirtyPalette()) - videoDecoder->setSystemPalette(); + g_system->getPaletteManager()->setPalette(videoDecoder->getPalette(), 0, 256); while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) { if (videoDecoder->needsUpdate()) { @@ -503,7 +504,7 @@ void GfxFrameout::showVideo() { g_system->copyRectToScreen(frame->pixels, frame->pitch, x, y, frame->w, frame->h); if (videoDecoder->hasDirtyPalette()) - videoDecoder->setSystemPalette(); + g_system->getPaletteManager()->setPalette(videoDecoder->getPalette(), 0, 256); g_system->updateScreen(); } -- cgit v1.2.3 From 7d436622a8e10437488f6dfa930e3ff15e254a55 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 21 Aug 2012 03:31:00 +0300 Subject: SCI: More work on kRemapColors This implements some more color remap-based palette effects, found in QFG4 --- engines/sci/graphics/palette.cpp | 21 +++++++++++++++++++++ engines/sci/graphics/palette.h | 1 + 2 files changed, 22 insertions(+) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 68104b0ac8..53d69cdcca 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -375,6 +375,27 @@ void GfxPalette::setRemappingPercent(byte color, byte percent) { _remappingType[color] = kRemappingByPercent; } +void GfxPalette::setRemappingPercentGray(byte color, byte percent) { + _remapOn = true; + + // We need to defer the setup of the remapping table every time the screen + // palette is changed, so that kernelFindColor() can find the correct + // colors. Set it once here, in case the palette stays the same and update + // it on each palette change by copySysPaletteToScreen(). + _remappingPercentToSet = percent; + + // Note: This is not what the original does, but the results are the same visually + for (int i = 0; i < 256; i++) { + byte rComponent = _sysPalette.colors[i].r * _remappingPercentToSet * 0.30 / 100; + byte gComponent = _sysPalette.colors[i].g * _remappingPercentToSet * 0.59 / 100; + byte bComponent = _sysPalette.colors[i].b * _remappingPercentToSet * 0.11 / 100; + byte luminosity = rComponent + gComponent + bComponent; + _remappingByPercent[i] = kernelFindColor(luminosity, luminosity, luminosity); + } + + _remappingType[color] = kRemappingByPercent; +} + void GfxPalette::setRemappingRange(byte color, byte from, byte to, byte base) { _remapOn = true; diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 9898315897..e974781d49 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -61,6 +61,7 @@ public: void resetRemapping(); void setRemappingPercent(byte color, byte percent); + void setRemappingPercentGray(byte color, byte percent); void setRemappingRange(byte color, byte from, byte to, byte base); bool isRemapped(byte color) const { return _remapOn && (_remappingType[color] != kRemappingNone); -- cgit v1.2.3 From a391599403faf864f1583ababdba577fb6393afd Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 21 Aug 2012 11:55:21 +0300 Subject: SCI: Update a comment --- engines/sci/graphics/frameout.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines/sci/graphics') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 0098728e5d..6628247127 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -728,7 +728,9 @@ void GfxFrameout::kernelFrameout() { g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect); } - // FIXME: When does this happen, and why? + // Don't attempt to draw sprites that are outside the visible + // screen area. An example is the random people walking in + // Jackson Square in GK1. if (itemEntry->celRect.bottom < 0 || itemEntry->celRect.top >= _screen->getDisplayHeight() || itemEntry->celRect.right < 0 || itemEntry->celRect.left >= _screen->getDisplayWidth()) continue; -- cgit v1.2.3