From f36e9cbe4d40dc5235a2a1315eee28ab229bc6dc Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 31 Oct 2009 14:38:25 +0000 Subject: SCI/newgui: UpscaledHires implemented including undithering support, cleanup svn-id: r45562 --- engines/sci/gui/gui_cursor.cpp | 30 ++++---- engines/sci/gui/gui_cursor.h | 2 + engines/sci/gui/gui_screen.cpp | 154 ++++++++++++++++++++++++++++++----------- engines/sci/gui/gui_screen.h | 12 ++-- engines/sci/sci.cpp | 13 ++-- engines/sci/sci.h | 2 +- 6 files changed, 148 insertions(+), 65 deletions(-) (limited to 'engines') diff --git a/engines/sci/gui/gui_cursor.cpp b/engines/sci/gui/gui_cursor.cpp index e24e6e36b5..cad6b2178a 100644 --- a/engines/sci/gui/gui_cursor.cpp +++ b/engines/sci/gui/gui_cursor.cpp @@ -39,8 +39,9 @@ namespace Sci { SciGuiCursor::SciGuiCursor(ResourceManager *resMan, SciGuiPalette *palette, SciGuiScreen *screen) : _resMan(resMan), _palette(palette), _screen(screen) { - setPosition(Common::Point(160, 150)); - setMoveZone(Common::Rect(0, 0, _screen->_displayWidth, _screen->_displayHeight)); + _upscaledHires = _screen->getUpscaledHires(); + setPosition(Common::Point(160, 150)); // TODO: how is that different in 640x400 games? + setMoveZone(Common::Rect(0, 0, 320, 200)); // TODO: hires games } SciGuiCursor::~SciGuiCursor() { @@ -157,24 +158,21 @@ void SciGuiCursor::setView(GuiResourceId viewNum, int loopNum, int celNum, Commo } void SciGuiCursor::setPosition(Common::Point pos) { - int scaleFactor = _screen->getScaleFactor(); - - if (scaleFactor == 1) + if (!_upscaledHires) { g_system->warpMouse(pos.x, pos.y); - else - g_system->warpMouse(pos.x * scaleFactor, pos.y * scaleFactor); + } else { + g_system->warpMouse(pos.x * 2, pos.y * 2); + } } Common::Point SciGuiCursor::getPosition() { - int scaleFactor = _screen->getScaleFactor(); - Common::Point pos = g_system->getEventManager()->getMousePos(); - - if (scaleFactor != 1) { - pos.x /= scaleFactor; - pos.y /= scaleFactor; + if (!_upscaledHires) { + return g_system->getEventManager()->getMousePos(); + } else { + Common::Point mousePos = g_system->getEventManager()->getMousePos(); + mousePos.x /= 2; mousePos.y /= 2; + return mousePos; } - - return pos; } void SciGuiCursor::refreshPosition() { @@ -199,7 +197,7 @@ void SciGuiCursor::refreshPosition() { // FIXME: Do this only when mouse is grabbed? if (clipped) - setPosition(mousePoint); + g_system->warpMouse(mousePoint.x, mousePoint.y); } } // End of namespace Sci diff --git a/engines/sci/gui/gui_cursor.h b/engines/sci/gui/gui_cursor.h index a594f8a6c7..3cb9a3e537 100644 --- a/engines/sci/gui/gui_cursor.h +++ b/engines/sci/gui/gui_cursor.h @@ -69,6 +69,8 @@ private: SciGuiScreen *_screen; SciGuiPalette *_palette; + bool _upscaledHires; + Common::Rect _moveZone; // Rectangle in which the pointer can move CursorCache _cachedCursors; diff --git a/engines/sci/gui/gui_screen.cpp b/engines/sci/gui/gui_screen.cpp index 3b05452d35..75360c0838 100644 --- a/engines/sci/gui/gui_screen.cpp +++ b/engines/sci/gui/gui_screen.cpp @@ -33,16 +33,17 @@ namespace Sci { -SciGuiScreen::SciGuiScreen(ResourceManager *resMan, int16 width, int16 height, int16 scaleFactor) : - _resMan(resMan), _width(width), _height(height), _scaleFactor(scaleFactor) { +SciGuiScreen::SciGuiScreen(ResourceManager *resMan, int16 width, int16 height, bool upscaledHires) : + _resMan(resMan), _width(width), _height(height), _upscaledHires(upscaledHires) { _pixels = _width * _height; - if (scaleFactor != 1 && scaleFactor != 2) - error("Only scaling factors of 1 or 2 are supported"); - - _displayWidth = _width * scaleFactor; - _displayHeight = _height * scaleFactor; + _displayWidth = _width; + _displayHeight = _height; + if (_upscaledHires) { + _displayWidth *= 2; + _displayHeight *= 2; + } _displayPixels = _displayWidth * _displayHeight; _visualScreen = (byte *)calloc(_pixels, 1); @@ -90,11 +91,19 @@ void SciGuiScreen::copyFromScreen(byte *buffer) { } void SciGuiScreen::copyRectToScreen(const Common::Rect &rect) { - g_system->copyRectToScreen(_activeScreen + rect.top * _displayWidth + rect.left, _displayWidth, rect.left, rect.top, rect.width(), rect.height()); + if (!_upscaledHires) { + g_system->copyRectToScreen(_activeScreen + rect.top * _displayWidth + rect.left, _displayWidth, rect.left, rect.top, rect.width(), rect.height()); + } else { + g_system->copyRectToScreen(_activeScreen + rect.top * 2 * _displayWidth + rect.left * 2, _displayWidth, rect.left * 2, rect.top * 2, rect.width() * 2, rect.height() * 2); + } } void SciGuiScreen::copyRectToScreen(const Common::Rect &rect, int16 x, int16 y) { - g_system->copyRectToScreen(_activeScreen + rect.top * _displayWidth + rect.left, _displayWidth, x, y, rect.width(), rect.height()); + if (!_upscaledHires) { + g_system->copyRectToScreen(_activeScreen + rect.top * _displayWidth + rect.left, _displayWidth, x, y, rect.width(), rect.height()); + } else { + g_system->copyRectToScreen(_activeScreen + rect.top * 2 * _displayWidth + rect.left * 2, _displayWidth, x * 2, y * 2, rect.width() * 2, rect.height() * 2); + } } byte SciGuiScreen::getDrawingMask(byte color, byte prio, byte control) { @@ -108,26 +117,20 @@ byte SciGuiScreen::getDrawingMask(byte color, byte prio, byte control) { return flag; } -Common::Rect SciGuiScreen::getScaledRect(Common::Rect rect) { - return Common::Rect( - rect.left * _scaleFactor, rect.top * _scaleFactor, - rect.left * _scaleFactor + rect.width() * _scaleFactor, - rect.top * _scaleFactor + rect.height() * _scaleFactor); -} - void SciGuiScreen::putPixel(int x, int y, byte drawMask, byte color, byte priority, byte control) { int offset = y * _width + x; + int displayOffset; if (drawMask & SCI_SCREEN_MASK_VISUAL) { _visualScreen[offset] = color; - - if (_scaleFactor == 1) { + if (!_upscaledHires) { _displayScreen[offset] = color; } else { - _displayScreen[y * _displayWidth * 2 + x * 2] = color; // the actual pixel - _displayScreen[(y + 1) * _displayWidth * 2 + x * 2] = color; // one pixel down - _displayScreen[y * _displayWidth * 2 + (x * 2) + 1] = color; // one pixel right - _displayScreen[(y + 1) * _displayWidth * 2 + (x * 2) + 1] = color; // one pixel down and right + displayOffset = y * 2 * _displayWidth + x * 2; + _displayScreen[displayOffset] = color; + _displayScreen[displayOffset + 1] = color; + _displayScreen[displayOffset + _displayWidth] = color; + _displayScreen[displayOffset + _displayWidth + 1] = color; } } if (drawMask & SCI_SCREEN_MASK_PRIORITY) @@ -136,6 +139,13 @@ void SciGuiScreen::putPixel(int x, int y, byte drawMask, byte color, byte priori _controlScreen[offset] = control; } +// This will just change a pixel directly on displayscreen. Its supposed to get 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 SciGuiScreen::putPixelOnDisplay(int x, int y, byte color) { + int offset = y * _width + x; + _displayScreen[offset] = color; +} + // Sierra's Bresenham line drawing // WARNING: Do not just blindly replace this with Graphics::drawLine(), as it seems to create issues with flood fill void SciGuiScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control) { @@ -228,11 +238,13 @@ byte SciGuiScreen::isFillMatch(int16 x, int16 y, byte screenMask, byte t_color, int SciGuiScreen::bitsGetDataSize(Common::Rect rect, byte mask) { int byteCount = sizeof(rect) + sizeof(mask); int pixels = rect.width() * rect.height(); - Common::Rect scaledRect = getScaledRect(rect); - int scaledPixels = scaledRect.width() * scaledRect.height(); if (mask & SCI_SCREEN_MASK_VISUAL) { byteCount += pixels; // _visualScreen - byteCount += scaledPixels; // _displayScreen + if (!_upscaledHires) { + byteCount += pixels; // _displayScreen + } else { + byteCount += pixels * 4; // _displayScreen (upscaled hires) + } } if (mask & SCI_SCREEN_MASK_PRIORITY) { byteCount += pixels; // _priorityScreen @@ -250,7 +262,7 @@ void SciGuiScreen::bitsSave(Common::Rect rect, byte mask, byte *memoryPtr) { if (mask & SCI_SCREEN_MASK_VISUAL) { bitsSaveScreen(rect, _visualScreen, memoryPtr); - bitsSaveScreen(getScaledRect(rect), _displayScreen, memoryPtr); + bitsSaveDisplayScreen(rect, memoryPtr); } if (mask & SCI_SCREEN_MASK_PRIORITY) { bitsSaveScreen(rect, _priorityScreen, memoryPtr); @@ -272,6 +284,25 @@ void SciGuiScreen::bitsSaveScreen(Common::Rect rect, byte *screen, byte *&memory } } +void SciGuiScreen::bitsSaveDisplayScreen(Common::Rect rect, byte *&memoryPtr) { + byte *screen = _displayScreen; + int width = rect.width(); + int y; + + if (!_upscaledHires) { + screen += (rect.top * _displayWidth) + rect.left; + } else { + screen += (rect.top * 2 * _displayWidth) + rect.left * 2; + width *= 2; + rect.top *= 2; rect.bottom *= 2; + } + + for (y = rect.top; y < rect.bottom; y++) { + memcpy(memoryPtr, (void*)screen, width); memoryPtr += width; + screen += _displayWidth; + } +} + void SciGuiScreen::bitsGetRect(byte *memoryPtr, Common::Rect *destRect) { memcpy((void *)destRect, memoryPtr, sizeof(Common::Rect)); } @@ -285,7 +316,7 @@ void SciGuiScreen::bitsRestore(byte *memoryPtr) { if (mask & SCI_SCREEN_MASK_VISUAL) { bitsRestoreScreen(rect, memoryPtr, _visualScreen); - bitsRestoreScreen(getScaledRect(rect), memoryPtr, _displayScreen); + bitsRestoreDisplayScreen(rect, memoryPtr); } if (mask & SCI_SCREEN_MASK_PRIORITY) { bitsRestoreScreen(rect, memoryPtr, _priorityScreen); @@ -307,6 +338,25 @@ void SciGuiScreen::bitsRestoreScreen(Common::Rect rect, byte *&memoryPtr, byte * } } +void SciGuiScreen::bitsRestoreDisplayScreen(Common::Rect rect, byte *&memoryPtr) { + byte *screen = _displayScreen; + int width = rect.width(); + int y; + + if (!_upscaledHires) { + screen += (rect.top * _displayWidth) + rect.left; + } else { + screen += (rect.top * 2 * _displayWidth) + rect.left * 2; + width *= 2; + rect.top *= 2; rect.bottom *= 2; + } + + for (y = rect.top; y < rect.bottom; y++) { + memcpy((void*) screen, memoryPtr, width); memoryPtr += width; + screen += _displayWidth; + } +} + void SciGuiScreen::setPalette(GuiPalette*pal) { // just copy palette to system byte bpal[4 * 256]; @@ -324,28 +374,40 @@ void SciGuiScreen::setPalette(GuiPalette*pal) { } void SciGuiScreen::setVerticalShakePos(uint16 shakePos) { - g_system->setShakePos(shakePos); + if (!_upscaledHires) + g_system->setShakePos(shakePos); + else + g_system->setShakePos(shakePos * 2); } -// Currently not really done, its supposed to be possible to only dither _visualScreen void SciGuiScreen::dither(bool addToFlag) { int y, x; - byte color; - byte *screenPtr = _visualScreen; + byte color, ditheredColor; + byte *visualPtr = _visualScreen; byte *displayPtr = _displayScreen; if (!_unditherState) { // Do dithering on visual and display-screen for (y = 0; y < _height; y++) { for (x = 0; x < _width; x++) { - color = *screenPtr; + color = *visualPtr; if (color & 0xF0) { color ^= color << 4; color = ((x^y) & 1) ? color >> 4 : color & 0x0F; - *screenPtr = color; *displayPtr = color; + *displayPtr = color; + if (_upscaledHires) { + *(displayPtr + 1) = color; + *(displayPtr + _displayWidth) = color; + *(displayPtr + _displayWidth + 1) = color; + } + *visualPtr = color; } - screenPtr++; displayPtr++; + visualPtr++; displayPtr++; + if (_upscaledHires) + displayPtr++; } + if (_upscaledHires) + displayPtr += _displayWidth; } } else { if (!addToFlag) @@ -353,7 +415,7 @@ void SciGuiScreen::dither(bool addToFlag) { // 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++) { - color = *screenPtr; + color = *visualPtr; if (color & 0xF0) { color ^= color << 4; // remember dither combination for cel-undithering @@ -361,15 +423,25 @@ void SciGuiScreen::dither(bool addToFlag) { // if decoded color wants do dither with black on left side, we turn it around // otherwise the normal ega color would get used for display if (color & 0xF0) { - *displayPtr = color; + ditheredColor = color; } else { - *displayPtr = color << 4; + ditheredColor = color << 4; + } + *displayPtr = ditheredColor; + if (_upscaledHires) { + *(displayPtr + 1) = ditheredColor; + *(displayPtr + _displayWidth) = ditheredColor; + *(displayPtr + _displayWidth + 1) = ditheredColor; } color = ((x^y) & 1) ? color >> 4 : color & 0x0F; - *screenPtr = color; + *visualPtr = color; } - screenPtr++; displayPtr++; + visualPtr++; displayPtr++; + if (_upscaledHires) + displayPtr++; } + if (_upscaledHires) + displayPtr += _displayWidth; } } } @@ -386,6 +458,10 @@ int16 *SciGuiScreen::unditherGetMemorial() { } void SciGuiScreen::debugShowMap(int mapNo) { + // We cannot really support changing maps when in upscaledHires mode + if (_upscaledHires) + return; + switch (mapNo) { case 0: _activeScreen = _visualScreen; diff --git a/engines/sci/gui/gui_screen.h b/engines/sci/gui/gui_screen.h index 583f9c41a4..d913210495 100644 --- a/engines/sci/gui/gui_screen.h +++ b/engines/sci/gui/gui_screen.h @@ -42,7 +42,7 @@ namespace Sci { class SciGuiScreen { public: - SciGuiScreen(ResourceManager *resMan, int16 width = 320, int16 height = 200, int16 scaleFactor = 1); + SciGuiScreen(ResourceManager *resMan, int16 width = 320, int16 height = 200, bool upscaledHires = false); ~SciGuiScreen(); void copyToScreen(); @@ -52,10 +52,14 @@ public: byte getDrawingMask(byte color, byte prio, byte control); void putPixel(int x, int y, byte drawMask, byte color, byte prio, byte control); + void putPixelOnDisplay(int x, int 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); } + bool getUpscaledHires() { + return _upscaledHires; + } byte getVisual(int x, int y); byte getPriority(int x, int y); byte getControl(int x, int y); @@ -76,8 +80,6 @@ public: void debugShowMap(int mapNo); - int getScaleFactor() { return _scaleFactor; } - uint16 _width; uint16 _height; uint _pixels; @@ -92,7 +94,9 @@ public: private: void bitsRestoreScreen(Common::Rect rect, byte *&memoryPtr, byte *screen); + void bitsRestoreDisplayScreen(Common::Rect rect, byte *&memoryPtr); void bitsSaveScreen(Common::Rect rect, byte *screen, byte *&memoryPtr); + void bitsSaveDisplayScreen(Common::Rect rect, byte *&memoryPtr); bool _unditherState; int16 _unditherMemorial[SCI_SCREEN_UNDITHERMEMORIAL_SIZE]; @@ -114,7 +118,7 @@ private: // this is a pointer to the currently active screen (changing it only required for debug purposes) byte *_activeScreen; - int _scaleFactor; + bool _upscaledHires; }; } // End of namespace Sci diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 4c0441e0f1..ae6f9a5599 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -105,14 +105,17 @@ Common::Error SciEngine::run() { return Common::kNoGameDataFoundError; } - int scaleFactor = 1; + bool upscaledHires = false; // Scale the screen, if needed if (!strcmp(getGameID(), "kq6") && getPlatform() == Common::kPlatformWindows) - scaleFactor = 2; + upscaledHires = true; + + // TODO: Detect japanese editions and set upscaledHires on those as well + // TODO: Possibly look at first picture resource and determine if its hires or not // Initialize graphics-related parts - SciGuiScreen *screen = new SciGuiScreen(_resMan, 320, 200, scaleFactor); // invokes initGraphics() + SciGuiScreen *screen = new SciGuiScreen(_resMan, 320, 200, upscaledHires); // invokes initGraphics() SciGuiPalette *palette = new SciGuiPalette(_resMan, screen); SciGuiCursor *cursor = new SciGuiCursor(_resMan, palette, screen); @@ -130,8 +133,8 @@ Common::Error SciEngine::run() { #ifdef INCLUDE_OLDGFX // Gui change - //_gamestate->_gui = new SciGui(_gamestate, screen, palette, cursor); // new - _gamestate->_gui = new SciGui32(_gamestate, screen, palette, cursor); // old + _gamestate->_gui = new SciGui(_gamestate, screen, palette, cursor); // new + //_gamestate->_gui = new SciGui32(_gamestate, screen, palette, cursor); // old #else _gamestate->_gui = new SciGui(_gamestate, screen, palette, cursor); #endif diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 12143fa9e9..ee4077212d 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -31,7 +31,7 @@ namespace Sci { -#define INCLUDE_OLDGFX +//#define INCLUDE_OLDGFX class Console; struct EngineState; -- cgit v1.2.3