diff options
-rw-r--r-- | engines/sci/graphics/screen.cpp | 255 | ||||
-rw-r--r-- | engines/sci/graphics/screen.h | 310 |
2 files changed, 297 insertions, 268 deletions
diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index e77c74bb2a..c977a93817 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -214,36 +214,6 @@ 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; - case GFX_SCREEN_UPSCALED_DISABLED: - break; - } } GfxScreen::~GfxScreen() { @@ -334,40 +304,68 @@ byte GfxScreen::getDrawingMask(byte color, byte prio, byte control) { return flag; } -void GfxScreen::vectorAdjustCoordinateNOP(int16 *x, int16 *y) { +void GfxScreen::vectorAdjustLineCoordinates(int16 *left, int16 *top, int16 *right, int16 *bottom, byte drawMask, byte color, byte priority, byte control) { + switch (_upscaledHires) { + case GFX_SCREEN_UPSCALED_480x300: { + int16 displayLeft = (*left * 3) / 2; + int16 displayRight = (*right * 3) / 2; + int16 displayTop = (*top * 3) / 2; + int16 displayBottom = (*bottom * 3) / 2; + + 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; + break; + } + default: + break; + } } -void GfxScreen::vectorAdjustCoordinate480x300Mac(int16 *x, int16 *y) { - *x = _upscaledWidthMapping[*x]; - *y = _upscaledHeightMapping[*y]; +// This is called from vector drawing to put a pixel at a certain location +void GfxScreen::vectorPutLinePixel(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) { + if (_upscaledHires == GFX_SCREEN_UPSCALED_480x300) { + vectorPutLinePixel480x300(x, y, drawMask, color, priority, control); + return; + } + + // For anything else forward to the regular putPixel + putPixel(x, y, drawMask, color, priority, control); } -void GfxScreen::vectorAdjustLineCoordinatesNOP(int16 *left, int16 *top, int16 *right, int16 *bottom, byte drawMask, byte color, byte priority, byte control) { +// Special 480x300 Mac putPixel for vector line drawing, also draws an additional pixel below the actual one +void GfxScreen::vectorPutLinePixel480x300(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) { + int offset = y * _width + x; + + if (drawMask & GFX_SCREEN_MASK_VISUAL) { + // also set pixel below actual pixel + _visualScreen[offset] = color; + _visualScreen[offset + _width] = color; + _displayScreen[offset] = color; + _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; + } } -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) { +byte GfxScreen::vectorIsFillMatch(int16 x, int16 y, byte screenMask, byte checkForColor, byte checkForPriority, byte checkForControl, bool isEGA) { int offset = y * _width + x; byte match = 0; @@ -397,132 +395,6 @@ byte GfxScreen::vectorIsFillMatchNormal(int16 x, int16 y, byte screenMask, byte 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(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: - putScaledPixelOnScreen(_displayScreen, x, actualY, color); - break; - } - } -} - -/** - * 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 GfxScreen::putPixelOnDisplay(int16 x, int16 y, byte color) { - int offset = y * _displayWidth + x; - _displayScreen[offset] = 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; - int widthOffsetBreak = _upscaledWidthMapping[x + 1] - _upscaledWidthMapping[x]; - do { - int widthOffset = 0; - do { - screen[displayOffset + heightOffset + widthOffset] = data; - 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 @@ -604,16 +476,6 @@ void GfxScreen::putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, u commonFont->drawChar(displayPtr, chr, _displayWidth, 1, color, 0, -1, -1); } -byte GfxScreen::getPixelNormal(byte *screen, int16 x, int16 y) { - return screen[y * _width + x]; -} - -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) { int byteCount = sizeof(rect) + sizeof(mask); int pixels = rect.width() * rect.height(); @@ -638,7 +500,6 @@ int GfxScreen::bitsGetDataSize(Common::Rect rect, byte mask) { error("bitsGetDataSize() called w/o being in upscaled hires mode"); byteCount += pixels; // _displayScreen (coordinates actually are given to us for hires displayScreen) } - return byteCount; } @@ -805,7 +666,7 @@ void GfxScreen::dither(bool addToFlag) { *displayPtr = color; break; default: - putScaledPixelOnScreen(_displayScreen, x, y, color); + putScaledPixelOnDisplay(x, y, color); break; } *visualPtr = color; @@ -837,7 +698,7 @@ void GfxScreen::dither(bool addToFlag) { *displayPtr = ditheredColor; break; default: - putScaledPixelOnScreen(_displayScreen, x, y, ditheredColor); + putScaledPixelOnDisplay(x, y, ditheredColor); break; } color = ((x^y) & 1) ? color >> 4 : color & 0x0F; diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h index 1c946ef02f..49c63d4681 100644 --- a/engines/sci/graphics/screen.h +++ b/engines/sci/graphics/screen.h @@ -84,51 +84,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 +171,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 +180,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 +204,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; + } + + // 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; + } + } + + /** + * 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; + } + } + } + + 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); + } - 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); + // 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 (GfxScreen::*_getPixelPtr) (byte *screen, int16 x, int16 y); - byte getPixelNormal (byte *screen, int16 x, int16 y); - byte getPixelUpscaled (byte *screen, int16 x, int16 y); + 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); + } - // pixel helper - void putScaledPixelOnScreen(byte *screen, int16 x, int16 y, byte color); + 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 |