diff options
-rw-r--r-- | engines/sci/graphics/cursor.cpp | 8 | ||||
-rw-r--r-- | engines/sci/graphics/font.cpp | 8 | ||||
-rw-r--r-- | engines/sci/graphics/font.h | 4 | ||||
-rw-r--r-- | engines/sci/graphics/picture.cpp | 84 | ||||
-rw-r--r-- | engines/sci/graphics/ports.cpp | 16 | ||||
-rw-r--r-- | engines/sci/graphics/screen.cpp | 385 | ||||
-rw-r--r-- | engines/sci/graphics/screen.h | 94 | ||||
-rw-r--r-- | engines/sci/graphics/transitions.cpp | 6 |
8 files changed, 412 insertions, 193 deletions
diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 048ec1e9b9..1a58de073c 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -47,7 +47,7 @@ GfxCursor::GfxCursor(ResourceManager *resMan, GfxPalette *palette, GfxScreen *sc _isVisible = true; // center mouse cursor - setPosition(Common::Point(_screen->getWidth() / 2, _screen->getHeight() / 2)); + setPosition(Common::Point(_screen->getScriptWidth() / 2, _screen->getScriptHeight() / 2)); _moveZoneActive = false; _zoomZoneActive = false; @@ -151,14 +151,14 @@ void GfxCursor::kernelSetShape(GuiResourceId resourceId) { colorMapping[0] = 0; // Black is hardcoded colorMapping[1] = _screen->getColorWhite(); // White is also hardcoded colorMapping[2] = SCI_CURSOR_SCI0_TRANSPARENCYCOLOR; - colorMapping[3] = _palette->matchColor(170, 170, 170); // Grey + colorMapping[3] = _palette->matchColor(170, 170, 170) & SCI_PALETTE_MATCH_COLORMASK; // Grey // 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 + colorMapping[3] = _palette->matchColor(223, 223, 223) & SCI_PALETTE_MATCH_COLORMASK; // Light Grey // Seek to actual data resourceData += 4; @@ -481,7 +481,7 @@ void GfxCursor::kernelSetPos(Common::Point pos) { void GfxCursor::kernelMoveCursor(Common::Point pos) { _coordAdjuster->moveCursor(pos); - if (pos.x > _screen->getWidth() || pos.y > _screen->getHeight()) { + if (pos.x > _screen->getScriptWidth() || pos.y > _screen->getScriptHeight()) { warning("attempt to place cursor at invalid coordinates (%d, %d)", pos.y, pos.x); return; } diff --git a/engines/sci/graphics/font.cpp b/engines/sci/graphics/font.cpp index e4684ff134..2268ec0459 100644 --- a/engines/sci/graphics/font.cpp +++ b/engines/sci/graphics/font.cpp @@ -48,8 +48,8 @@ GfxFontFromResource::GfxFontFromResource(ResourceManager *resMan, GfxScreen *scr // filling info for every char for (int16 i = 0; i < _numChars; i++) { _chars[i].offset = READ_SCI32ENDIAN_UINT16(_resourceData + 6 + i * 2); - _chars[i].w = _resourceData[_chars[i].offset]; - _chars[i].h = _resourceData[_chars[i].offset + 1]; + _chars[i].width = _resourceData[_chars[i].offset]; + _chars[i].height = _resourceData[_chars[i].offset + 1]; } } @@ -66,10 +66,10 @@ byte GfxFontFromResource::getHeight() { return _fontHeight; } byte GfxFontFromResource::getCharWidth(uint16 chr) { - return chr < _numChars ? _chars[chr].w : 0; + return chr < _numChars ? _chars[chr].width : 0; } byte GfxFontFromResource::getCharHeight(uint16 chr) { - return chr < _numChars ? _chars[chr].h : 0; + return chr < _numChars ? _chars[chr].height : 0; } byte *GfxFontFromResource::getCharData(uint16 chr) { return chr < _numChars ? _resourceData + _chars[chr].offset + 2 : 0; diff --git a/engines/sci/graphics/font.h b/engines/sci/graphics/font.h index 58b2ba4813..451261f315 100644 --- a/engines/sci/graphics/font.h +++ b/engines/sci/graphics/font.h @@ -71,9 +71,11 @@ private: byte *_resourceData; struct Charinfo { - byte w, h; + byte width; + byte height; int16 offset; }; + byte _fontHeight; uint16 _numChars; Charinfo *_chars; diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp index d751f9738f..d7ef84dc1e 100644 --- a/engines/sci/graphics/picture.cpp +++ b/engines/sci/graphics/picture.cpp @@ -88,10 +88,13 @@ void GfxPicture::draw(int16 animationNr, bool mirroredFlag, bool addToFlag, int1 } void GfxPicture::reset() { + int16 startY = _ports->getPort()->top; + int16 startX = 0; int16 x, y; - for (y = _ports->getPort()->top; y < _screen->getHeight(); y++) { - for (x = 0; x < _screen->getWidth(); x++) { - _screen->putPixel(x, y, GFX_SCREEN_MASK_ALL, 255, 0, 0); + _screen->vectorAdjustCoordinate(&startX, &startY); + for (y = startY; y < _screen->getHeight(); y++) { + for (x = startX; x < _screen->getWidth(); x++) { + _screen->vectorPutPixel(x, y, GFX_SCREEN_MASK_ALL, 255, 0, 0); } } } @@ -482,6 +485,8 @@ enum { PIC_OPX_VGA_PRIORITY_TABLE_EXPLICIT = 4 }; +//#define DEBUG_PICTURE_DRAW 1 + #ifdef DEBUG_PICTURE_DRAW const char *picOpcodeNames[] = { "Set color", @@ -589,6 +594,9 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) { while (curPos < dataSize) { #ifdef DEBUG_PICTURE_DRAW debug("Picture op: %X (%s) at %d", data[curPos], picOpcodeNames[data[curPos] - 0xF0], curPos); + _screen->copyToScreen(); + g_system->updateScreen(); + g_system->delayMillis(400); #endif switch (pic_op = data[curPos++]) { case PIC_OP_SET_COLOR: @@ -934,17 +942,17 @@ void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, by Common::Point p, p1; byte screenMask = _screen->getDrawingMask(color, priority, control); byte matchedMask, matchMask; - int16 w, e, a_set, b_set; bool isEGA = (_resMan->getViewType() == kViewEga); p.x = x + curPort->left; p.y = y + curPort->top; - stack.push(p); - byte searchColor = _screen->getVisual(p.x, p.y); - byte searchPriority = _screen->getPriority(p.x, p.y); - byte searchControl = _screen->getControl(p.x, p.y); + _screen->vectorAdjustCoordinate(&p.x, &p.y); + + byte searchColor = _screen->vectorGetVisual(p.x, p.y); + byte searchPriority = _screen->vectorGetPriority(p.x, p.y); + byte searchControl = _screen->vectorGetControl(p.x, p.y); if (isEGA) { // In EGA games a pixel in the framebuffer is only 4 bits. We store @@ -991,22 +999,31 @@ void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, by } // hard borders for filling - int l = curPort->rect.left + curPort->left; - int t = curPort->rect.top + curPort->top; - int r = curPort->rect.right + curPort->left - 1; - int b = curPort->rect.bottom + curPort->top - 1; + int16 borderLeft = curPort->rect.left + curPort->left; + int16 borderTop = curPort->rect.top + curPort->top; + int16 borderRight = curPort->rect.right + curPort->left - 1; + int16 borderBottom = curPort->rect.bottom + curPort->top - 1; + int16 curToLeft, curToRight, a_set, b_set; + + // Translate coordinates, if required (needed for Macintosh 480x300) + _screen->vectorAdjustCoordinate(&borderLeft, &borderTop); + _screen->vectorAdjustCoordinate(&borderRight, &borderBottom); + //return; + + stack.push(p); + while (stack.size()) { p = stack.pop(); - if ((matchedMask = _screen->isFillMatch(p.x, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA)) == 0) // already filled + if ((matchedMask = _screen->vectorIsFillMatch(p.x, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA)) == 0) // already filled continue; - _screen->putPixel(p.x, p.y, screenMask, color, priority, control); - w = p.x; - e = p.x; + _screen->vectorPutPixel(p.x, p.y, screenMask, color, priority, control); + curToLeft = p.x; + curToRight = p.x; // moving west and east pointers as long as there is a matching color to fill - while (w > l && (matchedMask = _screen->isFillMatch(w - 1, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA))) - _screen->putPixel(--w, p.y, screenMask, color, priority, control); - while (e < r && (matchedMask = _screen->isFillMatch(e + 1, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA))) - _screen->putPixel(++e, p.y, screenMask, color, priority, control); + while (curToLeft > borderLeft && (matchedMask = _screen->vectorIsFillMatch(curToLeft - 1, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA))) + _screen->vectorPutPixel(--curToLeft, p.y, screenMask, color, priority, control); + while (curToRight < borderRight && (matchedMask = _screen->vectorIsFillMatch(curToRight + 1, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA))) + _screen->vectorPutPixel(++curToRight, p.y, screenMask, color, priority, control); #if 0 // debug code for floodfill _screen->copyToScreen(); @@ -1015,10 +1032,10 @@ void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, by #endif // checking lines above and below for possible flood targets a_set = b_set = 0; - while (w <= e) { - if (p.y > t && (matchedMask = _screen->isFillMatch(w, p.y - 1, matchMask, searchColor, searchPriority, searchControl, isEGA))) { // one line above + while (curToLeft <= curToRight) { + if (p.y > borderTop && (matchedMask = _screen->vectorIsFillMatch(curToLeft, p.y - 1, matchMask, searchColor, searchPriority, searchControl, isEGA))) { // one line above if (a_set == 0) { - p1.x = w; + p1.x = curToLeft; p1.y = p.y - 1; stack.push(p1); a_set = 1; @@ -1026,16 +1043,16 @@ void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, by } else a_set = 0; - if (p.y < b && (matchedMask = _screen->isFillMatch(w, p.y + 1, matchMask, searchColor, searchPriority, searchControl, isEGA))) { // one line below + if (p.y < borderBottom && (matchedMask = _screen->vectorIsFillMatch(curToLeft, p.y + 1, matchMask, searchColor, searchPriority, searchControl, isEGA))) { // one line below if (b_set == 0) { - p1.x = w; + p1.x = curToLeft; p1.y = p.y + 1; stack.push(p1); b_set = 1; } } else b_set = 0; - w++; + curToLeft++; } } } @@ -1173,7 +1190,7 @@ void GfxPicture::vectorPatternBox(Common::Rect box, byte color, byte prio, byte for (y = box.top; y < box.bottom; y++) { for (x = box.left; x < box.right; x++) { - _screen->putPixel(x, y, flag, color, prio, control); + _screen->vectorPutPixel(x, y, flag, color, prio, control); } } } @@ -1186,7 +1203,7 @@ void GfxPicture::vectorPatternTexturedBox(Common::Rect box, byte color, byte pri for (y = box.top; y < box.bottom; y++) { for (x = box.left; x < box.right; x++) { if (*textureData) { - _screen->putPixel(x, y, flag, color, prio, control); + _screen->vectorPutPixel(x, y, flag, color, prio, control); } textureData++; } @@ -1203,7 +1220,7 @@ void GfxPicture::vectorPatternCircle(Common::Rect box, byte size, byte color, by for (y = box.top; y < box.bottom; y++) { for (x = box.left; x < box.right; x++) { if (bitmap & 1) { - _screen->putPixel(x, y, flag, color, prio, control); + _screen->vectorPutPixel(x, y, flag, color, prio, control); } bitNo++; if (bitNo == 8) { @@ -1222,12 +1239,12 @@ void GfxPicture::vectorPatternTexturedCircle(Common::Rect box, byte size, byte c byte bitNo = 0; const bool *textureData = &vectorPatternTextures[vectorPatternTextureOffset[texture]]; int y, x; - + for (y = box.top; y < box.bottom; y++) { for (x = box.left; x < box.right; x++) { if (bitmap & 1) { if (*textureData) { - _screen->putPixel(x, y, flag, color, prio, control); + _screen->vectorPutPixel(x, y, flag, color, prio, control); } textureData++; } @@ -1252,7 +1269,10 @@ void GfxPicture::vectorPattern(int16 x, int16 y, byte color, byte priority, byte rect.top = y; rect.left = x; rect.setHeight((size*2)+1); rect.setWidth((size*2)+2); _ports->offsetRect(rect); - rect.clip(_screen->getWidth(), _screen->getHeight()); + rect.clip(_screen->getScriptWidth(), _screen->getScriptHeight()); + + _screen->vectorAdjustCoordinate(&rect.left, &rect.top); + _screen->vectorAdjustCoordinate(&rect.right, &rect.bottom); if (code & SCI_PATTERN_CODE_RECTANGLE) { // Rectangle diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index 56c63a7b12..bcc991081e 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -63,10 +63,10 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te openPort(_menuPort); setPort(_menuPort); _text16->SetFont(0); - _menuPort->rect = Common::Rect(0, 0, _screen->getWidth(), _screen->getHeight()); - _menuBarRect = Common::Rect(0, 0, _screen->getWidth(), 9); - _menuRect = Common::Rect(0, 0, _screen->getWidth(), 10); - _menuLine = Common::Rect(0, 9, _screen->getWidth(), 10); + _menuPort->rect = Common::Rect(0, 0, _screen->getScriptWidth(), _screen->getScriptHeight()); + _menuBarRect = Common::Rect(0, 0, _screen->getScriptWidth(), 9); + _menuRect = Common::Rect(0, 0, _screen->getScriptWidth(), 10); + _menuLine = Common::Rect(0, 9, _screen->getScriptWidth(), 10); _wmgrPort = new Port(1); _windowsById.resize(2); @@ -122,13 +122,13 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te } else { _wmgrPort->rect.bottom = _screen->getHeight(); } - _wmgrPort->rect.right = _screen->getWidth(); + _wmgrPort->rect.right = _screen->getScriptWidth(); _wmgrPort->rect.moveTo(0, 0); _wmgrPort->curTop = 0; _wmgrPort->curLeft = 0; _windowList.push_front(_wmgrPort); - _picWind = addWindow(Common::Rect(0, offTop, _screen->getWidth(), _screen->getHeight()), 0, 0, SCI_WINDOWMGR_STYLE_TRANSPARENT | SCI_WINDOWMGR_STYLE_NOFRAME, 0, true); + _picWind = addWindow(Common::Rect(0, offTop, _screen->getScriptWidth(), _screen->getScriptHeight()), 0, 0, SCI_WINDOWMGR_STYLE_TRANSPARENT | SCI_WINDOWMGR_STYLE_NOFRAME, 0, true); // For SCI0 games till kq4 (.502 - not including) we set _picWind top to offTop instead // Because of the menu/status bar if (_usesOldGfxFunctions) @@ -321,13 +321,13 @@ Window *GfxPorts::addWindow(const Common::Rect &dims, const Common::Rect *restor // their interpreter even in the newer VGA games. r.left = r.left & 0xFFFE; - if (r.width() > _screen->getWidth()) { + if (r.width() > _screen->getScriptWidth()) { // We get invalid dimensions at least at the end of sq3 (script bug!). // Same happens very often in lsl5, sierra sci didnt fix it but it looked awful. // Also happens frequently in the demo of GK1. warning("Fixing too large window, left: %d, right: %d", dims.left, dims.right); r.left = 0; - r.right = _screen->getWidth() - 1; + r.right = _screen->getScriptWidth() - 1; if ((style != _styleUser) && !(style & SCI_WINDOWMGR_STYLE_NOFRAME)) r.right--; } diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index d66352b411..594c4b3442 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -37,7 +37,13 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { // Scale the screen, if needed _upscaledHires = GFX_SCREEN_UPSCALED_DISABLED; - + + // we default to scripts running at 320x200 + _scriptWidth = 320; + _scriptHeight = 200; + _width = 0; + _height = 0; + // King's Quest 6 and Gabriel Knight 1 have hires content, gk1/cd was able // to provide that under DOS as well, but as gk1/floppy does support // upscaled hires scriptswise, but doesn't actually have the hires content @@ -51,9 +57,32 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { #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; + + // Macintosh SCI0 games used 480x300, while the scripts were running at 320x200 if (g_sci->getPlatform() == Common::kPlatformMacintosh) { - if (getSciVersion() <= SCI_VERSION_01) + if (getSciVersion() <= SCI_VERSION_01) { _upscaledHires = GFX_SCREEN_UPSCALED_480x300; + _width = 480; + _height = 300; // regular visual, priority and control map are 480x300 (this is different than other upscaled SCI games) + } + + // Some Mac SCI1/1.1 games only take up 190 rows and do not + // have the menu bar. + // TODO: Verify that LSL1 and LSL5 use height 190 + switch (g_sci->getGameId()) { + case GID_FREDDYPHARKAS: + case GID_KQ5: + case GID_KQ6: + case GID_LSL1: + case GID_LSL5: + case GID_SQ1: + _width = 190; + default: + break; + } } #ifdef ENABLE_SCI32 @@ -64,70 +93,66 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { } #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; - } + //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; + if (_resMan->detectHires()) { + _scriptWidth = 640; + _scriptHeight = 480; + } - _pixels = _pitch * _height; + // if not yet set, set those to script-width/height + if (!_width) + _width = _scriptWidth; + if (!_height) + _height = _scriptHeight; + + _pixels = _width * _height; switch (_upscaledHires) { case GFX_SCREEN_UPSCALED_480x300: // Space Quest 3, Hoyle 1+2 on MAC use this one - // TODO: Sierra's upscaling worked differently. We need to figure out the exact algo _displayWidth = 480; _displayHeight = 300; - for (int i = 0; i <= _height; i++) + for (int i = 0; i <= _scriptHeight; i++) _upscaledHeightMapping[i] = (i * 3) >> 1; - for (int i = 0; i <= _width; i++) + for (int i = 0; i <= _scriptWidth; i++) _upscaledWidthMapping[i] = (i * 3) >> 1; break; case GFX_SCREEN_UPSCALED_640x400: // Police Quest 2 and Quest For Glory on PC9801 (Japanese) _displayWidth = 640; _displayHeight = 400; - for (int i = 0; i <= _height; i++) + for (int i = 0; i <= _scriptHeight; i++) _upscaledHeightMapping[i] = i * 2; - for (int i = 0; i <= _width; i++) + for (int i = 0; i <= _scriptWidth; i++) _upscaledWidthMapping[i] = i * 2; break; case GFX_SCREEN_UPSCALED_640x440: // used by King's Quest 6 on Windows _displayWidth = 640; _displayHeight = 440; - for (int i = 0; i <= _height; i++) + for (int i = 0; i <= _scriptHeight; i++) _upscaledHeightMapping[i] = (i * 11) / 5; - for (int i = 0; i <= _width; i++) + for (int i = 0; i <= _scriptWidth; i++) _upscaledWidthMapping[i] = i * 2; break; case GFX_SCREEN_UPSCALED_640x480: // Gabriel Knight 1 (VESA, Mac) _displayWidth = 640; _displayHeight = 480; - for (int i = 0; i <= _height; i++) + for (int i = 0; i <= _scriptHeight; i++) _upscaledHeightMapping[i] = (i * 12) / 5; - for (int i = 0; i <= _width; i++) + for (int i = 0; i <= _scriptWidth; i++) _upscaledWidthMapping[i] = i * 2; break; default: - _displayWidth = _pitch; + _displayWidth = _width; _displayHeight = _height; memset(&_upscaledHeightMapping, 0, sizeof(_upscaledHeightMapping) ); memset(&_upscaledWidthMapping, 0, sizeof(_upscaledWidthMapping) ); @@ -135,6 +160,8 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { } _displayPixels = _displayWidth * _displayHeight; + + // Allocate visual, priority, control and display screen _visualScreen = (byte *)calloc(_pixels, 1); _priorityScreen = (byte *)calloc(_pixels, 1); _controlScreen = (byte *)calloc(_pixels, 1); @@ -179,6 +206,34 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { error("Unknown SCI1.1 Mac game"); } else initGraphics(_displayWidth, _displayHeight, _displayWidth > 320); + + // Initialize code pointers + _vectorAdjustCoordinatePtr = &GfxScreen::vectorAdjustCoordinateNOP; + _vectorAdjustLineCoordinatesPtr = &GfxScreen::vectorAdjustLineCoordinatesNOP; + _vectorIsFillMatchPtr = &GfxScreen::vectorIsFillMatchNormal; + _vectorPutPixelPtr = &GfxScreen::putPixelNormal; + _vectorPutLinePixelPtr = &GfxScreen::putPixel; + _vectorGetPixelPtr = &GfxScreen::getPixelNormal; + _putPixelPtr = &GfxScreen::putPixelNormal; + _getPixelPtr = &GfxScreen::getPixelNormal; + + switch (_upscaledHires) { + case GFX_SCREEN_UPSCALED_480x300: + _vectorAdjustCoordinatePtr = &GfxScreen::vectorAdjustCoordinate480x300Mac; + _vectorAdjustLineCoordinatesPtr = &GfxScreen::vectorAdjustLineCoordinates480x300Mac; + // vectorPutPixel -> we already adjust coordinates for vector code, that's why we can set pixels directly + // vectorGetPixel -> see vectorPutPixel + _vectorPutLinePixelPtr = &GfxScreen::vectorPutLinePixel480x300Mac; + _putPixelPtr = &GfxScreen::putPixelAllUpscaled; + _getPixelPtr = &GfxScreen::getPixelUpscaled; + break; + case GFX_SCREEN_UPSCALED_640x400: + case GFX_SCREEN_UPSCALED_640x440: + case GFX_SCREEN_UPSCALED_640x480: + _vectorPutPixelPtr = &GfxScreen::putPixelDisplayUpscaled; + _putPixelPtr = &GfxScreen::putPixelDisplayUpscaled; + break; + } } GfxScreen::~GfxScreen() { @@ -248,43 +303,162 @@ byte GfxScreen::getDrawingMask(byte color, byte prio, byte control) { return flag; } -void GfxScreen::putPixel(int x, int y, byte drawMask, byte color, byte priority, byte control) { - int offset = y * _pitch + x; +void GfxScreen::vectorAdjustCoordinateNOP(int16 *x, int16 *y) { +} - if (drawMask & GFX_SCREEN_MASK_VISUAL) { - _visualScreen[offset] = color; - if (!_upscaledHires) { - _displayScreen[offset] = color; +void GfxScreen::vectorAdjustCoordinate480x300Mac(int16 *x, int16 *y) { + *x = _upscaledWidthMapping[*x]; + *y = _upscaledHeightMapping[*y]; +} + +void GfxScreen::vectorAdjustLineCoordinatesNOP(int16 *left, int16 *top, int16 *right, int16 *bottom, byte drawMask, byte color, byte priority, byte control) { +} + +void GfxScreen::vectorAdjustLineCoordinates480x300Mac(int16 *left, int16 *top, int16 *right, int16 *bottom, byte drawMask, byte color, byte priority, byte control) { + int16 displayLeft = _upscaledWidthMapping[*left]; + int16 displayRight = _upscaledWidthMapping[*right]; + int16 displayTop = _upscaledHeightMapping[*top]; + int16 displayBottom = _upscaledHeightMapping[*bottom]; + + if (displayLeft < displayRight) { + // one more pixel to the left, one more pixel to the right + if (displayLeft > 0) + vectorPutLinePixel(displayLeft - 1, displayTop, drawMask, color, priority, control); + vectorPutLinePixel(displayRight + 1, displayBottom, drawMask, color, priority, control); + } else if (displayLeft > displayRight) { + if (displayRight > 0) + vectorPutLinePixel(displayRight - 1, displayBottom, drawMask, color, priority, control); + vectorPutLinePixel(displayLeft + 1, displayTop, drawMask, color, priority, control); + } + *left = displayLeft; + *top = displayTop; + *right = displayRight; + *bottom = displayBottom; +} + +byte GfxScreen::vectorIsFillMatchNormal(int16 x, int16 y, byte screenMask, byte checkForColor, byte checkForPriority, byte checkForControl, bool isEGA) { + int offset = y * _width + x; + byte match = 0; + + if (screenMask & GFX_SCREEN_MASK_VISUAL) { + if (!isEGA) { + if (*(_visualScreen + offset) == checkForColor) + match |= GFX_SCREEN_MASK_VISUAL; } else { - putScaledPixelOnDisplay(x, y, color); + // In EGA games a pixel in the framebuffer is only 4 bits. We store + // a full byte per pixel to allow undithering, but when comparing + // pixels for flood-fill purposes, we should only compare the + // visible color of a pixel. + + byte EGAcolor = *(_visualScreen + offset); + if ((x ^ y) & 1) + EGAcolor = (EGAcolor ^ (EGAcolor >> 4)) & 0x0F; + else + EGAcolor = EGAcolor & 0x0F; + if (EGAcolor == checkForColor) + match |= GFX_SCREEN_MASK_VISUAL; } } + if ((screenMask & GFX_SCREEN_MASK_PRIORITY) && *(_priorityScreen + offset) == checkForPriority) + match |= GFX_SCREEN_MASK_PRIORITY; + if ((screenMask & GFX_SCREEN_MASK_CONTROL) && *(_controlScreen + offset) == checkForControl) + match |= GFX_SCREEN_MASK_CONTROL; + return match; +} + +// Special 480x300 Mac putPixel for vector line drawing, also draws an additional pixel below the actual one +void GfxScreen::vectorPutLinePixel480x300Mac(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) { + int offset = y * _width + x; + + if (drawMask & GFX_SCREEN_MASK_VISUAL) { + _visualScreen[offset] = color; + _visualScreen[offset + _width] = color; + _displayScreen[offset] = color; + // also set pixel below actual pixel + _displayScreen[offset + _displayWidth] = color; + } + if (drawMask & GFX_SCREEN_MASK_PRIORITY) { + _priorityScreen[offset] = priority; + _priorityScreen[offset + _width] = priority; + } + if (drawMask & GFX_SCREEN_MASK_CONTROL) { + _controlScreen[offset] = control; + _controlScreen[offset + _width] = control; + } +} + +// Directly sets a pixel on various screens, display is not upscaled +void GfxScreen::putPixelNormal(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) { + int offset = y * _width + x; + + if (drawMask & GFX_SCREEN_MASK_VISUAL) { + _visualScreen[offset] = color; + _displayScreen[offset] = color; + } + if (drawMask & GFX_SCREEN_MASK_PRIORITY) + _priorityScreen[offset] = priority; + if (drawMask & GFX_SCREEN_MASK_CONTROL) + _controlScreen[offset] = control; +} + +// Directly sets a pixel on various screens, display IS upscaled +void GfxScreen::putPixelDisplayUpscaled(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) { + int offset = y * _width + x; + + if (drawMask & GFX_SCREEN_MASK_VISUAL) { + _visualScreen[offset] = color; + putScaledPixelOnScreen(_displayScreen, x, y, color); + } if (drawMask & GFX_SCREEN_MASK_PRIORITY) _priorityScreen[offset] = priority; if (drawMask & GFX_SCREEN_MASK_CONTROL) _controlScreen[offset] = control; } +// Directly sets a pixel on various screens, ALL screens ARE upscaled +void GfxScreen::putPixelAllUpscaled(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) { + if (drawMask & GFX_SCREEN_MASK_VISUAL) { + putScaledPixelOnScreen(_visualScreen, x, y, color); + putScaledPixelOnScreen(_displayScreen, x, y, color); + } + if (drawMask & GFX_SCREEN_MASK_PRIORITY) + putScaledPixelOnScreen(_priorityScreen, x, y, priority); + if (drawMask & GFX_SCREEN_MASK_CONTROL) + putScaledPixelOnScreen(_controlScreen, x, y, control); +} + /** * This is used to put font pixels onto the screen - we adjust differently, so that we won't * do triple pixel lines in any case on upscaled hires. That way the font will not get distorted * Sierra SCI didn't do this */ -void GfxScreen::putFontPixel(int startingY, int x, int y, byte color) { - int actualY = startingY + y; +void GfxScreen::putFontPixel(int16 startingY, int16 x, int16 y, byte color) { + int16 actualY = startingY + y; if (_fontIsUpscaled) { // Do not scale ourselves, but put it on the display directly putPixelOnDisplay(x, actualY, color); } else { - int offset = actualY * _pitch + x; + int offset = actualY * _width + x; _visualScreen[offset] = color; switch (_upscaledHires) { case GFX_SCREEN_UPSCALED_DISABLED: _displayScreen[offset] = color; break; + case GFX_SCREEN_UPSCALED_640x400: + case GFX_SCREEN_UPSCALED_640x440: + case GFX_SCREEN_UPSCALED_640x480: { + // to 1-> 4 pixels upscaling for all of those, so that fonts won't look weird + int displayOffset = (_upscaledHeightMapping[startingY] + y * 2) * _displayWidth + x * 2; + _displayScreen[displayOffset] = color; + _displayScreen[displayOffset + 1] = color; + displayOffset += _displayWidth; + _displayScreen[displayOffset] = color; + _displayScreen[displayOffset + 1] = color; + break; + } default: - putScaledPixelOnDisplay(x, actualY, color); + putScaledPixelOnScreen(_displayScreen, x, actualY, color); break; } } @@ -295,12 +469,15 @@ void GfxScreen::putFontPixel(int startingY, int x, int y, byte color) { * only used on upscaled-Hires games where hires content needs to get drawn ONTO * the upscaled display screen (like japanese fonts, hires portraits, etc.). */ -void GfxScreen::putPixelOnDisplay(int x, int y, byte color) { +void GfxScreen::putPixelOnDisplay(int16 x, int16 y, byte color) { int offset = y * _displayWidth + x; _displayScreen[offset] = color; } -void GfxScreen::putScaledPixelOnDisplay(int x, int y, byte color) { +//void GfxScreen::putScaledPixelOnDisplay(int16 x, int16 y, byte color) { +//} + +void GfxScreen::putScaledPixelOnScreen(byte *screen, int16 x, int16 y, byte data) { int displayOffset = _upscaledHeightMapping[y] * _displayWidth + _upscaledWidthMapping[x]; int heightOffsetBreak = (_upscaledHeightMapping[y + 1] - _upscaledHeightMapping[y]) * _displayWidth; int heightOffset = 0; @@ -308,7 +485,7 @@ void GfxScreen::putScaledPixelOnDisplay(int x, int y, byte color) { do { int widthOffset = 0; do { - _displayScreen[displayOffset + heightOffset + widthOffset] = color; + screen[displayOffset + heightOffset + widthOffset] = data; widthOffset++; } while (widthOffset != widthOffsetBreak); heightOffset += _displayWidth; @@ -333,12 +510,14 @@ void GfxScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte //set_drawing_flag byte drawMask = getDrawingMask(color, priority, control); + vectorAdjustLineCoordinates(&left, &top, &right, &bottom, drawMask, color, priority, control); + // horizontal line if (top == bottom) { if (right < left) SWAP(right, left); for (int i = left; i <= right; i++) - putPixel(i, top, drawMask, color, priority, control); + vectorPutLinePixel(i, top, drawMask, color, priority, control); return; } // vertical line @@ -346,20 +525,20 @@ void GfxScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte if (top > bottom) SWAP(top, bottom); for (int i = top; i <= bottom; i++) - putPixel(left, i, drawMask, color, priority, control); + vectorPutLinePixel(left, i, drawMask, color, priority, control); return; } // sloped line - draw with Bresenham algorithm - int dy = bottom - top; - int dx = right - left; - int stepy = dy < 0 ? -1 : 1; - int stepx = dx < 0 ? -1 : 1; + int16 dy = bottom - top; + int16 dx = right - left; + int16 stepy = dy < 0 ? -1 : 1; + int16 stepx = dx < 0 ? -1 : 1; dy = ABS(dy) << 1; dx = ABS(dx) << 1; // setting the 1st and last pixel - putPixel(left, top, drawMask, color, priority, control); - putPixel(right, bottom, drawMask, color, priority, control); + vectorPutLinePixel(left, top, drawMask, color, priority, control); + vectorPutLinePixel(right, bottom, drawMask, color, priority, control); // drawing the line if (dx > dy) { // going horizontal int fraction = dy - (dx >> 1); @@ -370,7 +549,7 @@ void GfxScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte } left += stepx; fraction += dy; - putPixel(left, top, drawMask, color, priority, control); + vectorPutLinePixel(left, top, drawMask, color, priority, control); } } else { // going vertical int fraction = dx - (dy >> 1); @@ -381,7 +560,7 @@ void GfxScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte } top += stepy; fraction += dx; - putPixel(left, top, drawMask, color, priority, control); + vectorPutLinePixel(left, top, drawMask, color, priority, control); } } } @@ -394,46 +573,14 @@ void GfxScreen::putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, u commonFont->drawChar(displayPtr, chr, _displayWidth, 1, color, 0, -1, -1); } -byte GfxScreen::getVisual(int x, int y) { - return _visualScreen[y * _pitch + x]; -} - -byte GfxScreen::getPriority(int x, int y) { - return _priorityScreen[y * _pitch + x]; -} - -byte GfxScreen::getControl(int x, int y) { - return _controlScreen[y * _pitch + x]; +byte GfxScreen::getPixelNormal(byte *screen, int16 x, int16 y) { + return screen[y * _width + x]; } -byte GfxScreen::isFillMatch(int16 x, int16 y, byte screenMask, byte t_color, byte t_pri, byte t_con, bool isEGA) { - int offset = y * _pitch + x; - byte match = 0; - - if (screenMask & GFX_SCREEN_MASK_VISUAL) { - if (!isEGA) { - if (*(_visualScreen + offset) == t_color) - match |= GFX_SCREEN_MASK_VISUAL; - } else { - // In EGA games a pixel in the framebuffer is only 4 bits. We store - // a full byte per pixel to allow undithering, but when comparing - // pixels for flood-fill purposes, we should only compare the - // visible color of a pixel. - - byte c = *(_visualScreen + offset); - if ((x ^ y) & 1) - c = (c ^ (c >> 4)) & 0x0F; - else - c = c & 0x0F; - if (c == t_color) - match |= GFX_SCREEN_MASK_VISUAL; - } - } - if ((screenMask & GFX_SCREEN_MASK_PRIORITY) && *(_priorityScreen + offset) == t_pri) - match |= GFX_SCREEN_MASK_PRIORITY; - if ((screenMask & GFX_SCREEN_MASK_CONTROL) && *(_controlScreen + offset) == t_con) - match |= GFX_SCREEN_MASK_CONTROL; - return match; +byte GfxScreen::getPixelUpscaled(byte *screen, int16 x, int16 y) { + int16 mappedX = _upscaledWidthMapping[x]; + int16 mappedY = _upscaledHeightMapping[y]; + return screen[mappedY * _width + mappedX]; } int GfxScreen::bitsGetDataSize(Common::Rect rect, byte mask) { @@ -469,14 +616,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, _pitch, memoryPtr); + bitsSaveScreen(rect, _visualScreen, _width, memoryPtr); bitsSaveDisplayScreen(rect, memoryPtr); } if (mask & GFX_SCREEN_MASK_PRIORITY) { - bitsSaveScreen(rect, _priorityScreen, _pitch, memoryPtr); + bitsSaveScreen(rect, _priorityScreen, _width, memoryPtr); } if (mask & GFX_SCREEN_MASK_CONTROL) { - bitsSaveScreen(rect, _controlScreen, _pitch, memoryPtr); + bitsSaveScreen(rect, _controlScreen, _width, memoryPtr); } if (mask & GFX_SCREEN_MASK_DISPLAY) { if (!_upscaledHires) @@ -530,14 +677,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, _pitch); + bitsRestoreScreen(rect, memoryPtr, _visualScreen, _width); bitsRestoreDisplayScreen(rect, memoryPtr); } if (mask & GFX_SCREEN_MASK_PRIORITY) { - bitsRestoreScreen(rect, memoryPtr, _priorityScreen, _pitch); + bitsRestoreScreen(rect, memoryPtr, _priorityScreen, _width); } if (mask & GFX_SCREEN_MASK_CONTROL) { - bitsRestoreScreen(rect, memoryPtr, _controlScreen, _pitch); + bitsRestoreScreen(rect, memoryPtr, _controlScreen, _width); } if (mask & GFX_SCREEN_MASK_DISPLAY) { if (!_upscaledHires) @@ -612,21 +759,22 @@ void GfxScreen::dither(bool addToFlag) { byte color, ditheredColor; byte *visualPtr = _visualScreen; byte *displayPtr = _displayScreen; - + if (!_unditheringEnabled) { // Do dithering on visual and display-screen for (y = 0; y < _height; y++) { - for (x = 0; x < _pitch; x++) { + for (x = 0; x < _width; x++) { color = *visualPtr; if (color & 0xF0) { color ^= color << 4; color = ((x^y) & 1) ? color >> 4 : color & 0x0F; switch (_upscaledHires) { case GFX_SCREEN_UPSCALED_DISABLED: + case GFX_SCREEN_UPSCALED_480x300: *displayPtr = color; break; default: - putScaledPixelOnDisplay(x, y, color); + putScaledPixelOnScreen(_displayScreen, x, y, color); break; } *visualPtr = color; @@ -639,7 +787,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 < _pitch; x++) { + for (x = 0; x < _width; x++) { color = *visualPtr; if (color & 0xF0) { color ^= color << 4; @@ -654,10 +802,11 @@ void GfxScreen::dither(bool addToFlag) { } switch (_upscaledHires) { case GFX_SCREEN_UPSCALED_DISABLED: + case GFX_SCREEN_UPSCALED_480x300: *displayPtr = ditheredColor; break; default: - putScaledPixelOnDisplay(x, y, ditheredColor); + putScaledPixelOnScreen(_displayScreen, x, y, ditheredColor); break; } color = ((x^y) & 1) ? color >> 4 : color & 0x0F; @@ -685,8 +834,8 @@ int16 *GfxScreen::unditherGetDitheredBgColors() { } void GfxScreen::debugShowMap(int mapNo) { - // We cannot really support changing maps when in upscaledHires mode - if (_upscaledHires) + // We cannot really support changing maps when display screen has a different resolution than visual screen + if ((_width != _displayWidth) || (_height != _displayHeight)) return; switch (mapNo) { @@ -779,8 +928,8 @@ void GfxScreen::adjustBackUpscaledCoordinates(int16 &y, int16 &x, Sci32ViewNativ switch (_upscaledHires) { case GFX_SCREEN_UPSCALED_480x300: - x = (x << 1) / 3; - y = (y << 1) / 3; + x = (x * 4) / 6; + y = (y * 4) / 6; break; case GFX_SCREEN_UPSCALED_640x400: x /= 2; @@ -816,26 +965,4 @@ int16 GfxScreen::kernelPicNotValid(int16 newPicNotValid) { return oldPicNotValid; } -uint16 GfxScreen::getLowResScreenHeight() { - // Some Mac SCI1/1.1 games only take up 190 rows and do not - // have the menu bar. - // TODO: Verify that LSL1 and LSL5 use height 190 - if (g_sci->getPlatform() == Common::kPlatformMacintosh) { - switch (g_sci->getGameId()) { - case GID_FREDDYPHARKAS: - case GID_KQ5: - case GID_KQ6: - case GID_LSL1: - case GID_LSL5: - case GID_SQ1: - return 190; - default: - break; - } - } - - // Everything else is 200 - return 200; -} - } // End of namespace Sci diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h index e266a4ed16..766e32614a 100644 --- a/engines/sci/graphics/screen.h +++ b/engines/sci/graphics/screen.h @@ -69,6 +69,8 @@ public: uint16 getWidth() { return _width; } uint16 getHeight() { return _height; } + uint16 getScriptWidth() { return _scriptWidth; } + uint16 getScriptHeight() { return _scriptHeight; } uint16 getDisplayWidth() { return _displayWidth; } uint16 getDisplayHeight() { return _displayHeight; } byte getColorWhite() { return _colorWhite; } @@ -81,11 +83,51 @@ public: void copyDisplayRectToScreen(const Common::Rect &rect); void copyRectToScreen(const Common::Rect &rect, int16 x, int16 y); + // calls to code pointers + void inline vectorAdjustCoordinate (int16 *x, int16 *y) { + (this->*_vectorAdjustCoordinatePtr)(x, y); + } + void inline vectorAdjustLineCoordinates (int16 *left, int16 *top, int16 *right, int16 *bottom, byte drawMask, byte color, byte priority, byte control) { + (this->*_vectorAdjustLineCoordinatesPtr)(left, top, right, bottom, drawMask, color, priority, control); + } + byte inline vectorIsFillMatch (int16 x, int16 y, byte screenMask, byte t_color, byte t_pri, byte t_con, bool isEGA) { + return (this->*_vectorIsFillMatchPtr)(x, y, screenMask, t_color, t_pri, t_con, isEGA); + } + void inline vectorPutPixel(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) { + (this->*_vectorPutPixelPtr)(x, y, drawMask, color, priority, control); + } + void inline vectorPutLinePixel(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) { + (this->*_vectorPutLinePixelPtr)(x, y, drawMask, color, priority, control); + } + byte inline vectorGetVisual(int16 x, int16 y) { + return (this->*_vectorGetPixelPtr)(_visualScreen, x, y); + } + byte inline vectorGetPriority(int16 x, int16 y) { + return (this->*_vectorGetPixelPtr)(_priorityScreen, x, y); + } + byte inline vectorGetControl(int16 x, int16 y) { + return (this->*_vectorGetPixelPtr)(_controlScreen, x, y); + } + + + void inline putPixel(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) { + (this->*_putPixelPtr)(x, y, drawMask, color, priority, control); + } + + byte inline getVisual(int16 x, int16 y) { + return (this->*_getPixelPtr)(_visualScreen, x, y); + } + byte inline getPriority(int16 x, int16 y) { + return (this->*_getPixelPtr)(_priorityScreen, x, y); + } + byte inline getControl(int16 x, int16 y) { + return (this->*_getPixelPtr)(_controlScreen, x, y); + } + byte getDrawingMask(byte color, byte prio, byte control); - void putPixel(int x, int y, byte drawMask, byte color, byte prio, byte control); - void putFontPixel(int startingY, int x, int y, byte color); - void putPixelOnDisplay(int x, int y, byte color); - void putScaledPixelOnDisplay(int x, int y, byte color); + //void putPixel(int16 x, int16 y, byte drawMask, byte color, byte prio, byte control); + void putFontPixel(int16 startingY, int16 x, int16 y, byte color); + void putPixelOnDisplay(int16 x, int16 y, byte color); void drawLine(Common::Point startPoint, Common::Point endPoint, byte color, byte prio, byte control); void drawLine(int16 left, int16 top, int16 right, int16 bottom, byte color, byte prio, byte control) { drawLine(Common::Point(left, top), Common::Point(right, bottom), color, prio, control); @@ -101,10 +143,6 @@ public: void enableUndithering(bool flag); void putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, uint16 chr, byte color); - byte getVisual(int x, int y); - byte getPriority(int x, int y); - byte getControl(int x, int y); - byte isFillMatch(int16 x, int16 y, byte drawMask, byte t_color, byte t_pri, byte t_con, bool isEGA); int bitsGetDataSize(Common::Rect rect, byte mask); void bitsSave(Common::Rect rect, byte mask, byte *memoryPtr); @@ -135,9 +173,10 @@ public: private: uint16 _width; - uint16 _pitch; uint16 _height; uint _pixels; + uint16 _scriptWidth; + uint16 _scriptHeight; uint16 _displayWidth; uint16 _displayHeight; uint _displayPixels; @@ -190,8 +229,8 @@ private: * This here holds a translation for vertical+horizontal coordinates between native * (visual) and actual (display) screen. */ - int _upscaledHeightMapping[SCI_SCREEN_UPSCALEDMAXHEIGHT + 1]; - int _upscaledWidthMapping[SCI_SCREEN_UPSCALEDMAXWIDTH + 1]; + int16 _upscaledHeightMapping[SCI_SCREEN_UPSCALEDMAXHEIGHT + 1]; + int16 _upscaledWidthMapping[SCI_SCREEN_UPSCALEDMAXWIDTH + 1]; /** * This defines whether or not the font we're drawing is already scaled @@ -199,7 +238,38 @@ private: */ bool _fontIsUpscaled; - uint16 getLowResScreenHeight(); + // dynamic code + void (GfxScreen::*_vectorAdjustCoordinatePtr) (int16 *x, int16 *y); + void vectorAdjustCoordinateNOP (int16 *x, int16 *y); + void vectorAdjustCoordinate480x300Mac (int16 *x, int16 *y); + + void (GfxScreen::*_vectorAdjustLineCoordinatesPtr) (int16 *left, int16 *top, int16 *right, int16 *bottom, byte drawMask, byte color, byte priority, byte control); + void vectorAdjustLineCoordinatesNOP (int16 *left, int16 *top, int16 *right, int16 *bottom, byte drawMask, byte color, byte priority, byte control); + void vectorAdjustLineCoordinates480x300Mac (int16 *left, int16 *top, int16 *right, int16 *bottom, byte drawMask, byte color, byte priority, byte control); + + byte (GfxScreen::*_vectorIsFillMatchPtr) (int16 x, int16 y, byte screenMask, byte t_color, byte t_pri, byte t_con, bool isEGA); + byte vectorIsFillMatchNormal (int16 x, int16 y, byte screenMask, byte t_color, byte t_pri, byte t_con, bool isEGA); + byte vectorIsFillMatch480x300Mac (int16 x, int16 y, byte screenMask, byte t_color, byte t_pri, byte t_con, bool isEGA); + + void (GfxScreen::*_vectorPutPixelPtr) (int16 x, int16 y, byte drawMask, byte color, byte priority, byte control); + void vectorPutPixel480x300Mac (int16 x, int16 y, byte drawMask, byte color, byte priority, byte control); + + void (GfxScreen::*_vectorPutLinePixelPtr) (int16 x, int16 y, byte drawMask, byte color, byte priority, byte control); + void vectorPutLinePixel480x300Mac (int16 x, int16 y, byte drawMask, byte color, byte priority, byte control); + + byte (GfxScreen::*_vectorGetPixelPtr) (byte *screen, int16 x, int16 y); + + void (GfxScreen::*_putPixelPtr) (int16 x, int16 y, byte drawMask, byte color, byte priority, byte control); + void putPixelNormal (int16 x, int16 y, byte drawMask, byte color, byte priority, byte control); + void putPixelDisplayUpscaled (int16 x, int16 y, byte drawMask, byte color, byte priority, byte control); + void putPixelAllUpscaled (int16 x, int16 y, byte drawMask, byte color, byte priority, byte control); + + byte (GfxScreen::*_getPixelPtr) (byte *screen, int16 x, int16 y); + byte getPixelNormal (byte *screen, int16 x, int16 y); + byte getPixelUpscaled (byte *screen, int16 x, int16 y); + + // pixel helper + void putScaledPixelOnScreen(byte *screen, int16 x, int16 y, byte color); }; } // End of namespace Sci diff --git a/engines/sci/graphics/transitions.cpp b/engines/sci/graphics/transitions.cpp index 5e7dbc6c15..ccc7a4389a 100644 --- a/engines/sci/graphics/transitions.cpp +++ b/engines/sci/graphics/transitions.cpp @@ -339,10 +339,10 @@ void GfxTransitions::pixelation(bool blackoutFlag) { do { mask = (mask & 1) ? (mask >> 1) ^ 0xB400 : mask >> 1; - if (mask >= _screen->getWidth() * _screen->getHeight()) + if (mask >= _screen->getScriptWidth() * _screen->getScriptHeight()) continue; - pixelRect.left = mask % _screen->getWidth(); pixelRect.right = pixelRect.left + 1; - pixelRect.top = mask / _screen->getWidth(); pixelRect.bottom = pixelRect.top + 1; + pixelRect.left = mask % _screen->getScriptWidth(); pixelRect.right = pixelRect.left + 1; + pixelRect.top = mask / _screen->getScriptWidth(); pixelRect.bottom = pixelRect.top + 1; pixelRect.clip(_picRect); if (!pixelRect.isEmpty()) copyRectToScreen(pixelRect, blackoutFlag); |