From 94160a28e37326237abf990d280a211349197060 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 1 Jun 2014 13:41:14 +0200 Subject: SCI: work on SCI0/01 Mac 480x300 scaling --- engines/sci/graphics/screen.cpp | 158 ++++++++++++++++++++++++---------------- 1 file changed, 97 insertions(+), 61 deletions(-) (limited to 'engines/sci/graphics/screen.cpp') diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 15717239d8..6b1cab95c6 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -50,6 +50,11 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { _upscaledHires = GFX_SCREEN_UPSCALED_640x480; #endif } + + if (g_sci->getPlatform() == Common::kPlatformMacintosh) { + if (getSciVersion() <= SCI_VERSION_01) + _upscaledHires = GFX_SCREEN_UPSCALED_480x300; + } #ifdef ENABLE_SCI32 // GK1 Mac uses a 640x480 resolution too @@ -84,28 +89,48 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { _pixels = _pitch * _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++) + _upscaledHeightMapping[i] = (i * 3) >> 1; + for (int i = 0; i <= _width; 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++) - _upscaledMapping[i] = i * 2; + _upscaledHeightMapping[i] = i * 2; + for (int i = 0; i <= _width; 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++) - _upscaledMapping[i] = (i * 11) / 5; + _upscaledHeightMapping[i] = (i * 11) / 5; + for (int i = 0; i <= _width; 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++) - _upscaledMapping[i] = (i * 12) / 5; + _upscaledHeightMapping[i] = (i * 12) / 5; + for (int i = 0; i <= _width; i++) + _upscaledWidthMapping[i] = i * 2; break; default: _displayWidth = _pitch; _displayHeight = _height; - memset(&_upscaledMapping, 0, sizeof(_upscaledMapping) ); + memset(&_upscaledHeightMapping, 0, sizeof(_upscaledHeightMapping) ); + memset(&_upscaledWidthMapping, 0, sizeof(_upscaledWidthMapping) ); break; } @@ -185,8 +210,9 @@ void GfxScreen::copyRectToScreen(const Common::Rect &rect) { if (!_upscaledHires) { g_system->copyRectToScreen(_activeScreen + rect.top * _displayWidth + rect.left, _displayWidth, rect.left, rect.top, rect.width(), rect.height()); } else { - int rectHeight = _upscaledMapping[rect.bottom] - _upscaledMapping[rect.top]; - g_system->copyRectToScreen(_activeScreen + _upscaledMapping[rect.top] * _displayWidth + rect.left * 2, _displayWidth, rect.left * 2, _upscaledMapping[rect.top], rect.width() * 2, rectHeight); + int rectHeight = _upscaledHeightMapping[rect.bottom] - _upscaledHeightMapping[rect.top]; + int rectWidth = _upscaledWidthMapping[rect.right] - _upscaledWidthMapping[rect.left]; + g_system->copyRectToScreen(_activeScreen + _upscaledHeightMapping[rect.top] * _displayWidth + _upscaledWidthMapping[rect.left], _displayWidth, _upscaledWidthMapping[rect.left], _upscaledHeightMapping[rect.top], rectWidth, rectHeight); } } @@ -204,8 +230,10 @@ void GfxScreen::copyRectToScreen(const Common::Rect &rect, int16 x, int16 y) { if (!_upscaledHires) { g_system->copyRectToScreen(_activeScreen + rect.top * _displayWidth + rect.left, _displayWidth, x, y, rect.width(), rect.height()); } else { - int rectHeight = _upscaledMapping[rect.bottom] - _upscaledMapping[rect.top]; - g_system->copyRectToScreen(_activeScreen + _upscaledMapping[rect.top] * _displayWidth + rect.left * 2, _displayWidth, x * 2, _upscaledMapping[y], rect.width() * 2, rectHeight); + int rectHeight = _upscaledHeightMapping[rect.bottom] - _upscaledHeightMapping[rect.top]; + int rectWidth = _upscaledWidthMapping[rect.right] - _upscaledWidthMapping[rect.left]; + + g_system->copyRectToScreen(_activeScreen + _upscaledHeightMapping[rect.top] * _displayWidth + _upscaledWidthMapping[rect.left], _displayWidth, _upscaledWidthMapping[x], _upscaledHeightMapping[y], rectWidth, rectHeight); } } @@ -228,14 +256,7 @@ void GfxScreen::putPixel(int x, int y, byte drawMask, byte color, byte priority, if (!_upscaledHires) { _displayScreen[offset] = color; } else { - int displayOffset = _upscaledMapping[y] * _displayWidth + x * 2; - int heightOffsetBreak = (_upscaledMapping[y + 1] - _upscaledMapping[y]) * _displayWidth; - int heightOffset = 0; - do { - _displayScreen[displayOffset + heightOffset] = color; - _displayScreen[displayOffset + heightOffset + 1] = color; - heightOffset += _displayWidth; - } while (heightOffset != heightOffsetBreak); + putScaledPixelOnDisplay(x, y, color); } } if (drawMask & GFX_SCREEN_MASK_PRIORITY) @@ -250,22 +271,21 @@ void GfxScreen::putPixel(int x, int y, byte drawMask, byte color, byte priority, * Sierra SCI didn't do this */ void GfxScreen::putFontPixel(int startingY, int x, int y, byte color) { + int actualY = startingY + y; if (_fontIsUpscaled) { // Do not scale ourselves, but put it on the display directly - putPixelOnDisplay(x, y + startingY, color); + putPixelOnDisplay(x, actualY, color); } else { - int offset = (startingY + y) * _pitch + x; + int offset = actualY * _pitch + x; _visualScreen[offset] = color; - if (!_upscaledHires) { + switch (_upscaledHires) { + case GFX_SCREEN_UPSCALED_DISABLED: _displayScreen[offset] = color; - } else { - int displayOffset = (_upscaledMapping[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); + break; } } } @@ -280,6 +300,21 @@ void GfxScreen::putPixelOnDisplay(int x, int y, byte color) { _displayScreen[offset] = color; } +void GfxScreen::putScaledPixelOnDisplay(int x, int y, byte color) { + int displayOffset = _upscaledHeightMapping[y] * _displayWidth + _upscaledWidthMapping[x]; + int heightOffsetBreak = (_upscaledHeightMapping[y + 1] - _upscaledHeightMapping[y]) * _displayWidth; + int heightOffset = 0; + int widthOffsetBreak = _upscaledWidthMapping[x + 1] - _upscaledWidthMapping[x]; + do { + int widthOffset = 0; + do { + _displayScreen[displayOffset + heightOffset + widthOffset] = color; + widthOffset++; + } while (widthOffset != widthOffsetBreak); + heightOffset += _displayWidth; + } while (heightOffset != heightOffsetBreak); +} + /** * Sierra's Bresenham line drawing. * WARNING: Do not replace this with Graphics::drawLine(), as this causes issues @@ -409,8 +444,9 @@ int GfxScreen::bitsGetDataSize(Common::Rect rect, byte mask) { if (!_upscaledHires) { byteCount += pixels; // _displayScreen } else { - int rectHeight = _upscaledMapping[rect.bottom] - _upscaledMapping[rect.top]; - byteCount += rectHeight * rect.width() * 2; // _displayScreen (upscaled hires) + int rectHeight = _upscaledHeightMapping[rect.bottom] - _upscaledHeightMapping[rect.top]; + int rectWidth = _upscaledWidthMapping[rect.right] - _upscaledWidthMapping[rect.left]; + byteCount += rectHeight * rect.width() * rectWidth; // _displayScreen (upscaled hires) } } if (mask & GFX_SCREEN_MASK_PRIORITY) { @@ -463,16 +499,17 @@ void GfxScreen::bitsSaveScreen(Common::Rect rect, byte *screen, uint16 screenWid void GfxScreen::bitsSaveDisplayScreen(Common::Rect rect, byte *&memoryPtr) { byte *screen = _displayScreen; - int width = rect.width(); + int width; int y; if (!_upscaledHires) { + width = rect.width(); screen += (rect.top * _displayWidth) + rect.left; } else { - screen += (_upscaledMapping[rect.top] * _displayWidth) + rect.left * 2; - width *= 2; - rect.top = _upscaledMapping[rect.top]; - rect.bottom = _upscaledMapping[rect.bottom]; + screen += (_upscaledHeightMapping[rect.top] * _displayWidth) + _upscaledWidthMapping[rect.left]; + width = _upscaledWidthMapping[rect.right] - _upscaledWidthMapping[rect.left]; + rect.top = _upscaledHeightMapping[rect.top]; + rect.bottom = _upscaledHeightMapping[rect.bottom]; } for (y = rect.top; y < rect.bottom; y++) { @@ -528,16 +565,17 @@ void GfxScreen::bitsRestoreScreen(Common::Rect rect, byte *&memoryPtr, byte *scr void GfxScreen::bitsRestoreDisplayScreen(Common::Rect rect, byte *&memoryPtr) { byte *screen = _displayScreen; - int width = rect.width(); + int width; int y; if (!_upscaledHires) { screen += (rect.top * _displayWidth) + rect.left; + width = rect.width(); } else { - screen += (_upscaledMapping[rect.top] * _displayWidth) + rect.left * 2; - width *= 2; - rect.top = _upscaledMapping[rect.top]; - rect.bottom = _upscaledMapping[rect.bottom]; + screen += (_upscaledHeightMapping[rect.top] * _displayWidth) + _upscaledWidthMapping[rect.left]; + width = _upscaledWidthMapping[rect.right] - _upscaledWidthMapping[rect.left]; + rect.top = _upscaledHeightMapping[rect.top]; + rect.bottom = _upscaledHeightMapping[rect.bottom]; } for (y = rect.top; y < rect.bottom; y++) { @@ -550,7 +588,7 @@ void GfxScreen::setVerticalShakePos(uint16 shakePos) { if (!_upscaledHires) g_system->setShakePos(shakePos); else - g_system->setShakePos(shakePos * 2); + g_system->setShakePos(_upscaledHeightMapping[shakePos]); } void GfxScreen::kernelShakeScreen(uint16 shakeCount, uint16 directions) { @@ -583,20 +621,19 @@ void GfxScreen::dither(bool addToFlag) { if (color & 0xF0) { color ^= color << 4; color = ((x^y) & 1) ? color >> 4 : color & 0x0F; - *displayPtr = color; - if (_upscaledHires) { - *(displayPtr + 1) = color; - *(displayPtr + _displayWidth) = color; - *(displayPtr + _displayWidth + 1) = color; + switch (_upscaledHires) { + case GFX_SCREEN_UPSCALED_DISABLED: + *displayPtr = color; + displayPtr++; + break; + default: + putScaledPixelOnDisplay(x, y, color); + break; } *visualPtr = color; } - visualPtr++; displayPtr++; - if (_upscaledHires) - displayPtr++; + visualPtr++; } - if (_upscaledHires) - displayPtr += _displayWidth; } } else { if (!addToFlag) @@ -616,21 +653,20 @@ void GfxScreen::dither(bool addToFlag) { } else { ditheredColor = color << 4; } - *displayPtr = ditheredColor; - if (_upscaledHires) { - *(displayPtr + 1) = ditheredColor; - *(displayPtr + _displayWidth) = ditheredColor; - *(displayPtr + _displayWidth + 1) = ditheredColor; + switch (_upscaledHires) { + case GFX_SCREEN_UPSCALED_DISABLED: + *displayPtr = ditheredColor; + displayPtr++; + break; + default: + putScaledPixelOnDisplay(x, y, ditheredColor); + break; } color = ((x^y) & 1) ? color >> 4 : color & 0x0F; *visualPtr = color; } - visualPtr++; displayPtr++; - if (_upscaledHires) - displayPtr++; + visualPtr++; } - if (_upscaledHires) - displayPtr += _displayWidth; } } } @@ -722,8 +758,8 @@ static const UpScaledAdjust s_upscaledAdjustTable[] = { }; void GfxScreen::adjustToUpscaledCoordinates(int16 &y, int16 &x, Sci32ViewNativeResolution viewNativeRes) { - x *= 2; - y = _upscaledMapping[y]; + x = _upscaledWidthMapping[x]; + y = _upscaledHeightMapping[y]; for (int i = 0; i < ARRAYSIZE(s_upscaledAdjustTable); i++) { if (s_upscaledAdjustTable[i].gameHiresMode == _upscaledHires && -- cgit v1.2.3