Ticket #8353: mouse.v5.diff

File mouse.v5.diff, 26.4 KB (added by sev-, 19 years ago)

Mouse on a separate surface v5 patch

  • backends/sdl/graphics.cpp

    RCS file: /cvsroot/scummvm/scummvm/backends/sdl/graphics.cpp,v
    retrieving revision 1.24
    diff -u -r1.24 graphics.cpp
     
    4242        {0, 0, 0}
    4343};
    4444
     45// Table of relative scalers magnitudes
     46// [definedScale-1][_scaleFactor-1]
     47static ScalerProc *scalersMagn[3][3] = {
     48        { Normal1x, AdvMame2x, AdvMame3x },
     49        { Normal1x, Normal1x, Normal1o5x },
     50        { Normal1x, Normal1x, Normal1x }
     51};
     52
     53static int cursorStretch200To240(uint8 *buf, uint32 pitch, int width, int height, int srcX, int srcY, int origSrcY);
     54
    4555const OSystem::GraphicsMode *OSystem_SDL::getSupportedGraphicsModes() const {
    4656        return s_supportedGraphicsModes;
    4757}
     
    367377        SDL_FreeSurface(old_screen);
    368378        SDL_FreeSurface(old_tmpscreen);
    369379
     380        // Update cursor to new scale
     381        blitCursor();
     382
    370383        // Blit everything to the screen
    371384        internUpdateScreen();
    372385       
     
    399412                _forceFull = true;
    400413        }
    401414
    402         // Make sure the mouse is drawn, if it should be drawn.
    403         drawMouse();
    404        
    405415        // Check whether the palette was changed in the meantime and update the
    406416        // screen surface accordingly.
    407417        if (_paletteDirtyEnd != 0) {
     
    434444        }
    435445#endif
    436446
     447        undrawMouse();
     448
    437449        // Force a full redraw if requested
    438450        if (_forceFull) {
    439451                _numDirtyRects = 1;
     
    527539                        SDL_BlitSurface(_osdSurface, 0, _hwscreen, 0);
    528540                }
    529541#endif
    530 
     542                drawMouse();
     543               
    531544                // Finally, blit all our changes to the screen
    532545                SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList);
     546        } else {
     547                drawMouse();
     548                if (_numDirtyRects)
     549                        SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList);
    533550        }
    534551
    535552        _numDirtyRects = 0;
     
    562579                assert(_hwscreen != 0);
    563580                _fullscreen ^= true;
    564581               
    565                 undrawMouse();
    566 
    567582#if defined(MACOSX) && !SDL_VERSION_ATLEAST(1, 2, 6)
    568583                // On OS X, SDL_WM_ToggleFullScreen is currently not implemented. Worse,
    569584                // before SDL 1.2.6 it always returned -1 (which would indicate a
     
    672687                addDirtyRect(x, y, w, h);
    673688        }
    674689
    675         /* FIXME: undraw mouse only if the draw rect intersects with the mouse rect */
    676         undrawMouse();
    677 
    678690        // Try to lock the screen surface
    679691        if (SDL_LockSurface(_screen) == -1)
    680692                error("SDL_LockSurface failed: %s", SDL_GetError());
     
    696708}
    697709
    698710
    699 void OSystem_SDL::addDirtyRect(int x, int y, int w, int h) {
     711void OSystem_SDL::addDirtyRect(int x, int y, int w, int h, bool mouseRect) {
    700712        if (_forceFull)
    701713                return;
    702714
     715        if (mouseRect) {
     716                SDL_Rect *r = &_dirtyRectList[_numDirtyRects++];
     717                r->x = x;
     718                r->y = y;
     719                r->w = w;
     720                r->h = h;
     721                return;
     722        }
     723
    703724        if (_numDirtyRects == NUM_DIRTY_RECT)
    704725                _forceFull = true;
    705726        else {
     
    846867
    847868        if (start + num > _paletteDirtyEnd)
    848869                _paletteDirtyEnd = start + num;
     870
     871        // Some games blink cursors with palette
     872        if (!_overlayVisible && !_cursorHasOwnPalette)
     873                blitCursor();
     874}
     875
     876void OSystem_SDL::setCursorPalette(const byte *colors, uint start, uint num) {
     877        const byte *b = colors;
     878        uint i;
     879        SDL_Color *base = _cursorPalette + start;
     880        for (i = 0; i < num; i++) {
     881                base[i].r = b[0];
     882                base[i].g = b[1];
     883                base[i].b = b[2];
     884                b += 4;
     885        }
     886
     887        _cursorHasOwnPalette = true;
     888
     889        if (!_overlayVisible)
     890                blitCursor();
    849891}
    850892
    851893void OSystem_SDL::setShakePos(int shake_pos) {
     
    862904void OSystem_SDL::showOverlay() {
    863905        assert (_transactionMode == kTransactionNone);
    864906
    865         // hide the mouse
    866         undrawMouse();
    867 
    868907        _overlayVisible = true;
    869908        clearOverlay();
    870909}
     
    872911void OSystem_SDL::hideOverlay() {
    873912        assert (_transactionMode == kTransactionNone);
    874913
    875         // hide the mouse
    876         undrawMouse();
    877 
    878914        _overlayVisible = false;
    879915        _forceFull = true;
    880916}
     
    887923       
    888924        Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
    889925       
    890         // hide the mouse
    891         undrawMouse();
    892 
    893926        // Clear the overlay by making the game screen "look through" everywhere.
    894927        SDL_Rect src, dst;
    895928        src.x = src.y = 0;
     
    911944        if (_tmpscreen == NULL)
    912945                return;
    913946
    914         // hide the mouse
    915         undrawMouse();
    916 
    917947        if (SDL_LockSurface(_tmpscreen) == -1)
    918948                error("SDL_LockSurface failed: %s", SDL_GetError());
    919949
     
    964994        _cksumValid = false;
    965995        addDirtyRect(x, y, w, h);
    966996
    967         /* FIXME: undraw mouse only if the draw rect intersects with the mouse rect */
    968         undrawMouse();
    969 
    970997        if (SDL_LockSurface(_tmpscreen) == -1)
    971998                error("SDL_LockSurface failed: %s", SDL_GetError());
    972999
     
    10001027        bool last = _mouseVisible;
    10011028        _mouseVisible = visible;
    10021029
    1003         if (visible)
    1004                 drawMouse();
    1005         else
    1006                 undrawMouse();
     1030        updateScreen();
    10071031
    10081032        return last;
    10091033}
    10101034
    10111035void OSystem_SDL::setMousePos(int x, int y) {
    10121036        if (x != _mouseCurState.x || y != _mouseCurState.y) {
    1013                 undrawMouse();
    10141037                _mouseCurState.x = x;
    10151038                _mouseCurState.y = y;
    10161039                updateScreen();
     
    10321055        }
    10331056}
    10341057       
    1035 void OSystem_SDL::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor) {
    1036 
    1037         undrawMouse();
    1038 
    1039         assert(w <= MAX_MOUSE_W);
    1040         assert(h <= MAX_MOUSE_H);
    1041         _mouseCurState.w = w;
    1042         _mouseCurState.h = h;
    1043 
     1058void OSystem_SDL::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor, int cursorTargetScale) {
    10441059        _mouseHotspotX = hotspot_x;
    10451060        _mouseHotspotY = hotspot_y;
    10461061
    10471062        _mouseKeyColor = keycolor;
    10481063
     1064        _cursorTargetScale = cursorTargetScale;
     1065 
     1066        if (_mouseCurState.w != (int)w || _mouseCurState.h != (int)h) {
     1067                _mouseCurState.w = w;
     1068                _mouseCurState.h = h;
     1069 
     1070                if (_mouseOrigSurface)
     1071                        SDL_FreeSurface(_mouseOrigSurface);
     1072 
     1073                // Allocate bigger surface because AdvMame2x adds black pixel at [0,0]
     1074                _mouseOrigSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
     1075                                                _mouseCurState.w + 2,
     1076                                                _mouseCurState.h + 2,
     1077                                                16,
     1078                                                _hwscreen->format->Rmask,
     1079                                                _hwscreen->format->Gmask,
     1080                                                _hwscreen->format->Bmask,
     1081                                                _hwscreen->format->Amask);
     1082 
     1083                if (_mouseOrigSurface == NULL)
     1084                        error("allocating _mouseOrigSurface failed");
     1085                SDL_SetColorKey(_mouseOrigSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey);
     1086        }
     1087 
    10491088        free(_mouseData);
    10501089
    10511090        _mouseData = (byte *)malloc(w * h);
    10521091        memcpy(_mouseData, buf, w * h);
     1092        blitCursor();
    10531093}
    10541094
    1055 void OSystem_SDL::toggleMouseGrab() {
    1056         if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF)
    1057                 SDL_WM_GrabInput(SDL_GRAB_ON);
    1058         else
    1059                 SDL_WM_GrabInput(SDL_GRAB_OFF);
    1060 }
    1061 
    1062 void OSystem_SDL::drawMouse() {
    1063         if (_mouseDrawn || !_mouseVisible || !_mouseData)
    1064                 return;
    1065 
    1066         int x = _mouseCurState.x - _mouseHotspotX;
    1067         int y = _mouseCurState.y - _mouseHotspotY;
    1068         int w = _mouseCurState.w;
    1069         int h = _mouseCurState.h;
     1095void OSystem_SDL::blitCursor() {
     1096        byte *dstPtr;
     1097        const byte *srcPtr = _mouseData;
    10701098        byte color;
    1071         const byte *src = _mouseData;           // Image representing the mouse
    1072        
    1073         // clip the mouse rect, and addjust the src pointer accordingly
    1074         if (x < 0) {
    1075                 w += x;
    1076                 src -= x;
    1077                 x = 0;
    1078         }
    1079         if (y < 0) {
    1080                 h += y;
    1081                 src -= y * _mouseCurState.w;
    1082                 y = 0;
     1099        int w, h;
     1100 
     1101        if (!_mouseOrigSurface)
     1102                return;
     1103 
     1104        w = _mouseCurState.w;
     1105        h = _mouseCurState.h;
     1106 
     1107        SDL_LockSurface(_mouseOrigSurface);
     1108
     1109        // Make whole surface transparent
     1110        for (int i = 0; i < h + 2; i++) {
     1111                dstPtr = (byte *)_mouseOrigSurface->pixels + _mouseOrigSurface->pitch * i;
     1112                for (int j = 0; j < w + 2; j++) {
     1113                        *(uint16 *)dstPtr = kMouseColorKey;
     1114                        dstPtr += 2;
     1115                }
    10831116        }
    10841117
    1085         if (w > _screenWidth - x)
    1086                 w = _screenWidth - x;
    1087         if (h > _screenHeight - y)
    1088                 h = _screenHeight - y;
    1089 
    1090         // Quick check to see if anything has to be drawn at all
    1091         if (w <= 0 || h <= 0)
    1092                 return;
    1093 
    1094         // Draw the mouse cursor; backup the covered area in "bak"
    1095         if (SDL_LockSurface(_overlayVisible ? _tmpscreen : _screen) == -1)
    1096                 error("SDL_LockSurface failed: %s", SDL_GetError());
    1097 
    1098         // Mark as dirty
    1099         addDirtyRect(x, y, w, h);
    1100 
    1101         if (!_overlayVisible) {
    1102                 byte *bak = _mouseBackup;               // Surface used to backup the area obscured by the mouse
    1103                 byte *dst;                                      // Surface we are drawing into
    1104        
    1105                 dst = (byte *)_screen->pixels + y * _screenWidth + x;
    1106                 while (h > 0) {
    1107                         int width = w;
    1108                         while (width > 0) {
    1109                                 *bak++ = *dst;
    1110                                 color = *src++;
    1111                                 if (color != _mouseKeyColor)    // transparent, don't draw
    1112                                         *dst = color;
    1113                                 dst++;
    1114                                 width--;
     1118        // Draw from [1,1] since AdvMame2x adds artefact at 0,0
     1119        dstPtr = (byte *)_mouseOrigSurface->pixels + _mouseOrigSurface->pitch + 2;
     1120
     1121        for (int i = 0; i < h; i++) {
     1122                for (int j = 0; j < w; j++) {
     1123                        color = *srcPtr;
     1124                        if (color != _mouseKeyColor) {  // transparent, don't draw
     1125                                if (_cursorHasOwnPalette && !_overlayVisible)
     1126                                        *(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format,
     1127                                                                   _cursorPalette[color].r, _cursorPalette[color].g,
     1128                                                                                                                           _cursorPalette[color].b);
     1129                                else
     1130                                        *(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format,
     1131                                                                   _currentPalette[color].r, _currentPalette[color].g,
     1132                                                                                                                                _currentPalette[color].b);
    11151133                        }
    1116                         src += _mouseCurState.w - w;
    1117                         bak += MAX_MOUSE_W - w;
    1118                         dst += _screenWidth - w;
    1119                         h--;
     1134                        dstPtr += 2;
     1135                        srcPtr++;
    11201136                }
    1121        
     1137                dstPtr += _mouseOrigSurface->pitch - w * 2;
     1138        }
     1139
     1140        int hW, hH, hH1;
     1141
     1142        if (_cursorTargetScale >= _scaleFactor) {
     1143                hW = w;
     1144                hH = hH1 = h;
    11221145        } else {
    1123                 uint16 *bak = (uint16 *)_mouseBackup;   // Surface used to backup the area obscured by the mouse
    1124                 byte *dst;                                      // Surface we are drawing into
    1125        
    1126                 dst = (byte *)_tmpscreen->pixels + (y + 1) * _tmpscreen->pitch + (x + 1) * 2;
    1127                 while (h > 0) {
    1128                         int width = w;
    1129                         while (width > 0) {
    1130                                 *bak++ = *(uint16 *)dst;
    1131                                 color = *src++;
    1132                                 if (color != 0xFF)      // 0xFF = transparent, don't draw
    1133                                         *(uint16 *)dst = RGBToColor(_currentPalette[color].r, _currentPalette[color].g, _currentPalette[color].b);
    1134                                 dst += 2;
    1135                                 width--;
    1136                         }
    1137                         src += _mouseCurState.w - w;
    1138                         bak += MAX_MOUSE_W - w;
    1139                         dst += _tmpscreen->pitch - w * 2;
    1140                         h--;
    1141                 }
     1146                hW = w * _scaleFactor / _cursorTargetScale;
     1147                hH = hH1 = h * _scaleFactor / _cursorTargetScale;
     1148        }
     1149 
     1150        if (_adjustAspectRatio) {
     1151                hH = real2Aspect(hH - 1) + 1;
     1152        }
     1153 
     1154        if (_mouseCurState.hW != hW || _mouseCurState.hH != hH) {
     1155                _mouseCurState.hW = hW;
     1156                _mouseCurState.hH = hH;
     1157 
     1158                if (_mouseSurface)
     1159                        SDL_FreeSurface(_mouseSurface);
     1160 
     1161                _mouseSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
     1162                                                _mouseCurState.hW,
     1163                                                _mouseCurState.hH,
     1164                                                16,
     1165                                                _hwscreen->format->Rmask,
     1166                                                _hwscreen->format->Gmask,
     1167                                                _hwscreen->format->Bmask,
     1168                                                _hwscreen->format->Amask);
     1169 
     1170                if (_mouseSurface == NULL)
     1171                        error("allocating _mouseSurface failed");
     1172
     1173                SDL_SetColorKey(_mouseSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey);
     1174        }
     1175 
     1176        SDL_LockSurface(_mouseSurface);
     1177        (scalersMagn[_cursorTargetScale-1][_scaleFactor-1])((byte *)_mouseOrigSurface->pixels + _mouseOrigSurface->pitch + 2,
     1178                _mouseOrigSurface->pitch, (byte *)_mouseSurface->pixels, _mouseSurface->pitch,
     1179                          _mouseCurState.w, _mouseCurState.h);
     1180
     1181        if (_adjustAspectRatio)
     1182                cursorStretch200To240((uint8 *)_mouseSurface->pixels, _mouseSurface->pitch, hW, hH1, 0, 0, 0);
     1183 
     1184        SDL_UnlockSurface(_mouseSurface);
     1185        SDL_UnlockSurface(_mouseOrigSurface);
     1186}
     1187
     1188// Basically it is kVeryFastAndUglyAspectMode of stretch200To240 from
     1189// common/scale/aspect.cpp
     1190static int cursorStretch200To240(uint8 *buf, uint32 pitch, int width, int height, int srcX, int srcY, int origSrcY) {
     1191        int maxDstY = real2Aspect(origSrcY + height - 1);
     1192        int y;
     1193        const uint8 *startSrcPtr = buf + srcX * 2 + (srcY - origSrcY) * pitch;
     1194        uint8 *dstPtr = buf + srcX * 2 + maxDstY * pitch;
     1195
     1196        for (y = maxDstY; y >= srcY; y--) {
     1197                const uint8 *srcPtr = startSrcPtr + aspect2Real(y) * pitch;
     1198
     1199                if (srcPtr == dstPtr)
     1200                        break;
     1201                memcpy(dstPtr, srcPtr, width * 2);
     1202                dstPtr -= pitch;
    11421203        }
    11431204
    1144         SDL_UnlockSurface(_overlayVisible ? _tmpscreen : _screen);
     1205        return 1 + maxDstY - srcY;
     1206}
    11451207
    1146         // Finally, set the flag to indicate the mouse has been drawn
    1147         _mouseDrawn = true;
     1208void OSystem_SDL::toggleMouseGrab() {
     1209        if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF)
     1210                SDL_WM_GrabInput(SDL_GRAB_ON);
     1211        else
     1212                SDL_WM_GrabInput(SDL_GRAB_OFF);
    11481213}
    11491214
    11501215void OSystem_SDL::undrawMouse() {
    1151         assert (_transactionMode == kTransactionNone || _transactionMode == kTransactionCommit);
    1152 
    1153         if (!_mouseDrawn)
    1154                 return;
    1155         _mouseDrawn = false;
    1156 
    1157         int old_mouse_x = _mouseCurState.x - _mouseHotspotX;
    1158         int old_mouse_y = _mouseCurState.y - _mouseHotspotY;
    1159         int old_mouse_w = _mouseCurState.w;
    1160         int old_mouse_h = _mouseCurState.h;
    1161 
    1162         // clip the mouse rect, and addjust the src pointer accordingly
    1163         if (old_mouse_x < 0) {
    1164                 old_mouse_w += old_mouse_x;
    1165                 old_mouse_x = 0;
    1166         }
    1167         if (old_mouse_y < 0) {
    1168                 old_mouse_h += old_mouse_y;
    1169                 old_mouse_y = 0;
    1170         }
    1171 
    1172         if (old_mouse_w > _screenWidth - old_mouse_x)
    1173                 old_mouse_w = _screenWidth - old_mouse_x;
    1174         if (old_mouse_h > _screenHeight - old_mouse_y)
    1175                 old_mouse_h = _screenHeight - old_mouse_y;
    1176 
    1177         // Quick check to see if anything has to be drawn at all
    1178         if (old_mouse_w <= 0 || old_mouse_h <= 0)
    1179                 return;
     1216        if (_mouseBackup.w) {
     1217                if (_adjustAspectRatio)
     1218                        addDirtyRect(_mouseBackup.x, aspect2Real(_mouseBackup.y), _mouseBackup.w,
     1219                                                   _mouseBackup.h);
     1220                else
     1221                        addDirtyRect(_mouseBackup.x, _mouseBackup.y, _mouseBackup.w,
     1222                                                   _mouseBackup.h);
     1223        }
     1224}
    11801225
    1181         if (SDL_LockSurface(_overlayVisible ? _tmpscreen : _screen) == -1)
    1182                 error("SDL_LockSurface failed: %s", SDL_GetError());
     1226void OSystem_SDL::drawMouse() {
     1227        if (!_mouseVisible) {
     1228                _mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0;
     1229                return;
     1230        }
     1231 
     1232        SDL_Rect src, dst;
     1233        bool scale;
    11831234
    1184         int x, y;
    1185         if (!_overlayVisible) {
    1186                 byte *dst, *bak = _mouseBackup;
    1187 
    1188                 // No need to do clipping here, since drawMouse() did that already
    1189                 dst = (byte *)_screen->pixels + old_mouse_y * _screenWidth + old_mouse_x;
    1190                 for (y = 0; y < old_mouse_h; ++y, bak += MAX_MOUSE_W, dst += _screenWidth) {
    1191                         for (x = 0; x < old_mouse_w; ++x) {
    1192                                 dst[x] = bak[x];
    1193                         }
    1194                 }
    1195        
    1196         } else {
     1235        scale = (_scaleFactor > _cursorTargetScale);
    11971236
    1198                 byte *dst;
    1199                 uint16 *bak = (uint16 *)_mouseBackup;
    1200        
    1201                 // No need to do clipping here, since drawMouse() did that already
    1202                 dst = (byte *)_tmpscreen->pixels + (old_mouse_y + 1) * _tmpscreen->pitch + (old_mouse_x + 1) * 2;
    1203                 for (y = 0; y < old_mouse_h; ++y, bak += MAX_MOUSE_W, dst += _tmpscreen->pitch) {
    1204                         for (x = 0; x < old_mouse_w; ++x) {
    1205                                 *((uint16 *)dst + x) = bak[x];
    1206                         }
    1207                 }
    1208         }
     1237        dst.x = _mouseCurState.x - _mouseHotspotX / _cursorTargetScale;
     1238        dst.y = _mouseCurState.y - _mouseHotspotY / _cursorTargetScale;
    12091239
    1210         addDirtyRect(old_mouse_x, old_mouse_y, old_mouse_w, old_mouse_h);
     1240        dst.w = _mouseCurState.hW;
     1241        dst.h = _mouseCurState.hH;
     1242        src.x = src.y = 0;
    12111243
    1212         SDL_UnlockSurface(_overlayVisible ? _tmpscreen : _screen);
     1244        // clip the mouse rect, and adjust the src pointer accordingly
     1245        int dx, dy;
     1246 
     1247        dx = dst.x; dy = dst.y;
     1248        dx = scale ? dst.x * _scaleFactor / _cursorTargetScale : dst.x;
     1249        dy = scale ? dst.y * _scaleFactor / _cursorTargetScale : dst.y;
     1250        if (_adjustAspectRatio)
     1251                dy = real2Aspect(dy);
     1252
     1253        if (dst.x < 0) {
     1254                dst.w += dx;
     1255                src.x -= dx;
     1256                dst.x = 0;
     1257        }
     1258        if (dst.y < 0) {
     1259                dst.h += dy;
     1260                src.y -= dy;
     1261                dst.y = 0;
     1262        }
     1263
     1264        // Quick check to see if anything has to be drawn at all
     1265        if (dst.w <= 0 || dst.h <= 0)
     1266                return;
     1267 
     1268        src.w = dst.w;
     1269        src.h = dst.h;
     1270 
     1271        if (_adjustAspectRatio)
     1272                dst.y = real2Aspect(dst.y);
     1273 
     1274        _mouseBackup.x = dst.x;
     1275        _mouseBackup.y = dst.y;
     1276        _mouseBackup.w = dst.w;
     1277        _mouseBackup.h = dst.h;
     1278 
     1279        dst.x *= _scaleFactor;
     1280        dst.y *= _scaleFactor;
     1281 
     1282        if (SDL_BlitSurface(_mouseSurface, &src, _hwscreen, &dst) != 0)
     1283                error("SDL_BlitSurface failed: %s", SDL_GetError());
     1284 
     1285        addDirtyRect(dst.x, dst.y, dst.w, dst.h, true);
    12131286}
    12141287
    1215 
    12161288#pragma mark -
    12171289#pragma mark --- Mouse ---
    12181290#pragma mark -
  • backends/sdl/sdl-common.h

    RCS file: /cvsroot/scummvm/scummvm/backends/sdl/sdl-common.h,v
    retrieving revision 1.71
    diff -u -r1.71 sdl-common.h
     
    8282        virtual void warpMouse(int x, int y); // overloaded by CE backend
    8383
    8484        // Set the bitmap that's used when drawing the cursor.
    85         void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor);
     85        void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor, int cursorTargetScale);
     86
     87        // Set colors of cursor palette
     88        void setCursorPalette(const byte *colors, uint start, uint num);
    8689
    8790        // Shaking is used in SCUMM. Set current shake position.
    8891        void setShakePos(int shake_pos);
     
    258261        };
    259262
    260263        struct MousePos {
    261                 int16 x, y, w, h;
     264                int16 x, y, w, h, hW, hH;
     265                MousePos() : x(0), y(0), w(0), h(0), hW(0), hH(0) {}
    262266        };
    263267
    264268        // mouse
     
    266270        bool _mouseVisible;
    267271        bool _mouseDrawn;
    268272        byte *_mouseData;
    269         byte *_mouseBackup;
     273        SDL_Rect _mouseBackup;
    270274        MousePos _mouseCurState;
    271275        int16 _mouseHotspotX;
    272276        int16 _mouseHotspotY;
    273277        byte _mouseKeyColor;
     278        int _cursorTargetScale;
     279        bool _cursorHasOwnPalette;
     280        SDL_Surface *_mouseOrigSurface;
     281        SDL_Surface *_mouseSurface;
     282        enum {
     283                kMouseColorKey = 1
     284        };
    274285
    275286        // joystick
    276287        SDL_Joystick *_joystick;
     
    283294        SDL_Color *_currentPalette;
    284295        uint _paletteDirtyStart, _paletteDirtyEnd;
    285296       
     297        // Cursor palette data
     298        SDL_Color *_cursorPalette;
     299       
    286300        /**
    287301         * Mutex which prevents multiple threads from interfering with each other
    288302         * when accessing the screen.
     
    293307        void addDirtyRgnAuto(const byte *buf);
    294308        void makeChecksums(const byte *buf);
    295309       
    296         virtual void addDirtyRect(int x, int y, int w, int h); // overloaded by CE backend
     310        virtual void addDirtyRect(int x, int y, int w, int h, bool mouseRect = false); // overloaded by CE backend
    297311
    298312        virtual void drawMouse(); // overloaded by CE backend
    299313        virtual void undrawMouse(); // overloaded by CE backend
     314        void blitCursor();
    300315       
    301316        /** Set the position of the virtual mouse cursor. */
    302317        void setMousePos(int x, int y);
  • backends/sdl/sdl.cpp

    RCS file: /cvsroot/scummvm/scummvm/backends/sdl/sdl.cpp,v
    retrieving revision 1.78
    diff -u -r1.78 sdl.cpp
     
    100100        _tmpscreen(0), _overlayVisible(false),
    101101        _samplesPerSec(0),
    102102        _cdrom(0), _scalerProc(0), _modeChanged(false), _dirtyChecksums(0),
    103         _mouseVisible(false), _mouseDrawn(false), _mouseData(0),
    104         _mouseHotspotX(0), _mouseHotspotY(0),
     103        _mouseVisible(false), _mouseDrawn(false), _mouseData(0), _mouseSurface(0),
     104        _mouseOrigSurface(0), _mouseHotspotX(0), _mouseHotspotY(0), _cursorTargetScale(1),
     105        _cursorHasOwnPalette(false),
    105106        _joystick(0),
    106107        _currentShakePos(0), _newShakePos(0),
    107108        _paletteDirtyStart(0), _paletteDirtyEnd(0),
     
    109110
    110111        // allocate palette storage
    111112        _currentPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256);
     113        _cursorPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256);
    112114
    113         // allocate the dirty rect storage
    114         _mouseBackup = (byte *)malloc(MAX_MOUSE_W * MAX_MOUSE_H * MAX_SCALING * 2);
     115        _mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0;
    115116
    116117        // reset mouse state
    117118        memset(&_km, 0, sizeof(_km));
     
    123124OSystem_SDL::~OSystem_SDL() {
    124125        free(_dirtyChecksums);
    125126        free(_currentPalette);
    126         free(_mouseBackup);
     127        free(_cursorPalette);
    127128        free(_mouseData);
    128129}
    129130
     
    147148        return
    148149                (f == kFeatureFullscreenMode) ||
    149150                (f == kFeatureAspectRatioCorrection) ||
    150                 (f == kFeatureAutoComputeDirtyRects);
     151                (f == kFeatureAutoComputeDirtyRects) ||
     152                (f == kFeatureCursorHasPalette);
    151153}
    152154
    153155void OSystem_SDL::setFeatureState(Feature f, bool enable) {
  • common/scaler.cpp

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

    RCS file: /cvsroot/scummvm/scummvm/common/scaler.h,v
    retrieving revision 1.27
    diff -u -r1.27 scaler.h
     
    4141DECLARE_SCALER(Normal1x);
    4242DECLARE_SCALER(Normal2x);
    4343DECLARE_SCALER(Normal3x);
     44DECLARE_SCALER(Normal1o5x);
    4445DECLARE_SCALER(TV2x);
    4546DECLARE_SCALER(DotMatrix);
    4647DECLARE_SCALER(HQ2x);
  • common/system.h

    RCS file: /cvsroot/scummvm/scummvm/common/system.h,v
    retrieving revision 1.86
    diff -u -r1.86 system.h
     
    9696                 * Implementing this is purely optional, and no harm should arise
    9797                 * when not doing so (except for decreased speed in said frontends).
    9898                 */
    99                 kFeatureAutoComputeDirtyRects
     99                kFeatureAutoComputeDirtyRects,
     100
     101                /**
     102                 * This flags determines either cursor can have its own palette or not
     103                 * It is currently used only by some Macintosh versions of Humongous
     104                 * Entertainment games. If backend doesn't implement this feature then
     105                 * engine switches to b/w version of cursors.
     106                 */
     107                kFeatureCursorHasPalette
    100108        };
    101109       
    102110        /**
     
    274282        virtual void setPalette(const byte *colors, uint start, uint num) = 0;
    275283
    276284        /**
     285         * Replace the specified range of cursor the palette with new colors.
     286         * The palette entries from 'start' till (start+num-1) will be replaced - so
     287         * a full palette update is accomplished via start=0, num=256.
     288         *
     289         * Backends which implement it should have kFeatureCursorHasPalette flag set
     290         *
     291         * @see setPalette
     292         * @see kFeatureCursorHasPalette
     293         */
     294        virtual void setCursorPalette(const byte *colors, uint start, uint num) {};
     295
     296        /**
    277297         * Blit a bitmap to the virtual screen.
    278298         * The real screen will not immediately be updated to reflect the changes.
    279299         * Client code has to to call updateScreen to ensure any changes are
     
    365385        /**
    366386         * Set the bitmap used for drawing the cursor.
    367387         *
    368          * @param buf           the pixmap data to be used (8bit/pixel)
    369          * @param w                     width of the mouse cursor
    370          * @param h                     height of the mouse cursor
    371          * @param hotspotX      horizontal offset from the left side to the hotspot
    372          * @param hotspotY      vertical offset from the top side to the hotspot
    373          * @param keycolor      transparency color index
     388         * @param buf                           the pixmap data to be used (8bit/pixel)
     389         * @param w                                     width of the mouse cursor
     390         * @param h                                     height of the mouse cursor
     391         * @param hotspotX                      horizontal offset from the left side to the hotspot
     392         * @param hotspotY                      vertical offset from the top side to the hotspot
     393         * @param keycolor                      transparency color index
     394         * @param cursorTargetScale     scale factor which cursor is designed for
    374395         */
    375         virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255) = 0;
     396        virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255, int cursorTargetScale = 1) = 0;
    376397
    377398        //@}
    378399
  • scumm/cursor.cpp

    RCS file: /cvsroot/scummvm/scummvm/scumm/cursor.cpp,v
    retrieving revision 2.27
    diff -u -r2.27 cursor.cpp
     
    107107
    108108void ScummEngine::updateCursor() {
    109109        _system->setMouseCursor(_grabbedCursor, _cursor.width, _cursor.height,
    110                                                         _cursor.hotspotX, _cursor.hotspotY);
     110                                                        _cursor.hotspotX, _cursor.hotspotY, 255,
     111                                                        (_heversion == 70 ? 2 : 1));
    111112}
    112113
    113114void ScummEngine_v6::grabCursor(int x, int y, int w, int h) {
  • scumm/resource_v7he.cpp

    RCS file: /cvsroot/scummvm/scummvm/scumm/resource_v7he.cpp,v
    retrieving revision 1.19
    diff -u -r1.19 resource_v7he.cpp
     
    15321532        *hotspot_x = dis.readUint16BE();
    15331533        *w = *h = 16;
    15341534
    1535         // FIXME
    1536         // Color cursors use their own palette.
    1537         // So we can't use it for now and use B/W version
    1538         return;
     1535        // Use b/w cursor on backends which don't support cursor palettes
     1536        if (!_vm->_system->hasFeature(OSystem::kFeatureCursorHasPalette))
     1537                return;
    15391538
    15401539        dis.readUint32BE(); // reserved
    15411540        dis.readUint32BE(); // cursorID
     
    16001599                palette[c * 4 + 3] = 0;
    16011600        }
    16021601
    1603         // TODO: Here we should set separate cursor palette.
    1604         // It requires cursor to be rendered on a different surface at
    1605         // least in SDL backend.
    1606         // HACK: now set global palett just to see if colors are correct.
    1607         // this affects subtitles colors
    1608         _vm->_system->setPalette(palette, 0, ctSize);
     1602        _vm->_system->setCursorPalette(palette, 0, ctSize);
    16091603
    16101604        numBytes =
    16111605         (iconBounds[2] - iconBounds[0]) *