Ticket #8353: overlay.diff

File overlay.diff, 30.1 KB (added by sev-, 20 years ago)

Scaled overlay patch

  • backends/sdl/events.cpp

    RCS file: /cvsroot/scummvm/scummvm/backends/sdl/events.cpp,v
    retrieving revision 1.7
    diff -u -r1.7 events.cpp
     
    7979        km.y = y;
    8080
    8181        // Adjust for the screen scaling
    82         event.mouse.x /= _scaleFactor;
    83         event.mouse.y /= _scaleFactor;
     82        if (!_overlayVisible) {
     83                event.mouse.x /= _scaleFactor;
     84                event.mouse.y /= _scaleFactor;
     85        } else {
     86                event.mouse.x = event.mouse.x * _scaleFactor / _overlayScale;
     87                event.mouse.y = event.mouse.y * _scaleFactor / _overlayScale;
     88        }
    8489
    8590        // Optionally perform aspect ratio adjusting
    8691        if (_adjustAspectRatio)
     
    300305                                if (ev.key.keysym.sym == SDLK_EQUALS || ev.key.keysym.sym == SDLK_PLUS || ev.key.keysym.sym == SDLK_MINUS ||
    301306                                        ev.key.keysym.sym == SDLK_KP_PLUS || ev.key.keysym.sym == SDLK_KP_MINUS) {
    302307                                        factor += (ev.key.keysym.sym == SDLK_MINUS || ev.key.keysym.sym == SDLK_KP_MINUS) ? -1 : +1;
    303                                         if (0 <= factor && factor < 4 && s_gfxModeSwitchTable[_scalerType][factor] >= 0) {
     308                                        if (0 <= factor && factor < 4 && s_gfxModeSwitchTable[_scalerType][factor] >= 0
     309                                                        && factor >= _overlayScale-1) {
    304310                                                newMode = s_gfxModeSwitchTable[_scalerType][factor];
    305311                                        }
    306312                                }
  • backends/sdl/graphics.cpp

    RCS file: /cvsroot/scummvm/scummvm/backends/sdl/graphics.cpp,v
    retrieving revision 1.11
    diff -u -r1.11 graphics.cpp
     
    4141        {0, 0, 0}
    4242};
    4343
     44// Scalers used for overlay scaler
     45// [_overlayScale-1][_scaleFactor-1]
     46static ScalerProc *overlayScalers[3][3] = {
     47        { Normal1x, Normal2x, Normal3x }, // [1] 1 2 3
     48        { 0, Normal1x, Normal1o5x },      // [2] 1 2 3
     49        { 0, 0, Normal1x }
     50};
     51
    4452const OSystem::GraphicsMode *OSystem_SDL::getSupportedGraphicsModes() const {
    4553        return s_supportedGraphicsModes;
    4654}
     
    135143        return _mode;
    136144}
    137145
    138 void OSystem_SDL::initSize(uint w, uint h) {
     146void OSystem_SDL::initSize(uint w, uint h, uint overlayScale) {
    139147        // Avoid redundant res changes
    140         if ((int)w == _screenWidth && (int)h == _screenHeight)
     148        if ((int)w == _screenWidth && (int)h == _screenHeight && (int)overlayScale == _overlayScale)
    141149                return;
    142150
    143151        _screenWidth = w;
     
    146154        if (h != 200)
    147155                _adjustAspectRatio = false;
    148156
     157        _overlayScale = overlayScale;
     158        if (w != 320)
     159                _overlayScale = 1;
     160
     161        _overlayWidth = w * _overlayScale;
     162        _overlayHeight = h * _overlayScale;
     163
    149164        CKSUM_NUM = (_screenWidth * _screenHeight / (8 * 8));
    150165
    151166        free(_dirty_checksums);
     
    155170
    156171        unload_gfx_mode();
    157172        load_gfx_mode();
     173
     174        // if initSize() gets called in the middle, overlay is not transparent
     175        clearOverlay();
    158176}
    159177
    160178void OSystem_SDL::load_gfx_mode() {
    161179        _forceFull = true;
    162180        _mode_flags |= DF_UPDATE_EXPAND_1_PIXEL;
    163 
    164         _tmpscreen = NULL;
    165181       
    166182        //
    167183        // Create the surface that contains the 8 bit game data
    168184        //
    169185        _screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _screenWidth, _screenHeight, 8, 0, 0, 0, 0);
    170186        if (_screen == NULL)
    171                 error("allocating _screen failed");
     187                error("allocating _screen failed: %s", SDL_GetError());
    172188
    173189        //
    174190        // Create the surface that contains the scaled graphics in 16 bit mode
     
    209225                InitScalers(565);
    210226       
    211227        // Need some extra bytes around when using 2xSaI
    212         _tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE,
    213                                                 _screenWidth + 3,
    214                                                 _screenHeight + 3,
     228        _tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _screenWidth + 3, _screenHeight + 3, 16, 0, 0, 0, 0);
     229
     230        if (_tmpscreen == NULL)
     231                error("allocating _tmpscreen failed");
     232
     233        _overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
     234                                                _overlayWidth,
     235                                                _overlayHeight,
    215236                                                16,
    216237                                                _hwscreen->format->Rmask,
    217238                                                _hwscreen->format->Gmask,
    218239                                                _hwscreen->format->Bmask,
    219240                                                _hwscreen->format->Amask);
    220241
    221         if (_tmpscreen == NULL)
    222                 error("allocating _tmpscreen failed");
    223        
     242        if (_overlayscreen == NULL)
     243                error("allocating _overlayscreen failed");
     244        SDL_SetColorKey(_overlayscreen, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kOverlayColorKey);
     245
     246        int tmpheight = _overlayHeight * _scaleFactor / _overlayScale;
     247        if (_adjustAspectRatio)
     248                tmpheight = real2Aspect(tmpheight);
     249        _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
     250                                                _overlayWidth * _scaleFactor / _overlayScale,
     251                                                tmpheight,
     252                                                16,
     253                                                _hwscreen->format->Rmask,
     254                                                _hwscreen->format->Gmask,
     255                                                _hwscreen->format->Bmask,
     256                                                _hwscreen->format->Amask);
     257
     258        if (_tmpscreen2 == NULL)
     259                error("allocating _tmpscreen2 failed");
     260        SDL_SetColorKey(_tmpscreen2, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kOverlayColorKey);
     261
    224262#ifdef USE_OSD
    225263        _osdSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
    226264                                                _hwscreen->w,
     
    258296                _tmpscreen = NULL;
    259297        }
    260298
     299        if (_tmpscreen2) {
     300                SDL_FreeSurface(_tmpscreen2);
     301                _tmpscreen2 = NULL;
     302        }
     303
     304        if (_overlayscreen) {
     305                SDL_FreeSurface(_overlayscreen);
     306                _overlayscreen = NULL;
     307        }
     308
    261309#ifdef USE_OSD
    262310        if (_osdSurface) {
    263311                SDL_FreeSurface(_osdSurface);
     
    270318        if (!_screen)
    271319                return;
    272320
    273         // Keep around the old _screen & _tmpscreen so we can restore the screen data
     321        // Keep around the old _screen & _overlayscreen so we can restore the screen data
    274322        // after the mode switch.
    275323        SDL_Surface *old_screen = _screen;
    276         SDL_Surface *old_tmpscreen = _tmpscreen;
     324        SDL_Surface *old_overlayscreen = _overlayscreen;
    277325
    278326        // Release the HW screen surface
    279327        SDL_FreeSurface(_hwscreen);
    280328
     329        SDL_FreeSurface(_tmpscreen);
     330        SDL_FreeSurface(_tmpscreen2);
     331
    281332#ifdef USE_OSD
    282333        // Release the OSD surface
    283334        SDL_FreeSurface(_osdSurface);
     
    291342
    292343        // Restore old screen content
    293344        SDL_BlitSurface(old_screen, NULL, _screen, NULL);
    294         SDL_BlitSurface(old_tmpscreen, NULL, _tmpscreen, NULL);
     345
     346        // FIXME: for some reason simple blit doesn't keep keycolor transparency
     347        SDL_LockSurface(_overlayscreen);
     348        SDL_LockSurface(old_overlayscreen);
     349        Normal1x((byte *)old_overlayscreen->pixels, old_overlayscreen->pitch,
     350                                                (byte *)_overlayscreen->pixels, _overlayscreen->pitch, _overlayWidth, _overlayHeight);
     351        SDL_UnlockSurface(_overlayscreen);
     352        SDL_UnlockSurface(old_overlayscreen);
    295353       
    296354        // Free the old surfaces
    297355        SDL_FreeSurface(old_screen);
    298         SDL_FreeSurface(old_tmpscreen);
     356        SDL_FreeSurface(old_overlayscreen);
    299357
    300358        // Blit everything to the screen
    301359        internUpdateScreen();
     
    380438                uint32 srcPitch, dstPitch;
    381439                SDL_Rect *last_rect = _dirty_rect_list + _num_dirty_rects;
    382440
    383                 if (_scaler_proc == Normal1x && !_adjustAspectRatio) {
    384                         SDL_Surface *target = _overlayVisible ? _tmpscreen : _screen;
     441                if (_scaler_proc == Normal1x && !_adjustAspectRatio && 0) {
    385442                        for (r = _dirty_rect_list; r != last_rect; ++r) {
    386443                                dst = *r;
    387444                               
    388                                 if (_overlayVisible) {
    389                                         // FIXME: I don't understand why this is necessary...
    390                                         dst.x--;
    391                                         dst.y--;
    392                                 }
    393445                                dst.y += _currentShakePos;
    394                                 if (SDL_BlitSurface(target, r, _hwscreen, &dst) != 0)
     446                                if (SDL_BlitSurface(_screen, r, _hwscreen, &dst) != 0)
    395447                                        error("SDL_BlitSurface failed: %s", SDL_GetError());
    396448                        }
     449                        if (SDL_BlitSurface(_overlayscreen, 0, _hwscreen, 0) != 0)
     450                                error("SDL_BlitSurface failed: %s", SDL_GetError());
    397451                } else {
    398                         if (!_overlayVisible) {
    399                                 for (r = _dirty_rect_list; r != last_rect; ++r) {
    400                                         dst = *r;
    401                                         dst.x++;        // Shift rect by one since 2xSai needs to acces the data around
    402                                         dst.y++;        // any pixel to scale it, and we want to avoid mem access crashes.
    403                                         if (SDL_BlitSurface(_screen, r, _tmpscreen, &dst) != 0)
    404                                                 error("SDL_BlitSurface failed: %s", SDL_GetError());
    405                                 }
     452                        for (r = _dirty_rect_list; r != last_rect; ++r) {
     453                                dst = *r;
     454                                dst.x++;        // Shift rect by one since 2xSai needs to acces the data around
     455                                dst.y++;        // any pixel to scale it, and we want to avoid mem access crashes.
     456                                if (SDL_BlitSurface(_screen, r, _tmpscreen, &dst) != 0)
     457                                        error("SDL_BlitSurface failed: %s", SDL_GetError());
    406458                        }
    407459
    408460                        SDL_LockSurface(_tmpscreen);
     
    439491
    440492                                if (_adjustAspectRatio && orig_dst_y / _scaleFactor < _screenHeight)
    441493                                        r->h = stretch200To240((uint8 *) _hwscreen->pixels, dstPitch, r->w, r->h, r->x, r->y, orig_dst_y);
     494
    442495                        }
    443496                        SDL_UnlockSurface(_tmpscreen);
    444497                        SDL_UnlockSurface(_hwscreen);
     498
     499                        srcPitch = _overlayscreen->pitch;
     500                        dstPitch = _tmpscreen2->pitch;
     501
     502                        SDL_LockSurface(_tmpscreen2);
     503                        SDL_LockSurface(_overlayscreen);
     504                        (overlayScalers[_overlayScale-1][_scaleFactor-1])((byte *)_overlayscreen->pixels, srcPitch,
     505                                                (byte *)_tmpscreen2->pixels, dstPitch, _overlayWidth, _overlayHeight);
     506                        if (_adjustAspectRatio)
     507                                stretch200To240((uint8 *)_tmpscreen2->pixels, _tmpscreen2->pitch,
     508                                        _overlayWidth * _scaleFactor / _overlayScale, _overlayHeight * _scaleFactor / _overlayScale,
     509                                        0, 0, 0);
     510
     511                        SDL_UnlockSurface(_tmpscreen2);
     512                        SDL_UnlockSurface(_overlayscreen);
     513                        if (SDL_BlitSurface(_tmpscreen2, 0, _hwscreen, 0) != 0)
     514                                error("SDL_BlitSurface failed: %s", SDL_GetError());
    445515                }
    446516
    447517                // Readjust the dirty rect list in case we are doing a full update.
     
    813883        undraw_mouse();
    814884
    815885        _overlayVisible = false;
     886        clearOverlay();
    816887        _forceFull = true;
    817888}
    818889
    819890void OSystem_SDL::clearOverlay() {
    820         if (!_overlayVisible)
    821                 return;
    822        
    823891        Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
    824892       
    825893        // hide the mouse
    826894        undraw_mouse();
    827895
    828         // Clear the overlay by making the game screen "look through" everywhere.
    829         SDL_Rect src, dst;
    830         src.x = src.y = 0;
    831         dst.x = dst.y = 1;
    832         src.w = dst.w = _screenWidth;
    833         src.h = dst.h = _screenHeight;
    834         if (SDL_BlitSurface(_screen, &src, _tmpscreen, &dst) != 0)
    835                 error("SDL_BlitSurface failed: %s", SDL_GetError());
    836 
     896        if (!_overlayVisible) {
     897                // Fill everything with the "transparent" color, i.e. the colorkey
     898                SDL_FillRect(_overlayscreen, 0, kOverlayColorKey);
     899        } else {
     900                // Clear the overlay by making the game screen "look through" everywhere.
     901                SDL_Rect src, dst;
     902                src.x = src.y = 0;
     903                dst.x = dst.y = 1;
     904                src.w = dst.w = _screenWidth;
     905                src.h = dst.h = _screenHeight;
     906                if (SDL_BlitSurface(_screen, &src, _tmpscreen, &dst) != 0)
     907                        error("SDL_BlitSurface failed: %s", SDL_GetError());
     908
     909                SDL_LockSurface(_tmpscreen);
     910                SDL_LockSurface(_overlayscreen);
     911                if (_overlayScale == _scaleFactor) {
     912                        _scaler_proc((byte *)(_tmpscreen->pixels) + _tmpscreen->pitch + 2,
     913                                _tmpscreen->pitch, (byte *)_overlayscreen->pixels, _overlayscreen->pitch, _screenWidth, _screenHeight);
     914                } else {
     915                        // Quality is degraded here. It is possible to run one-less scaler here, but is it
     916                        // really needed? Quality will anyway be degraded because of 1.5x scaler.
     917                        (overlayScalers[0][_overlayScale-1])((byte *)(_tmpscreen->pixels) + _tmpscreen->pitch + 2,
     918                                _tmpscreen->pitch, (byte *)_overlayscreen->pixels, _overlayscreen->pitch, _screenWidth, _screenHeight);
     919                }
     920                SDL_UnlockSurface(_tmpscreen);
     921                SDL_UnlockSurface(_overlayscreen);
     922        }
    837923        _forceFull = true;
    838924}
    839925
    840926void OSystem_SDL::grabOverlay(OverlayColor *buf, int pitch) {
    841         if (!_overlayVisible)
    842                 return;
    843 
    844         if (_tmpscreen == NULL)
     927        if (_overlayscreen == NULL)
    845928                return;
    846929
    847930        // hide the mouse
    848931        undraw_mouse();
    849932
    850         if (SDL_LockSurface(_tmpscreen) == -1)
     933        if (SDL_LockSurface(_overlayscreen) == -1)
    851934                error("SDL_LockSurface failed: %s", SDL_GetError());
    852935
    853         byte *src = (byte *)_tmpscreen->pixels + _tmpscreen->pitch + 2; // Offset by one row, one column
    854         int h = _screenHeight;
     936        byte *src = (byte *)_overlayscreen->pixels;
     937        int h = _overlayHeight;
    855938        do {
    856                 memcpy(buf, src, _screenWidth*2);
    857                 src += _tmpscreen->pitch;
     939                memcpy(buf, src, _overlayWidth*2);
     940                src += _overlayscreen->pitch;
    858941                buf += pitch;
    859942        } while (--h);
    860943
    861         SDL_UnlockSurface(_tmpscreen);
     944        SDL_UnlockSurface(_overlayscreen);
    862945}
    863946
    864947void OSystem_SDL::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) {
    865         if (!_overlayVisible)
    866                 return;
    867 
    868         if (_tmpscreen == NULL)
     948        if (_overlayscreen == NULL)
    869949                return;
    870950
    871951        // Clip the coordinates
     
    880960                y = 0;
    881961        }
    882962
    883         if (w > _screenWidth - x) {
    884                 w = _screenWidth - x;
     963        if (w > _overlayWidth - x) {
     964                w = _overlayWidth - x;
    885965        }
    886966
    887         if (h > _screenHeight-y) {
    888                 h = _screenHeight - y;
     967        if (h > _overlayHeight-y) {
     968                h = _overlayHeight - y;
    889969        }
    890970
    891971        if (w <= 0 || h <= 0)
     
    893973
    894974        // Mark the modified region as dirty
    895975        cksum_valid = false;
    896         add_dirty_rect(x, y, w, h);
     976        add_dirty_rect(Ovl2Scr(x), Ovl2Scr(y), Ovl2Scr(w), Ovl2Scr(h));
    897977
    898978        /* FIXME: undraw mouse only if the draw rect intersects with the mouse rect */
    899979        undraw_mouse();
    900980
    901         if (SDL_LockSurface(_tmpscreen) == -1)
     981        if (SDL_LockSurface(_overlayscreen) == -1)
    902982                error("SDL_LockSurface failed: %s", SDL_GetError());
    903983
    904         byte *dst = (byte *)_tmpscreen->pixels + (y + 1) * _tmpscreen->pitch + (x + 1) * 2;
     984        byte *dst = (byte *)_overlayscreen->pixels + y * _overlayscreen->pitch + x * 2;
    905985        do {
    906986                memcpy(dst, buf, w * 2);
    907                 dst += _tmpscreen->pitch;
     987                dst += _overlayscreen->pitch;
    908988                buf += pitch;
    909989        } while (--h);
    910990
    911         SDL_UnlockSurface(_tmpscreen);
     991        SDL_UnlockSurface(_overlayscreen);
    912992}
    913993
    914994OverlayColor OSystem_SDL::RGBToColor(uint8 r, uint8 g, uint8 b) {
    915         return SDL_MapRGB(_tmpscreen->format, r, g, b);
     995        return SDL_MapRGB(_overlayscreen->format, r, g, b);
    916996}
    917997
    918998void OSystem_SDL::colorToRGB(OverlayColor color, uint8 &r, uint8 &g, uint8 &b) {
    919         SDL_GetRGB(color, _tmpscreen->format, &r, &g, &b);
     999        SDL_GetRGB(color, _overlayscreen->format, &r, &g, &b);
    9201000}
    9211001
    9221002
     
    9501030
    9511031void OSystem_SDL::warpMouse(int x, int y) {
    9521032        if (_mouseCurState.x != x || _mouseCurState.y != y) {
    953                 SDL_WarpMouse(x * _scaleFactor, y * _scaleFactor);
     1033                if (_overlayVisible)
     1034                        SDL_WarpMouse(x * _scaleFactor / _overlayScale, y * _scaleFactor / _overlayScale);
     1035                else
     1036                        SDL_WarpMouse(x * _scaleFactor, y * _scaleFactor);
    9541037
    9551038                // SDL_WarpMouse() generates a mouse movement event, so
    9561039                // set_mouse_pos() would be called eventually. However, the
     
    9641047}
    9651048       
    9661049void OSystem_SDL::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor) {
     1050        int cursorScale = _overlayScale;
     1051        int dstPitch;
     1052        byte *tmpPtr, *dstPtr;
     1053        const byte *srcPtr = buf;
    9671054
    9681055        undraw_mouse();
    9691056
     1057        if (!_cursorScaled)
     1058                cursorScale = 1;
     1059
    9701060        assert(w <= MAX_MOUSE_W);
    9711061        assert(h <= MAX_MOUSE_H);
    972         _mouseCurState.w = w;
    973         _mouseCurState.h = h;
     1062        _mouseCurState.w = w * cursorScale;
     1063        _mouseCurState.h = h * cursorScale;
    9741064
    975         _mouseHotspotX = hotspot_x;
    976         _mouseHotspotY = hotspot_y;
     1065        _mouseHotspotX = hotspot_x * cursorScale;
     1066        _mouseHotspotY = hotspot_y * cursorScale;
    9771067
    9781068        _mouseKeycolor = keycolor;
    9791069
    9801070        if (_mouseData)
    9811071                free(_mouseData);
    9821072
    983         _mouseData = (byte *)malloc(w * h);
    984         memcpy(_mouseData, buf, w * h);
     1073        dstPtr = _mouseData = (byte *)malloc(w * h * cursorScale * cursorScale);
     1074
     1075        if (cursorScale == 1) {
     1076                memcpy(_mouseData, buf, w * h);
     1077                return;
     1078        }
     1079
     1080        dstPitch = w * cursorScale;
     1081        for (uint i = 0; i < h; i++) {
     1082                for (uint j = 0; j < w; j++) {
     1083                        for (int k = 0; k < cursorScale; k++) {
     1084                                tmpPtr = dstPtr + dstPitch * k;
     1085                                for (int l = 0; l < cursorScale; l++) {
     1086                                        *tmpPtr++ = *srcPtr;
     1087                                }
     1088                        }
     1089                        srcPtr++;
     1090                        dstPtr += cursorScale;
     1091                }
     1092                dstPtr += dstPitch * (cursorScale - 1);
     1093        }
    9851094}
    9861095
    9871096void OSystem_SDL::toggleMouseGrab() {
     
    10021111        byte color;
    10031112        const byte *src = _mouseData;           // Image representing the mouse
    10041113
    1005         // clip the mouse rect, and addjust the src pointer accordingly
     1114        if (!_overlayVisible) {
     1115                x = Scr2Ovl(x);
     1116                y = Scr2Ovl(y);
     1117        }
     1118
     1119        // clip the mouse rect, and adjust the src pointer accordingly
    10061120        if (x < 0) {
    10071121                w += x;
    10081122                src -= x;
     
    10141128                y = 0;
    10151129        }
    10161130
    1017         if (w > _screenWidth - x)
    1018                 w = _screenWidth - x;
    1019         if (h > _screenHeight - y)
    1020                 h = _screenHeight - y;
     1131        if (w > _overlayWidth - x)
     1132                w = _overlayWidth - x;
     1133        if (h > _overlayHeight - y)
     1134                h = _overlayHeight - y;
    10211135
    10221136        // Quick check to see if anything has to be drawn at all
    10231137        if (w <= 0 || h <= 0)
    10241138                return;
    10251139
    10261140        // Draw the mouse cursor; backup the covered area in "bak"
    1027         if (SDL_LockSurface(_overlayVisible ? _tmpscreen : _screen) == -1)
     1141        if (SDL_LockSurface(_overlayscreen) == -1)
    10281142                error("SDL_LockSurface failed: %s", SDL_GetError());
    10291143
    10301144        // Mark as dirty
    1031         add_dirty_rect(x, y, w, h);
     1145        add_dirty_rect(Ovl2Scr(x), Ovl2Scr(y), Ovl2Scr(w), Ovl2Scr(h));
    10321146
    1033         if (!_overlayVisible) {
    1034                 byte *bak = _mouseBackup;               // Surface used to backup the area obscured by the mouse
    1035                 byte *dst;                                      // Surface we are drawing into
    1036        
    1037                 dst = (byte *)_screen->pixels + y * _screenWidth + x;
    1038                 while (h > 0) {
    1039                         int width = w;
    1040                         while (width > 0) {
    1041                                 *bak++ = *dst;
    1042                                 color = *src++;
    1043                                 if (color != _mouseKeycolor)    // transparent, don't draw
    1044                                         *dst = color;
    1045                                 dst++;
    1046                                 width--;
    1047                         }
    1048                         src += _mouseCurState.w - w;
    1049                         bak += MAX_MOUSE_W - w;
    1050                         dst += _screenWidth - w;
    1051                         h--;
    1052                 }
     1147        uint16 *bak = (uint16 *)_mouseBackup;   // Surface used to backup the area obscured by the mouse
     1148        byte *dst;                                      // Surface we are drawing into
    10531149       
    1054         } else {
    1055                 uint16 *bak = (uint16 *)_mouseBackup;   // Surface used to backup the area obscured by the mouse
    1056                 byte *dst;                                      // Surface we are drawing into
    1057        
    1058                 dst = (byte *)_tmpscreen->pixels + (y + 1) * _tmpscreen->pitch + (x + 1) * 2;
    1059                 while (h > 0) {
    1060                         int width = w;
    1061                         while (width > 0) {
    1062                                 *bak++ = *(uint16 *)dst;
    1063                                 color = *src++;
    1064                                 if (color != 0xFF)      // 0xFF = transparent, don't draw
    1065                                         *(uint16 *)dst = RGBToColor(_currentPalette[color].r, _currentPalette[color].g, _currentPalette[color].b);
    1066                                 dst += 2;
    1067                                 width--;
    1068                         }
    1069                         src += _mouseCurState.w - w;
    1070                         bak += MAX_MOUSE_W - w;
    1071                         dst += _tmpscreen->pitch - w * 2;
    1072                         h--;
    1073                 }
     1150        dst = (byte *)_overlayscreen->pixels + (y + 1) * _overlayscreen->pitch + (x + 1) * 2;
     1151        while (h > 0) {
     1152                int width = w;
     1153                while (width > 0) {
     1154                        *bak++ = *(uint16 *)dst;
     1155                        color = *src++;
     1156                        if (color != _mouseKeycolor)    // transparent, don't draw
     1157                                *(uint16 *)dst = RGBToColor(_currentPalette[color].r, _currentPalette[color].g, _currentPalette[color].b);
     1158                        dst += 2;
     1159                        width--;
     1160                }
     1161                src += _mouseCurState.w - w;
     1162                bak += MAX_MOUSE_W - w;
     1163                dst += _overlayscreen->pitch - w * 2;
     1164                h--;
    10741165        }
    10751166
    1076         SDL_UnlockSurface(_overlayVisible ? _tmpscreen : _screen);
     1167        SDL_UnlockSurface(_overlayscreen);
    10771168
    10781169        // Finally, set the flag to indicate the mouse has been drawn
    10791170        _mouseDrawn = true;
     
    10841175                return;
    10851176        _mouseDrawn = false;
    10861177
    1087         if (SDL_LockSurface(_overlayVisible ? _tmpscreen : _screen) == -1)
     1178        if (SDL_LockSurface(_overlayscreen) == -1)
    10881179                error("SDL_LockSurface failed: %s", SDL_GetError());
    10891180
    10901181        int old_mouse_x = _mouseCurState.x - _mouseHotspotX;
     
    10921183        int old_mouse_w = _mouseCurState.w;
    10931184        int old_mouse_h = _mouseCurState.h;
    10941185
     1186        if (!_overlayVisible) {
     1187                old_mouse_x = Scr2Ovl(old_mouse_x);
     1188                old_mouse_y = Scr2Ovl(old_mouse_y);
     1189        }
     1190
    10951191        // clip the mouse rect, and addjust the src pointer accordingly
    10961192        if (old_mouse_x < 0) {
    10971193                old_mouse_w += old_mouse_x;
     
    11021198                old_mouse_y = 0;
    11031199        }
    11041200
    1105         if (old_mouse_w > _screenWidth - old_mouse_x)
    1106                 old_mouse_w = _screenWidth - old_mouse_x;
    1107         if (old_mouse_h > _screenHeight - old_mouse_y)
    1108                 old_mouse_h = _screenHeight - old_mouse_y;
     1201        if (old_mouse_w > _overlayWidth - old_mouse_x)
     1202                old_mouse_w = _overlayWidth - old_mouse_x;
     1203        if (old_mouse_h > _overlayHeight - old_mouse_y)
     1204                old_mouse_h = _overlayHeight - old_mouse_y;
    11091205
    11101206        // Quick check to see if anything has to be drawn at all
    11111207        if (old_mouse_w <= 0 || old_mouse_h <= 0)
     
    11131209
    11141210
    11151211        int x, y;
    1116         if (!_overlayVisible) {
    1117                 byte *dst, *bak = _mouseBackup;
    1118 
    1119                 // No need to do clipping here, since draw_mouse() did that already
    1120                 dst = (byte *)_screen->pixels + old_mouse_y * _screenWidth + old_mouse_x;
    1121                 for (y = 0; y < old_mouse_h; ++y, bak += MAX_MOUSE_W, dst += _screenWidth) {
    1122                         for (x = 0; x < old_mouse_w; ++x) {
    1123                                 dst[x] = bak[x];
    1124                         }
    1125                 }
     1212        byte *dst;
     1213        uint16 *bak = (uint16 *)_mouseBackup;
    11261214       
    1127         } else {
    1128 
    1129                 byte *dst;
    1130                 uint16 *bak = (uint16 *)_mouseBackup;
    1131        
    1132                 // No need to do clipping here, since draw_mouse() did that already
    1133                 dst = (byte *)_tmpscreen->pixels + (old_mouse_y + 1) * _tmpscreen->pitch + (old_mouse_x + 1) * 2;
    1134                 for (y = 0; y < old_mouse_h; ++y, bak += MAX_MOUSE_W, dst += _tmpscreen->pitch) {
    1135                         for (x = 0; x < old_mouse_w; ++x) {
    1136                                 *((uint16 *)dst + x) = bak[x];
    1137                         }
     1215        // No need to do clipping here, since draw_mouse() did that already
     1216        dst = (byte *)_overlayscreen->pixels + (old_mouse_y + 1) * _overlayscreen->pitch + (old_mouse_x + 1) * 2;
     1217        for (y = 0; y < old_mouse_h; ++y, bak += MAX_MOUSE_W, dst += _overlayscreen->pitch) {
     1218                for (x = 0; x < old_mouse_w; ++x) {
     1219                        *((uint16 *)dst + x) = bak[x];
    11381220                }
    11391221        }
    11401222
    1141         add_dirty_rect(old_mouse_x, old_mouse_y, old_mouse_w, old_mouse_h);
     1223        add_dirty_rect(Ovl2Scr(old_mouse_x), Ovl2Scr(old_mouse_y), Ovl2Scr(old_mouse_w), Ovl2Scr(old_mouse_h));
    11421224
    1143         SDL_UnlockSurface(_overlayVisible ? _tmpscreen : _screen);
     1225        SDL_UnlockSurface(_overlayscreen);
    11441226}
    11451227
    11461228
  • backends/sdl/sdl-common.h

    RCS file: /cvsroot/scummvm/scummvm/backends/sdl/sdl-common.h,v
    retrieving revision 1.62
    diff -u -r1.62 sdl-common.h
     
    4343
    4444        // Set the size of the video bitmap.
    4545        // Typically, 320x200
    46         void initSize(uint w, uint h);
     46        void initSize(uint w, uint h, uint overlayScale);
    4747
    4848        // Set colors of the palette
    4949        void setPalette(const byte *colors, uint start, uint num);
     
    5959
    6060        // Either show or hide the mouse cursor
    6161        bool showMouse(bool visible);
     62
     63        // Either scale or not the mouse cursor
     64        void cursorScaled(bool scale) { _cursorScaled = scale; }
    6265       
    6366        // Warp the mouse cursor. Where set_mouse_pos() only informs the
    6467        // backend of the mouse cursor's current position, this function
     
    120123        virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
    121124        virtual int16 getHeight();
    122125        virtual int16 getWidth();
     126        virtual int16 getOverlayHeight()  { return _overlayHeight; }
     127        virtual int16 getOverlayWidth()   { return _overlayWidth; }
     128        virtual OverlayColor overlayKeyColor() { return kOverlayColorKey; }
     129        virtual int Scr2Ovl(int x) { return x * _overlayScale; }
     130        virtual int Ovl2Scr(int x) { return x / _overlayScale; }
    123131
    124132        // Methods that convert RGB to/from colors suitable for the overlay.
    125133        virtual OverlayColor RGBToColor(uint8 r, uint8 g, uint8 b);
     
    165173        SDL_Surface *_screen;
    166174        int _screenWidth, _screenHeight;
    167175
    168         // temporary screen (for scalers/overlay)
     176        // temporary screens (for scalers)
    169177        SDL_Surface *_tmpscreen;
     178        SDL_Surface *_tmpscreen2;
     179
     180        // overlay
     181        SDL_Surface *_overlayscreen;
     182        int _overlayWidth, _overlayHeight;
     183        int _overlayScale;
    170184        bool _overlayVisible;
     185       
     186        enum {
     187                kOverlayColorKey = 1
     188        };
    171189
    172190        // Audio
    173191        int _samplesPerSec;
     
    222240        // mouse
    223241        bool _mouseVisible;
    224242        bool _mouseDrawn;
     243        bool _cursorScaled;
    225244        byte *_mouseData;
    226245        byte *_mouseBackup;
    227246        MousePos _mouseCurState;
  • backends/sdl/sdl.cpp

    RCS file: /cvsroot/scummvm/scummvm/backends/sdl/sdl.cpp,v
    retrieving revision 1.72
    diff -u -r1.72 sdl.cpp
     
    9494        _osdSurface(0), _osdAlpha(SDL_ALPHA_TRANSPARENT), _osdFadeStartTime(0),
    9595#endif
    9696        _hwscreen(0), _screen(0), _screenWidth(0), _screenHeight(0),
    97         _tmpscreen(0), _overlayVisible(false),
    98         _samplesPerSec(0),
     97        _tmpscreen(0), _overlayscreen(0), _overlayVisible(false),
     98        _tmpscreen2(0), _samplesPerSec(0),
    9999        _cdrom(0), _scaler_proc(0), _modeChanged(false), _dirty_checksums(0),
    100100        _mouseVisible(false), _mouseDrawn(false), _mouseData(0),
    101         _mouseHotspotX(0), _mouseHotspotY(0),
     101        _mouseHotspotX(0), _mouseHotspotY(0), _cursorScaled(true),
    102102        _currentShakePos(0), _newShakePos(0),
    103103        _paletteDirtyStart(0), _paletteDirtyEnd(0),
    104104        _graphicsMutex(0) {
  • base/main.cpp

    RCS file: /cvsroot/scummvm/scummvm/base/main.cpp,v
    retrieving revision 1.46
    diff -u -r1.46 main.cpp
     
    182182
    183183        // FIXME - we need to call initSize() here so that we can display for example
    184184        // the launcher dialog. But the Engine object will also call it again (possibly
    185         // with a different widht/height!9 However, this method is not for all OSystem
     185        // with a different widht/height! However, this method is not for all OSystem
    186186        // implementations reentrant (it is so now for the SDL backend). Thus we need
    187187        // to fix all backends to support it, if they don't already.
    188         system->initSize(320, 200);
     188        system->initSize(320, 200, 2);
    189189       
    190190        // FIXME - mouse cursors are currently always set via 8 bit data.
    191191        // Thus for now we need to setup a dummy palette. On the long run, we might
  • common/scaler.cpp

    RCS file: /cvsroot/scummvm/scummvm/common/scaler.cpp,v
    retrieving revision 1.63
    diff -u -r1.63 scaler.cpp
     
    170170}
    171171
    172172/**
     173 * Trivial nearest-neighbour 1.5x scaler.
     174 */
     175void Normal1o5x(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch,
     176                                                        int width, int height) {
     177        uint8 *r;
     178        const uint32 dstPitch2 = dstPitch * 2;
     179        const uint32 dstPitch3 = dstPitch * 3;
     180        const uint32 srcPitch2 = srcPitch * 2;
     181
     182        assert(((int)dstPtr & 1) == 0);
     183        while (height) {
     184                r = dstPtr;
     185                for (int i = 0; i < width; i += 2, r += 6) {
     186                        uint16 color0 = *(((const uint16 *)srcPtr) + i);
     187                        uint16 color1 = *(((const uint16 *)srcPtr) + i + 1);
     188                        uint16 color2 = *(((const uint16 *)(srcPtr + srcPitch)) + i);
     189                        uint16 color3 = *(((const uint16 *)(srcPtr + srcPitch)) + i + 1);
     190
     191                        *(uint16 *)(r + 0) = color0;
     192                        *(uint16 *)(r + 2) = color0;
     193                        *(uint16 *)(r + 4) = color1;
     194                        *(uint16 *)(r + 0 + dstPitch) = color0;
     195                        *(uint16 *)(r + 2 + dstPitch) = color0;
     196                        *(uint16 *)(r + 4 + dstPitch) = color1;
     197                        *(uint16 *)(r + 0 + dstPitch2) = color2;
     198                        *(uint16 *)(r + 2 + dstPitch2) = color2;
     199                        *(uint16 *)(r + 4 + dstPitch2) = color3;
     200                }
     201                srcPtr += srcPitch2;
     202                dstPtr += dstPitch3;
     203                height -= 2;
     204        }
     205}
     206
     207/**
    173208 * The Scale2x filter, also known as AdvMame2x.
    174209 * See also http://scale2x.sourceforge.net
    175210 */
  • common/scaler.h

    RCS file: /cvsroot/scummvm/scummvm/common/scaler.h,v
    retrieving revision 1.26
    diff -u -r1.26 scaler.h
     
    4040DECLARE_SCALER(AdvMame3x);
    4141DECLARE_SCALER(Normal1x);
    4242DECLARE_SCALER(Normal2x);
     43DECLARE_SCALER(Normal1o5x);
    4344DECLARE_SCALER(Normal3x);
    4445DECLARE_SCALER(TV2x);
    4546DECLARE_SCALER(DotMatrix);
  • common/system.h

    RCS file: /cvsroot/scummvm/scummvm/common/system.h,v
    retrieving revision 1.68
    diff -u -r1.68 system.h
     
    216216         * @param width         the new virtual screen width
    217217         * @param height        the new virtual screen height
    218218         */
    219         virtual void initSize(uint width, uint height) = 0;
     219        virtual void initSize(uint width, uint height, uint overlayScale = 1) = 0;
    220220
    221221        /**
    222222         * Returns the currently set virtual screen height.
     
    305305        virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) = 0;
    306306        virtual int16 getOverlayHeight()  { return getHeight(); }
    307307        virtual int16 getOverlayWidth()   { return getWidth(); }
     308        virtual OverlayColor overlayKeyColor() { return RGBToColor(0, 0, 0); }
     309        virtual int Scr2Ovl(int x) { return x; }
     310        virtual int Ovl2Scr(int x) { return x; }
    308311
    309312        /**
    310313        * Convert the given RGB triplet into an OverlayColor. A OverlayColor can
     
    340343        /** Show or hide the mouse cursor. */
    341344        virtual bool showMouse(bool visible) = 0;
    342345
     346        /** Scale or not the mouse cursor */
     347        virtual void cursorScaled(bool scale) { }
     348
    343349        /**
    344350         * Move ("warp") the mouse cursor to the specified position in virtual
    345351         * screen coordinates.
     
    435441                /**
    436442                 * The mouse coordinates, in virtual screen coordinates. Only valid
    437443                 * for mouse events.
    438                  * Virtual screen coordinatest means: the coordinate system of the
     444                 * Virtual screen coordinates mean: the coordinate system of the
    439445                 * screen area as defined by the most recent call to initSize().
    440446                 */
    441447                Common::Point mouse;
  • scumm/scumm.cpp

     Index: scumm/scumm.cpp
    RCS file: /cvsroot/scummvm/scummvm/scumm/scumm.cpp,v
    retrieving revision 1.131
    diff -u -r1.131 scumm.cpp
     
    808808        }
    809809
    810810        // Initialize backend
    811         syst->initSize(_screenWidth, _screenHeight);
     811        syst->initSize(_screenWidth, _screenHeight, 2);
     812        syst->cursorScaled((_features & GF_UNSCALED_CURSORS) == 0);
     813
    812814        int cd_num = ConfMan.getInt("cdrom");
    813815        if (cd_num >= 0 && (_features & GF_AUDIOTRACKS))
    814816                syst->openCD(cd_num);
     
    31953197                // specify correct version here
    31963198                if (game.features & GF_HUMONGOUS && (game.heversion == 60 || game.id == GID_PUTTDEMO)) {
    31973199                        game.heversion = 70;
    3198                         game.features |= GF_NEW_COSTUMES;
     3200                        game.features |= GF_NEW_COSTUMES | GF_UNSCALED_CURSORS;
    31993201                }
    32003202                break;
    32013203        case Common::kPlatformFMTowns:
  • scumm/scumm.h

    RCS file: /cvsroot/scummvm/scummvm/scumm/scumm.h,v
    retrieving revision 1.445
    diff -u -r1.445 scumm.h
     
    113113        GF_FEW_LOCALS          = 1 << 13,
    114114        GF_HUMONGOUS           = 1 << 14,
    115115        GF_MULTIPLE_VERSIONS   = 1 << 15,
     116        GF_UNSCALED_CURSORS    = 1 << 16,
    116117       
    117118        GF_FMTOWNS             = 1 << 17,
    118119        GF_AMIGA               = 1 << 18,