aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/graphics/screen.h
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/graphics/screen.h')
-rw-r--r--engines/sci/graphics/screen.h315
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