aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backends/PalmOS/Src/palm.h2
-rw-r--r--backends/PalmOS/Src/palmgfx.cpp2
-rw-r--r--backends/dc/dc.h2
-rw-r--r--backends/dc/display.cpp2
-rw-r--r--backends/gp32/gp32.cpp2
-rw-r--r--backends/gp32/gp32.h2
-rw-r--r--backends/morphos/morphos.cpp2
-rw-r--r--backends/morphos/morphos.h2
-rw-r--r--backends/null/null.cpp4
-rw-r--r--backends/sdl/events.cpp9
-rw-r--r--backends/sdl/graphics.cpp351
-rw-r--r--backends/sdl/sdl-common.h20
-rw-r--r--backends/sdl/sdl.cpp3
-rw-r--r--backends/wince/wince-sdl.cpp4
-rw-r--r--backends/wince/wince-sdl.h2
-rw-r--r--backends/x11/x11.cpp4
-rw-r--r--base/main.cpp4
-rw-r--r--common/system.h8
-rw-r--r--gui/newgui.cpp2
-rw-r--r--scumm/scumm.cpp8
20 files changed, 288 insertions, 147 deletions
diff --git a/backends/PalmOS/Src/palm.h b/backends/PalmOS/Src/palm.h
index 996c49a912..a46ea7e318 100644
--- a/backends/PalmOS/Src/palm.h
+++ b/backends/PalmOS/Src/palm.h
@@ -82,7 +82,7 @@ public:
// Set the size of the video bitmap.
// Typically, 320x200
- void initSize(uint w, uint h);
+ void initSize(uint w, uint h, int overlayScale);
// Draw a bitmap to screen.
// The screen will not be updated to reflect the new bitmap
diff --git a/backends/PalmOS/Src/palmgfx.cpp b/backends/PalmOS/Src/palmgfx.cpp
index 4abf13e061..594d6645a7 100644
--- a/backends/PalmOS/Src/palmgfx.cpp
+++ b/backends/PalmOS/Src/palmgfx.cpp
@@ -78,7 +78,7 @@ bool OSystem_PALMOS::setGraphicsMode(int mode) {
return true;
}
-void OSystem_PALMOS::initSize(uint w, uint h) {
+void OSystem_PALMOS::initSize(uint w, uint h, int overlayScale) {
_screenWidth = w;
_screenHeight = h;
_offScreenPitch = gVars->screenPitch; // direct screen / flipping use this, reset later if buffered
diff --git a/backends/dc/dc.h b/backends/dc/dc.h
index 76d4f612af..cf6fd59726 100644
--- a/backends/dc/dc.h
+++ b/backends/dc/dc.h
@@ -67,7 +67,7 @@ class OSystem_Dreamcast : public OSystem {
// Set the size of the video bitmap.
// Typically, 320x200
- void initSize(uint w, uint h);
+ void initSize(uint w, uint h, int overlayScale);
int16 getHeight() { return _screen_h; }
int16 getWidth() { return _screen_w; }
diff --git a/backends/dc/display.cpp b/backends/dc/display.cpp
index c6a5bee176..040eb0dec5 100644
--- a/backends/dc/display.cpp
+++ b/backends/dc/display.cpp
@@ -157,7 +157,7 @@ void OSystem_Dreamcast::setScaling()
}
}
-void OSystem_Dreamcast::initSize(uint w, uint h)
+void OSystem_Dreamcast::initSize(uint w, uint h, int overlayScale)
{
assert(w <= SCREEN_W && h <= SCREEN_H);
diff --git a/backends/gp32/gp32.cpp b/backends/gp32/gp32.cpp
index c8912ed166..0ff9827a0a 100644
--- a/backends/gp32/gp32.cpp
+++ b/backends/gp32/gp32.cpp
@@ -229,7 +229,7 @@ const char shortkey3[] = "wlptuo"; // samnmax
const char *shortkey;
int skindex = 0;
-void OSystem_GP32::initSize(uint w, uint h) {
+void OSystem_GP32::initSize(uint w, uint h, int overlayScale) {
/*switch (menu[MENU_SCREENPOS].index) {
* case 0 : scrofsy = 239 - (240 - h)/2; break;
* case 1 : scrofsy = 239; break;
diff --git a/backends/gp32/gp32.h b/backends/gp32/gp32.h
index b5a9db6ee3..9b32f64255 100644
--- a/backends/gp32/gp32.h
+++ b/backends/gp32/gp32.h
@@ -88,7 +88,7 @@ public:
// Set the size of the video bitmap.
// Typically, 320x200
- void initSize(uint w, uint h);
+ void initSize(uint w, uint h, int overlayScale);
int16 getHeight() { return _screenHeight; }
int16 getWidth() { return _screenWidth; }
diff --git a/backends/morphos/morphos.cpp b/backends/morphos/morphos.cpp
index 5092ead8a7..987e43178e 100644
--- a/backends/morphos/morphos.cpp
+++ b/backends/morphos/morphos.cpp
@@ -1455,7 +1455,7 @@ void OSystem_MorphOS::clearSoundCallback()
}
}
-void OSystem_MorphOS::initSize(uint w, uint h)
+void OSystem_MorphOS::initSize(uint w, uint h, int overlayScale)
{
if (ScummBuffer)
{
diff --git a/backends/morphos/morphos.h b/backends/morphos/morphos.h
index 30c7c04edf..f1a99f3803 100644
--- a/backends/morphos/morphos.h
+++ b/backends/morphos/morphos.h
@@ -47,7 +47,7 @@ class OSystem_MorphOS : public OSystem
// Set the size of the video bitmap.
// Typically, 320x200
- virtual void initSize(uint w, uint h);
+ virtual void initSize(uint w, uint h, int overlayScale);
// Draw a bitmap to screen.
// The screen will not be updated to reflect the new bitmap
diff --git a/backends/null/null.cpp b/backends/null/null.cpp
index 3c5b0bd5b0..a85c83d8be 100644
--- a/backends/null/null.cpp
+++ b/backends/null/null.cpp
@@ -45,7 +45,7 @@ public:
virtual bool setGraphicsMode(int mode);
bool setGraphicsMode(const char *name);
virtual int getGraphicsMode() const;
- virtual void initSize(uint width, uint height);
+ virtual void initSize(uint width, uint height, int overlayScale);
virtual int16 getHeight();
virtual int16 getWidth();
virtual void setPalette(const byte *colors, uint start, uint num);
@@ -153,7 +153,7 @@ int OSystem_NULL::getGraphicsMode() const
return -1;
}
-void OSystem_NULL::initSize(uint width, uint height)
+void OSystem_NULL::initSize(uint width, uint height, int overlayScale)
{
}
diff --git a/backends/sdl/events.cpp b/backends/sdl/events.cpp
index e29616fbea..4185fcef37 100644
--- a/backends/sdl/events.cpp
+++ b/backends/sdl/events.cpp
@@ -68,8 +68,13 @@ void OSystem_SDL::fillMouseEvent(Event &event, int x, int y) {
_km.y = y;
// Adjust for the screen scaling
- event.mouse.x /= _scaleFactor;
- event.mouse.y /= _scaleFactor;
+ if (!_overlayVisible) {
+ event.mouse.x /= _scaleFactor;
+ event.mouse.y /= _scaleFactor;
+ } else {
+ event.mouse.x = event.mouse.x / _scaleFactor * _overlayScale;
+ event.mouse.y = event.mouse.y / _scaleFactor * _overlayScale;
+ }
// Optionally perform aspect ratio adjusting
if (_adjustAspectRatio)
diff --git a/backends/sdl/graphics.cpp b/backends/sdl/graphics.cpp
index 45a142de62..44335410eb 100644
--- a/backends/sdl/graphics.cpp
+++ b/backends/sdl/graphics.cpp
@@ -66,8 +66,7 @@ void OSystem_SDL::beginGFXTransaction(void) {
_transactionMode = kTransactionActive;
_transactionDetails.modeChanged = false;
- _transactionDetails.wChanged = false;
- _transactionDetails.hChanged = false;
+ _transactionDetails.sizeChanged = false;
_transactionDetails.arChanged = false;
_transactionDetails.fsChanged = false;
@@ -83,8 +82,9 @@ void OSystem_SDL::endGFXTransaction(void) {
if (_transactionDetails.modeChanged)
setGraphicsMode(_transactionDetails.mode);
- if (_transactionDetails.wChanged || _transactionDetails.hChanged)
- initSize(_transactionDetails.w, _transactionDetails.h);
+ if (_transactionDetails.sizeChanged)
+ initSize(_transactionDetails.w, _transactionDetails.h,
+ _transactionDetails.overlayScale);
if (_transactionDetails.arChanged)
setAspectRatioCorrection(_transactionDetails.ar);
@@ -92,6 +92,7 @@ void OSystem_SDL::endGFXTransaction(void) {
if (_transactionDetails.needUnload) {
unloadGFXMode();
loadGFXMode();
+ clearOverlay();
} else {
if (!_transactionDetails.fsChanged)
if (_transactionDetails.needHotswap)
@@ -168,6 +169,16 @@ bool OSystem_SDL::setGraphicsMode(int mode) {
return false;
}
+ // Do not let switch to lesser than overlay size resolutions
+ if (_screenWidth * newScaleFactor < _overlayWidth) {
+ if (_scaleFactor == 1) { // Force 2x mode
+ mode = GFX_DOUBLESIZE;
+ newScaleFactor = 2;
+ newScalerProc = Normal2x;
+ } else
+ return false;
+ }
+
_mode = mode;
_scalerProc = newScalerProc;
@@ -226,9 +237,10 @@ int OSystem_SDL::getGraphicsMode() const {
return _mode;
}
-void OSystem_SDL::initSize(uint w, uint h) {
+void OSystem_SDL::initSize(uint w, uint h, int overlayScale) {
// Avoid redundant res changes
if ((int)w == _screenWidth && (int)h == _screenHeight &&
+ (int)overlayScale == _overlayScale &&
_transactionMode != kTransactionCommit)
return;
@@ -238,13 +250,22 @@ void OSystem_SDL::initSize(uint w, uint h) {
if (h != 200)
_adjustAspectRatio = false;
+ if (overlayScale != -1) {
+ _overlayScale = overlayScale;
+ if (w != 320)
+ _overlayScale = 1;
+
+ _overlayWidth = w * _overlayScale;
+ _overlayHeight = h * _overlayScale;
+ }
+
_cksumNum = (_screenWidth * _screenHeight / (8 * 8));
if (_transactionMode == kTransactionActive) {
_transactionDetails.w = w;
- _transactionDetails.wChanged = true;
_transactionDetails.h = h;
- _transactionDetails.hChanged = true;
+ _transactionDetails.overlayScale = _overlayScale;
+ _transactionDetails.sizeChanged = true;
_transactionDetails.needUnload = true;
@@ -257,6 +278,9 @@ void OSystem_SDL::initSize(uint w, uint h) {
if (_transactionMode != kTransactionCommit) {
unloadGFXMode();
loadGFXMode();
+
+ // if initSize() gets called in the middle, overlay is not transparent
+ clearOverlay();
}
}
@@ -264,8 +288,6 @@ void OSystem_SDL::loadGFXMode() {
_forceFull = true;
_modeFlags |= DF_UPDATE_EXPAND_1_PIXEL;
- _tmpscreen = NULL;
-
//
// Create the surface that contains the 8 bit game data
//
@@ -312,18 +334,21 @@ void OSystem_SDL::loadGFXMode() {
InitScalers(565);
// Need some extra bytes around when using 2xSaI
- _tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE,
- _screenWidth + 3,
- _screenHeight + 3,
- 16,
- _hwscreen->format->Rmask,
- _hwscreen->format->Gmask,
- _hwscreen->format->Bmask,
- _hwscreen->format->Amask);
+ _tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _screenWidth + 3, _screenHeight + 3, 16, 0, 0, 0, 0);
if (_tmpscreen == NULL)
error("allocating _tmpscreen failed");
-
+
+ _overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _overlayWidth, _overlayHeight, 16, 0, 0, 0, 0);
+
+ if (_overlayscreen == NULL)
+ error("allocating _overlayscreen failed");
+
+ _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _overlayWidth + 3, _overlayHeight + 3, 16, 0, 0, 0, 0);
+
+ if (_tmpscreen2 == NULL)
+ error("allocating _tmpscreen2 failed");
+
#ifdef USE_OSD
_osdSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
_hwscreen->w,
@@ -361,6 +386,16 @@ void OSystem_SDL::unloadGFXMode() {
_tmpscreen = NULL;
}
+ if (_tmpscreen2) {
+ SDL_FreeSurface(_tmpscreen2);
+ _tmpscreen2 = NULL;
+ }
+
+ if (_overlayscreen) {
+ SDL_FreeSurface(_overlayscreen);
+ _overlayscreen = NULL;
+ }
+
#ifdef USE_OSD
if (_osdSurface) {
SDL_FreeSurface(_osdSurface);
@@ -373,14 +408,17 @@ void OSystem_SDL::hotswapGFXMode() {
if (!_screen)
return;
- // Keep around the old _screen & _tmpscreen so we can restore the screen data
+ // Keep around the old _screen & _overlayscreen so we can restore the screen data
// after the mode switch.
SDL_Surface *old_screen = _screen;
- SDL_Surface *old_tmpscreen = _tmpscreen;
+ SDL_Surface *old_overlayscreen = _overlayscreen;
// Release the HW screen surface
SDL_FreeSurface(_hwscreen);
+ SDL_FreeSurface(_tmpscreen);
+ SDL_FreeSurface(_tmpscreen2);
+
#ifdef USE_OSD
// Release the OSD surface
SDL_FreeSurface(_osdSurface);
@@ -394,11 +432,11 @@ void OSystem_SDL::hotswapGFXMode() {
// Restore old screen content
SDL_BlitSurface(old_screen, NULL, _screen, NULL);
- SDL_BlitSurface(old_tmpscreen, NULL, _tmpscreen, NULL);
-
+ SDL_BlitSurface(old_overlayscreen, NULL, _overlayscreen, NULL);
+
// Free the old surfaces
SDL_FreeSurface(old_screen);
- SDL_FreeSurface(old_tmpscreen);
+ SDL_FreeSurface(old_overlayscreen);
// Update cursor to new scale
blitCursor();
@@ -419,6 +457,11 @@ void OSystem_SDL::updateScreen() {
}
void OSystem_SDL::internUpdateScreen() {
+ SDL_Surface *srcSurf, *origSurf;
+ int height, width;
+ ScalerProc *scalerProc;
+ int scale1, scale2;
+
assert(_hwscreen != NULL);
// If the shake position changed, fill the dirty area with blackness
@@ -467,16 +510,34 @@ void OSystem_SDL::internUpdateScreen() {
}
#endif
- undrawMouse();
+ if (!_overlayVisible) {
+ origSurf = _screen;
+ srcSurf = _tmpscreen;
+ width = _screenWidth;
+ height = _screenHeight;
+ scalerProc = _scalerProc;
+ scale1 = _scaleFactor;
+ scale2 = 1;
+ } else {
+ origSurf = _overlayscreen;
+ srcSurf = _tmpscreen2;
+ width = _overlayWidth;
+ height = _overlayHeight;
+ scalerProc = scalersMagn[_overlayScale-1][_scaleFactor-1];
+
+ scale1 = _scaleFactor;
+ scale2 = _overlayScale;
+ }
// Force a full redraw if requested
if (_forceFull) {
_numDirtyRects = 1;
_dirtyRectList[0].x = 0;
_dirtyRectList[0].y = 0;
- _dirtyRectList[0].w = _screenWidth;
- _dirtyRectList[0].h = _screenHeight;
- }
+ _dirtyRectList[0].w = width;
+ _dirtyRectList[0].h = height;
+ } else
+ undrawMouse();
// Only draw anything if necessary
if (_numDirtyRects > 0) {
@@ -486,67 +547,66 @@ void OSystem_SDL::internUpdateScreen() {
uint32 srcPitch, dstPitch;
SDL_Rect *lastRect = _dirtyRectList + _numDirtyRects;
- if (_scalerProc == Normal1x && !_adjustAspectRatio) {
- SDL_Surface *target = _overlayVisible ? _tmpscreen : _screen;
+ if (scalerProc == Normal1x && !_adjustAspectRatio && 0) {
for (r = _dirtyRectList; r != lastRect; ++r) {
dst = *r;
- if (_overlayVisible) {
- // FIXME: I don't understand why this is necessary...
- dst.x--;
- dst.y--;
- }
dst.y += _currentShakePos;
- if (SDL_BlitSurface(target, r, _hwscreen, &dst) != 0)
+ if (SDL_BlitSurface(origSurf, r, _hwscreen, &dst) != 0)
error("SDL_BlitSurface failed: %s", SDL_GetError());
}
} else {
- if (!_overlayVisible) {
- for (r = _dirtyRectList; r != lastRect; ++r) {
- dst = *r;
- dst.x++; // Shift rect by one since 2xSai needs to acces the data around
- dst.y++; // any pixel to scale it, and we want to avoid mem access crashes.
- if (SDL_BlitSurface(_screen, r, _tmpscreen, &dst) != 0)
- error("SDL_BlitSurface failed: %s", SDL_GetError());
- }
+ for (r = _dirtyRectList; r != lastRect; ++r) {
+ dst = *r;
+ dst.x++; // Shift rect by one since 2xSai needs to acces the data around
+ dst.y++; // any pixel to scale it, and we want to avoid mem access crashes.
+
+ if (SDL_BlitSurface(origSurf, r, srcSurf, &dst) != 0)
+ error("SDL_BlitSurface failed: %s", SDL_GetError());
}
- SDL_LockSurface(_tmpscreen);
+ SDL_LockSurface(srcSurf);
SDL_LockSurface(_hwscreen);
- srcPitch = _tmpscreen->pitch;
+ srcPitch = srcSurf->pitch;
dstPitch = _hwscreen->pitch;
for (r = _dirtyRectList; r != lastRect; ++r) {
register int dst_y = r->y + _currentShakePos;
register int dst_h = 0;
register int orig_dst_y = 0;
+ register int rx1 = r->x * scale1 / scale2;
- if (dst_y < _screenHeight) {
+ if (dst_y < height) {
dst_h = r->h;
- if (dst_h > _screenHeight - dst_y)
- dst_h = _screenHeight - dst_y;
+ if (dst_h > height - dst_y)
+ dst_h = height - dst_y;
- dst_y *= _scaleFactor;
+ orig_dst_y = dst_y;
+ dst_y = dst_y * scale1 / scale2;
- if (_adjustAspectRatio) {
- orig_dst_y = dst_y;
+ if (_adjustAspectRatio)
dst_y = real2Aspect(dst_y);
+
+ if (scale1 == 3 && scale2 == 2 && _overlayVisible) {
+ if (r->y % 2)
+ r->y--;
+ dst_y -= dst_y % 3;
}
- _scalerProc((byte *)_tmpscreen->pixels + (r->x * 2 + 2) + (r->y + 1) * srcPitch, srcPitch,
- (byte *)_hwscreen->pixels + r->x * 2 * _scaleFactor + dst_y * dstPitch, dstPitch, r->w, dst_h);
+ scalerProc((byte *)srcSurf->pixels + (r->x * 2 + 2) + (r->y + 1) * srcPitch, srcPitch,
+ (byte *)_hwscreen->pixels + rx1 * 2 + dst_y * dstPitch, dstPitch, r->w, dst_h);
}
-
- r->x *= _scaleFactor;
+
+ r->x = rx1;
r->y = dst_y;
- r->w *= _scaleFactor;
- r->h = dst_h * _scaleFactor;
+ r->w = r->w * scale1 / scale2;
+ r->h = dst_h * scale1 / scale2;
- if (_adjustAspectRatio && orig_dst_y / _scaleFactor < _screenHeight)
- r->h = stretch200To240((uint8 *) _hwscreen->pixels, dstPitch, r->w, r->h, r->x, r->y, orig_dst_y);
+ if (_adjustAspectRatio && orig_dst_y < height)
+ r->h = stretch200To240((uint8 *) _hwscreen->pixels, dstPitch, r->w, r->h, r->x, r->y, orig_dst_y * scale1 / scale2);
}
- SDL_UnlockSurface(_tmpscreen);
+ SDL_UnlockSurface(srcSurf);
SDL_UnlockSurface(_hwscreen);
}
@@ -564,7 +624,6 @@ void OSystem_SDL::internUpdateScreen() {
SDL_BlitSurface(_osdSurface, 0, _hwscreen, 0);
}
#endif
-
// Finally, blit all our changes to the screen
SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList);
} else {
@@ -730,14 +789,24 @@ void OSystem_SDL::addDirtyRect(int x, int y, int w, int h, bool mouseRect) {
if (_forceFull)
return;
- if (mouseRect) {
- SDL_Rect *r = &_dirtyRectList[_numDirtyRects++];
- r->x = x;
- r->y = y;
- r->w = w;
- r->h = h;
- return;
- }
+ if (mouseRect) {
+ SDL_Rect *r = &_dirtyRectList[_numDirtyRects++];
+ r->x = x;
+ r->y = y;
+ r->w = w;
+ r->h = h;
+ return;
+ }
+
+ int height, width;
+
+ if (!_overlayVisible) {
+ width = _screenWidth;
+ height = _screenHeight;
+ } else {
+ width = _overlayWidth;
+ height = _overlayHeight;
+ }
if (_numDirtyRects == NUM_DIRTY_RECT)
_forceFull = true;
@@ -762,16 +831,21 @@ void OSystem_SDL::addDirtyRect(int x, int y, int w, int h, bool mouseRect) {
y=0;
}
- if (w > _screenWidth - x) {
- w = _screenWidth - x;
+ if (w > width - x) {
+ w = width - x;
}
- if (h > _screenHeight - y) {
- h = _screenHeight - y;
+ if (h > height - y) {
+ h = height - y;
}
- if (_adjustAspectRatio)
+ if (_adjustAspectRatio) {
makeRectStretchable(x, y, w, h);
+ if (_scaleFactor == 3 && _overlayScale == 2 && _overlayVisible) {
+ if (y % 2)
+ y++;
+ }
+ }
r->x = x;
r->y = y;
@@ -931,17 +1005,18 @@ void OSystem_SDL::hideOverlay() {
assert (_transactionMode == kTransactionNone);
_overlayVisible = false;
+ clearOverlay();
_forceFull = true;
}
void OSystem_SDL::clearOverlay() {
- assert (_transactionMode == kTransactionNone);
+ //assert (_transactionMode == kTransactionNone);
- if (!_overlayVisible)
- return;
-
Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
+ if (!_overlayVisible)
+ return;
+
// Clear the overlay by making the game screen "look through" everywhere.
SDL_Rect src, dst;
src.x = src.y = 0;
@@ -951,39 +1026,47 @@ void OSystem_SDL::clearOverlay() {
if (SDL_BlitSurface(_screen, &src, _tmpscreen, &dst) != 0)
error("SDL_BlitSurface failed: %s", SDL_GetError());
+ SDL_LockSurface(_tmpscreen);
+ SDL_LockSurface(_overlayscreen);
+ if (_overlayScale == _scaleFactor) {
+ _scalerProc((byte *)(_tmpscreen->pixels) + _tmpscreen->pitch + 2,
+ _tmpscreen->pitch, (byte *)_overlayscreen->pixels, _overlayscreen->pitch, _screenWidth, _screenHeight);
+ } else {
+ // Quality is degraded here. It is possible to run one-less scaler here, but is it
+ // really needed? Quality will anyway be degraded because of 1.5x scaler.
+ (scalersMagn[0][_overlayScale-1])((byte *)(_tmpscreen->pixels) + _tmpscreen->pitch + 2,
+ _tmpscreen->pitch, (byte *)_overlayscreen->pixels, _overlayscreen->pitch, _screenWidth, _screenHeight);
+ }
+ SDL_UnlockSurface(_tmpscreen);
+ SDL_UnlockSurface(_overlayscreen);
+
_forceFull = true;
}
void OSystem_SDL::grabOverlay(OverlayColor *buf, int pitch) {
assert (_transactionMode == kTransactionNone);
- if (!_overlayVisible)
- return;
-
- if (_tmpscreen == NULL)
+ if (_overlayscreen == NULL)
return;
- if (SDL_LockSurface(_tmpscreen) == -1)
+ if (SDL_LockSurface(_overlayscreen) == -1)
error("SDL_LockSurface failed: %s", SDL_GetError());
- byte *src = (byte *)_tmpscreen->pixels + _tmpscreen->pitch + 2; // Offset by one row, one column
- int h = _screenHeight;
+ byte *src = (byte *)_overlayscreen->pixels;
+ int h = _overlayHeight;
do {
- memcpy(buf, src, _screenWidth*2);
- src += _tmpscreen->pitch;
+ memcpy(buf, src, _overlayWidth*2);
+ src += _overlayscreen->pitch;
buf += pitch;
} while (--h);
- SDL_UnlockSurface(_tmpscreen);
+ SDL_UnlockSurface(_overlayscreen);
}
void OSystem_SDL::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) {
assert (_transactionMode == kTransactionNone);
- if (!_overlayVisible)
- return;
-
- if (_tmpscreen == NULL)
+ if (_overlayscreen == NULL)
return;
// Clip the coordinates
@@ -998,12 +1081,12 @@ void OSystem_SDL::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, i
y = 0;
}
- if (w > _screenWidth - x) {
- w = _screenWidth - x;
+ if (w > _overlayWidth - x) {
+ w = _overlayWidth - x;
}
- if (h > _screenHeight-y) {
- h = _screenHeight - y;
+ if (h > _overlayHeight - y) {
+ h = _overlayHeight - y;
}
if (w <= 0 || h <= 0)
@@ -1013,25 +1096,25 @@ void OSystem_SDL::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, i
_cksumValid = false;
addDirtyRect(x, y, w, h);
- if (SDL_LockSurface(_tmpscreen) == -1)
+ if (SDL_LockSurface(_overlayscreen) == -1)
error("SDL_LockSurface failed: %s", SDL_GetError());
- byte *dst = (byte *)_tmpscreen->pixels + (y + 1) * _tmpscreen->pitch + (x + 1) * 2;
+ byte *dst = (byte *)_overlayscreen->pixels + y * _overlayscreen->pitch + x * 2;
do {
memcpy(dst, buf, w * 2);
- dst += _tmpscreen->pitch;
+ dst += _overlayscreen->pitch;
buf += pitch;
} while (--h);
- SDL_UnlockSurface(_tmpscreen);
+ SDL_UnlockSurface(_overlayscreen);
}
OverlayColor OSystem_SDL::RGBToColor(uint8 r, uint8 g, uint8 b) {
- return SDL_MapRGB(_tmpscreen->format, r, g, b);
+ return SDL_MapRGB(_overlayscreen->format, r, g, b);
}
void OSystem_SDL::colorToRGB(OverlayColor color, uint8 &r, uint8 &g, uint8 &b) {
- SDL_GetRGB(color, _tmpscreen->format, &r, &g, &b);
+ SDL_GetRGB(color, _overlayscreen->format, &r, &g, &b);
}
@@ -1061,7 +1144,10 @@ void OSystem_SDL::setMousePos(int x, int y) {
void OSystem_SDL::warpMouse(int x, int y) {
if (_mouseCurState.x != x || _mouseCurState.y != y) {
- SDL_WarpMouse(x * _scaleFactor, y * _scaleFactor);
+ if (_overlayVisible)
+ SDL_WarpMouse(x * _scaleFactor / _overlayScale, y * _scaleFactor / _overlayScale);
+ else
+ SDL_WarpMouse(x * _scaleFactor, y * _scaleFactor);
// SDL_WarpMouse() generates a mouse movement event, so
// setMousePos() would be called eventually. However, the
@@ -1235,13 +1321,24 @@ void OSystem_SDL::toggleMouseGrab() {
}
void OSystem_SDL::undrawMouse() {
+ // When we switch bigger overlay off mouse jumps. Argh!
+ // this intended to prevent undrawing offscreen mouse
+ if (!_overlayVisible)
+ if (_adjustAspectRatio) {
+ if (_mouseBackup.x > _screenWidth || aspect2Real(_mouseBackup.y) > _screenHeight)
+ return;
+ } else {
+ if (_mouseBackup.x > _screenWidth || _mouseBackup.y > _screenHeight)
+ return;
+ }
+
if (_mouseBackup.w) {
if (_adjustAspectRatio)
addDirtyRect(_mouseBackup.x, aspect2Real(_mouseBackup.y), _mouseBackup.w,
- _mouseBackup.h);
+ _mouseBackup.h);
else
addDirtyRect(_mouseBackup.x, _mouseBackup.y, _mouseBackup.w,
- _mouseBackup.h);
+ _mouseBackup.h);
}
}
@@ -1250,9 +1347,23 @@ void OSystem_SDL::drawMouse() {
_mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0;
return;
}
-
+
SDL_Rect src, dst;
bool scale;
+ int scale1, scale2;
+ int width, height;
+
+ if (!_overlayVisible) {
+ scale1 = _scaleFactor;
+ scale2 = 1;
+ width = _screenWidth;
+ height = _screenHeight;
+ } else {
+ scale1 = _scaleFactor;
+ scale2 = _overlayScale;
+ width = _overlayWidth;
+ height = _overlayHeight;
+ }
scale = (_scaleFactor > _cursorTargetScale);
@@ -1267,10 +1378,8 @@ void OSystem_SDL::drawMouse() {
int dx, dy;
dx = dst.x; dy = dst.y;
- dx = scale ? dst.x * _scaleFactor / _cursorTargetScale : dst.x;
- dy = scale ? dst.y * _scaleFactor / _cursorTargetScale : dst.y;
- if (_adjustAspectRatio)
- dy = real2Aspect(dy);
+ dx = scale ? dst.x * scale1 / scale2 / _cursorTargetScale : dst.x;
+ dy = scale ? dst.y * scale1 / scale2 / _cursorTargetScale : dst.y;
if (dst.x < 0) {
dst.w += dx;
@@ -1284,7 +1393,7 @@ void OSystem_SDL::drawMouse() {
}
// Quick check to see if anything has to be drawn at all
- if (dst.w <= 0 || dst.h <= 0)
+ if (dst.w <= 0 || dst.h <= 0 || dst.x >= width || dst.y >= height)
return;
src.w = dst.w;
@@ -1292,18 +1401,26 @@ void OSystem_SDL::drawMouse() {
if (_adjustAspectRatio)
dst.y = real2Aspect(dst.y);
-
+
+ // special case for 1o5x scaler to prevent backgound shaking
+ if (scale1 == 3 && scale2 == 2) {
+ if (dst.x % 2)
+ dst.x--;
+ if (dst.y % 2)
+ dst.y--;
+ }
+
_mouseBackup.x = dst.x;
_mouseBackup.y = dst.y;
_mouseBackup.w = dst.w;
_mouseBackup.h = dst.h;
-
- dst.x *= _scaleFactor;
- dst.y *= _scaleFactor;
-
+
+ dst.x = dst.x * scale1 / scale2;
+ dst.y = dst.y * scale1 / scale2;
+
if (SDL_BlitSurface(_mouseSurface, &src, _hwscreen, &dst) != 0)
error("SDL_BlitSurface failed: %s", SDL_GetError());
-
+
addDirtyRect(dst.x, dst.y, dst.w, dst.h, true);
}
diff --git a/backends/sdl/sdl-common.h b/backends/sdl/sdl-common.h
index b99b6e9eb2..5a92840040 100644
--- a/backends/sdl/sdl-common.h
+++ b/backends/sdl/sdl-common.h
@@ -58,7 +58,7 @@ public:
// Set the size of the video bitmap.
// Typically, 320x200
- virtual void initSize(uint w, uint h); // overloaded by CE backend
+ virtual void initSize(uint w, uint h, int overlayScale); // overloaded by CE backend
// Set colors of the palette
void setPalette(const byte *colors, uint start, uint num);
@@ -142,6 +142,12 @@ public:
virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
virtual int16 getHeight();
virtual int16 getWidth();
+ virtual int16 getOverlayHeight() { return _overlayHeight; }
+ virtual int16 getOverlayWidth() { return _overlayWidth; }
+ virtual int ScreenToOverlayX(int x) { return x * _overlayScale; }
+ virtual int ScreenToOverlayY(int y) { return y * _overlayScale; }
+ virtual int OverlayToScreenX(int x) { return x / _overlayScale; }
+ virtual int OverlayToScreenY(int y) { return y / _overlayScale; }
// Methods that convert RGB to/from colors suitable for the overlay.
virtual OverlayColor RGBToColor(uint8 r, uint8 g, uint8 b);
@@ -187,8 +193,14 @@ protected:
SDL_Surface *_screen;
int _screenWidth, _screenHeight;
- // temporary screen (for scalers/overlay)
+ // temporary screen (for scalers)
SDL_Surface *_tmpscreen;
+ SDL_Surface *_tmpscreen2;
+
+ // overlay
+ SDL_Surface *_overlayscreen;
+ int _overlayWidth, _overlayHeight;
+ int _overlayScale;
bool _overlayVisible;
// Audio
@@ -214,9 +226,9 @@ protected:
int mode;
bool modeChanged;
int w;
- bool wChanged;
int h;
- bool hChanged;
+ int overlayScale;
+ bool sizeChanged;
bool fs;
bool fsChanged;
bool ar;
diff --git a/backends/sdl/sdl.cpp b/backends/sdl/sdl.cpp
index 717523b9fb..7d558b8ece 100644
--- a/backends/sdl/sdl.cpp
+++ b/backends/sdl/sdl.cpp
@@ -97,7 +97,8 @@ OSystem_SDL::OSystem_SDL()
_osdSurface(0), _osdAlpha(SDL_ALPHA_TRANSPARENT), _osdFadeStartTime(0),
#endif
_hwscreen(0), _screen(0), _screenWidth(0), _screenHeight(0),
- _tmpscreen(0), _overlayVisible(false),
+ _tmpscreen(0), _overlayVisible(false), _overlayScale(1),
+ _overlayscreen(0), _tmpscreen2(0),
_samplesPerSec(0),
_cdrom(0), _scalerProc(0), _modeChanged(false), _dirtyChecksums(0),
_mouseVisible(false), _mouseDrawn(false), _mouseData(0), _mouseSurface(0),
diff --git a/backends/wince/wince-sdl.cpp b/backends/wince/wince-sdl.cpp
index 977232a649..1affda9df6 100644
--- a/backends/wince/wince-sdl.cpp
+++ b/backends/wince/wince-sdl.cpp
@@ -733,7 +733,7 @@ void OSystem_WINCE3::update_game_settings() {
get_sample_rate();
}
-void OSystem_WINCE3::initSize(uint w, uint h) {
+void OSystem_WINCE3::initSize(uint w, uint h, int overlaySize) {
if (_isSmartphone && h == 240)
h = 200; // mainly for the launcher
@@ -765,7 +765,7 @@ void OSystem_WINCE3::initSize(uint w, uint h) {
if (w != _screenWidth || h != _screenHeight)
_scalersChanged = false;
- OSystem_SDL::initSize(w, h);
+ OSystem_SDL::initSize(w, h, overlayScale);
if (_scalersChanged) {
unloadGFXMode();
diff --git a/backends/wince/wince-sdl.h b/backends/wince/wince-sdl.h
index 79bdff1cd5..6338b839a8 100644
--- a/backends/wince/wince-sdl.h
+++ b/backends/wince/wince-sdl.h
@@ -45,7 +45,7 @@ public:
// Update the dirty areas of the screen
void internUpdateScreen();
- void initSize(uint w, uint h);
+ void initSize(uint w, uint h, int overlaySize);
// Overloaded from SDL_Common (toolbar handling)
bool pollEvent(Event &event);
diff --git a/backends/x11/x11.cpp b/backends/x11/x11.cpp
index c528b09484..1e4ef11eac 100644
--- a/backends/x11/x11.cpp
+++ b/backends/x11/x11.cpp
@@ -84,7 +84,7 @@ public:
// Set the size of the video bitmap.
// Typically, 320x200
- void initSize(uint w, uint h);
+ void initSize(uint w, uint h, int overlaySize);
// Draw a bitmap to screen.
// The screen will not be updated to reflect the new bitmap
@@ -469,7 +469,7 @@ uint32 OSystem_X11::getMillis() {
((current_time.tv_usec - start_time.tv_usec) / 1000));
}
-void OSystem_X11::initSize(uint w, uint h) {
+void OSystem_X11::initSize(uint w, uint h, int overlaySize) {
static XShmSegmentInfo shminfo;
fb_width = w;
diff --git a/base/main.cpp b/base/main.cpp
index c6fd2b60aa..c8a3c82474 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -223,8 +223,8 @@ static bool launcherDialog(GameDetector &detector, OSystem &system) {
// Set the user specified graphics mode (if any).
system.setGraphicsMode(ConfMan.get("gfx_mode").c_str());
- // GUI is (currently) always running at 320x200
- system.initSize(320, 200);
+ // Make GUI 640 x 400
+ system.initSize(320, 200, 2);
system.endGFXTransaction();
diff --git a/common/system.h b/common/system.h
index 0cc65cfdf1..639729ab03 100644
--- a/common/system.h
+++ b/common/system.h
@@ -216,7 +216,7 @@ public:
* @param width the new virtual screen width
* @param height the new virtual screen height
*/
- virtual void initSize(uint width, uint height) = 0;
+ virtual void initSize(uint width, uint height, int overlayScale = -1) = 0;
/**
* Begin a new GFX transaction, which is a sequence of GFX mode changes.
@@ -351,6 +351,10 @@ public:
virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) = 0;
virtual int16 getOverlayHeight() { return getHeight(); }
virtual int16 getOverlayWidth() { return getWidth(); }
+ virtual int ScreenToOverlayX(int x) { return x; }
+ virtual int ScreenToOverlayY(int y) { return y; }
+ virtual int OverlayToScreenX(int x) { return x; }
+ virtual int OverlayToScreenY(int y) { return y; }
/**
* Convert the given RGB triplet into an OverlayColor. A OverlayColor can
@@ -517,7 +521,7 @@ public:
/**
* The mouse coordinates, in virtual screen coordinates. Only valid
* for mouse events.
- * Virtual screen coordinatest means: the coordinate system of the
+ * Virtual screen coordinates means: the coordinate system of the
* screen area as defined by the most recent call to initSize().
*/
Common::Point mouse;
diff --git a/gui/newgui.cpp b/gui/newgui.cpp
index c6fb6b8683..9b4529616b 100644
--- a/gui/newgui.cpp
+++ b/gui/newgui.cpp
@@ -85,7 +85,7 @@ void NewGui::updateScaleFactor() {
kDefaultGUIHeight = 200
};
- _scaleFactor = MIN(_system->getWidth() / kDefaultGUIWidth, _system->getHeight() / kDefaultGUIHeight);
+ _scaleFactor = MIN(_system->getOverlayWidth() / kDefaultGUIWidth, _system->getOverlayHeight() / kDefaultGUIHeight);
// Pick the font depending on the scale factor.
if (_scaleFactor == 1)
diff --git a/scumm/scumm.cpp b/scumm/scumm.cpp
index d0355ae35d..bef1538ff2 100644
--- a/scumm/scumm.cpp
+++ b/scumm/scumm.cpp
@@ -1162,19 +1162,21 @@ int ScummEngine::init(GameDetector &detector) {
_system->beginGFXTransaction();
initCommonGFX(detector);
if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
- _system->initSize(Common::kHercW, Common::kHercH);
+ _system->initSize(Common::kHercW, Common::kHercH, 1);
_features |= GF_DEFAULT_TO_1X_SCALER;
_system->setGraphicsMode("1x");
} else {
- _system->initSize(_screenWidth, _screenHeight);
+ _system->initSize(_screenWidth, _screenHeight, 2);
+ if (_features & GF_DEFAULT_TO_1X_SCALER)
+ _system->setGraphicsMode("1x");
}
// FIXME: All this seems a dirty hack to me. We already
// have this check in constructor
if (_heversion >= 71) {
_features |= GF_DEFAULT_TO_1X_SCALER;
- _system->setGraphicsMode("1x");
}
+
_system->endGFXTransaction();
int cd_num = ConfMan.getInt("cdrom");