diff options
Diffstat (limited to 'engines/sci/graphics/screen.h')
-rw-r--r-- | engines/sci/graphics/screen.h | 315 |
1 files changed, 244 insertions, 71 deletions
diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h index 1c946ef02f..65416252f6 100644 --- a/engines/sci/graphics/screen.h +++ b/engines/sci/graphics/screen.h @@ -76,6 +76,11 @@ public: byte getColorWhite() { return _colorWhite; } byte getColorDefaultVectorData() { return _colorDefaultVectorData; } +#ifdef ENABLE_SCI32 + byte *getDisplayScreen() { return _displayScreen; } + byte *getPriorityScreen() { return _priorityScreen; } +#endif + void clearForRestoreGame(); void copyToScreen(); void copyFromScreen(byte *buffer); @@ -84,51 +89,16 @@ 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); - } + // Vector drawing +private: + void vectorPutLinePixel(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control); + void vectorPutLinePixel480x300(int16 x, int16 y, byte drawMask, byte color, byte priority, byte 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); - } +public: + void vectorAdjustLineCoordinates(int16 *left, int16 *top, int16 *right, int16 *bottom, byte drawMask, byte color, byte priority, byte control); + byte vectorIsFillMatch(int16 x, int16 y, byte screenMask, byte checkForColor, byte checkForPriority, byte checkForControl, bool isEGA); byte getDrawingMask(byte color, byte prio, byte control); - //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); @@ -206,8 +176,8 @@ private: byte *_controlScreen; /** - * This screen is the one that is actually displayed to the user. It may be - * 640x400 for japanese SCI1 games. SCI0 games may be undithered in here. + * This screen is the one, where pixels are copied out of into the frame buffer. + * It may be 640x400 for japanese SCI1 games. SCI0 games may be undithered in here. * Only read from this buffer for Save/ShowBits usage. */ byte *_displayScreen; @@ -215,8 +185,8 @@ private: ResourceManager *_resMan; /** - * Pointer to the currently active screen (changing it only required for - * debug purposes). + * Pointer to the currently active screen (changing only required for + * debug purposes, to show for example the priority screen). */ byte *_activeScreen; @@ -239,38 +209,241 @@ private: */ bool _fontIsUpscaled; - // 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); + // pixel related code, in header so that it can be inlined for performance +public: + void putPixel(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) { + if (_upscaledHires == GFX_SCREEN_UPSCALED_480x300) { + putPixel480x300(x, y, drawMask, color, priority, control); + return; + } + + // Set pixel for visual, priority and control map directly, those are not upscaled + int offset = y * _width + x; + + if (drawMask & GFX_SCREEN_MASK_VISUAL) { + _visualScreen[offset] = color; + + int displayOffset = 0; + + switch (_upscaledHires) { + case GFX_SCREEN_UPSCALED_DISABLED: + displayOffset = offset; + _displayScreen[displayOffset] = color; + break; + + case GFX_SCREEN_UPSCALED_640x400: + case GFX_SCREEN_UPSCALED_640x440: + case GFX_SCREEN_UPSCALED_640x480: + putScaledPixelOnDisplay(x, y, color); + break; + default: + break; + } + } + if (drawMask & GFX_SCREEN_MASK_PRIORITY) { + _priorityScreen[offset] = priority; + } + if (drawMask & GFX_SCREEN_MASK_CONTROL) { + _controlScreen[offset] = control; + } + } - 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 putPixel480x300(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) { + int offset = ((y * 3) / 2 * _width) + ((x * 3) / 2); + + // All maps are upscaled + // TODO: figure out, what Sierra exactly did on Mac for these games + if (drawMask & GFX_SCREEN_MASK_VISUAL) { + putPixel480x300Worker(x, y, offset, _visualScreen, color); + putPixel480x300Worker(x, y, offset, _displayScreen, color); + } + if (drawMask & GFX_SCREEN_MASK_PRIORITY) { + putPixel480x300Worker(x, y, offset, _priorityScreen, priority); + } + if (drawMask & GFX_SCREEN_MASK_CONTROL) { + putPixel480x300Worker(x, y, offset, _controlScreen, control); + } + } + void putPixel480x300Worker(int16 x, int16 y, int offset, byte *screen, byte byteToSet) { + screen[offset] = byteToSet; + if (x & 1) + screen[offset + 1] = byteToSet; + if (y & 1) + screen[offset + _width] = byteToSet; + if ((x & 1) && (y & 1)) + screen[offset + _width + 1] = byteToSet; + } - 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); + // This is called from vector drawing to put a pixel at a certain location + void vectorPutPixel(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) { + switch (_upscaledHires) { + case GFX_SCREEN_UPSCALED_640x400: + case GFX_SCREEN_UPSCALED_640x440: + case GFX_SCREEN_UPSCALED_640x480: + // For regular upscaled modes forward to the regular putPixel + putPixel(x, y, drawMask, color, priority, control); + return; + break; + + default: + break; + } + + // For non-upscaled mode and 480x300 Mac put pixels directly + 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; + } + } - byte (GfxScreen::*_vectorGetPixelPtr) (byte *screen, int16 x, int16 y); + /** + * This will just change a pixel directly on displayscreen. It is supposed to be + * 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 putPixelOnDisplay(int16 x, int16 y, byte color) { + int offset = y * _displayWidth + x; + _displayScreen[offset] = color; + } - 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); + // Upscales a pixel and puts it on display screen only + void putScaledPixelOnDisplay(int16 x, int16 y, byte color) { + int displayOffset = 0; + + switch (_upscaledHires) { + case GFX_SCREEN_UPSCALED_640x400: + displayOffset = (y * 2) * _displayWidth + x * 2; // straight 1 pixel -> 2 mapping + + _displayScreen[displayOffset] = color; + _displayScreen[displayOffset + 1] = color; + _displayScreen[displayOffset + _displayWidth] = color; + _displayScreen[displayOffset + _displayWidth + 1] = color; + break; + + case GFX_SCREEN_UPSCALED_640x440: { + int16 startY = (y * 11) / 5; + int16 endY = ((y + 1) * 11) / 5; + displayOffset = (startY * _displayWidth) + x * 2; + + for (int16 curY = startY; curY < endY; curY++) { + _displayScreen[displayOffset] = color; + _displayScreen[displayOffset + 1] = color; + displayOffset += _displayWidth; + } + break; + } + case GFX_SCREEN_UPSCALED_640x480: { + int16 startY = (y * 12) / 5; + int16 endY = ((y + 1) * 12) / 5; + displayOffset = (startY * _displayWidth) + x * 2; + + for (int16 curY = startY; curY < endY; curY++) { + _displayScreen[displayOffset] = color; + _displayScreen[displayOffset + 1] = color; + displayOffset += _displayWidth; + } + break; + } + default: + break; + } + } - 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); + /** + * 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 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 * _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); + break; + } + } + } - // pixel helper - void putScaledPixelOnScreen(byte *screen, int16 x, int16 y, byte color); + byte getPixel(byte *screen, int16 x, int16 y) { + switch (_upscaledHires) { + case GFX_SCREEN_UPSCALED_480x300: { + int offset = ((y * 3) / 2) * _width + ((y * 3) / 2); + + return screen[offset]; + break; + } + default: + break; + } + return screen[y * _width + x]; + } + + byte getVisual(int16 x, int16 y) { + return getPixel(_visualScreen, x, y); + } + byte getPriority(int16 x, int16 y) { + return getPixel(_priorityScreen, x, y); + } + byte getControl(int16 x, int16 y) { + return getPixel(_controlScreen, x, y); + } + + // Vector related public code - in here, so that it can be inlined + byte vectorGetPixel(byte *screen, int16 x, int16 y) { + return screen[y * _width + x]; + } + + byte vectorGetVisual(int16 x, int16 y) { + return vectorGetPixel(_visualScreen, x, y); + } + byte vectorGetPriority(int16 x, int16 y) { + return vectorGetPixel(_priorityScreen, x, y); + } + byte vectorGetControl(int16 x, int16 y) { + return vectorGetPixel(_controlScreen, x, y); + } + + void vectorAdjustCoordinate(int16 *x, int16 *y) { + switch (_upscaledHires) { + case GFX_SCREEN_UPSCALED_480x300: + *x = (*x * 3) / 2; + *y = (*y * 3) / 2; + break; + default: + break; + } + } }; } // End of namespace Sci |