Ticket #8405: thumbnail-v4-2pre1.patch

File thumbnail-v4-2pre1.patch, 33.6 KB (added by lordhoto, 16 years ago)

new standalone patch

  • backends/sdl/graphics.cpp

    diff -d -u --rec -N --exclude=CVS scummvm.old/backends/sdl/graphics.cpp scummvm/backends/sdl/graphics.cpp
    old new  
    2525#include "common/util.h"
    2626#include "graphics/font.h"
    2727#include "graphics/fontman.h"
     28#include "graphics/surface.h"
    2829
    2930static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
    3031        {"1x", "Normal (no scaling)", GFX_NORMAL},
     
    800801        SDL_UnlockSurface(_screen);
    801802}
    802803
     804void OSystem_SDL::grabRawScreen(Graphics::Surface *surf) {
     805        assert(_screen);
     806        assert(surf);
     807       
     808        Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
     809       
     810        surf->create(_screenWidth, _screenHeight, _screen->format->BytesPerPixel);
     811       
     812        // Try to lock the screen surface
     813        if (SDL_LockSurface(_screen) == -1)
     814                error("SDL_LockSurface failed: %s", SDL_GetError());
     815       
     816        memcpy(surf->pixels, _screen->pixels, _screenWidth * _screenHeight * _screen->format->BytesPerPixel);
     817       
     818        // Unlock the screen surface
     819        SDL_UnlockSurface(_screen);
     820}
    803821
    804822void OSystem_SDL::addDirtyRect(int x, int y, int w, int h, bool mouseRect) {
    805823        if (_forceFull)
     
    9821000        // Some games blink cursors with palette
    9831001        if (!_overlayVisible && (!_cursorHasOwnPalette || _cursorPaletteDisabled))
    9841002                blitCursor();
     1003}
     1004
     1005void OSystem_SDL::grabPalette(byte *colors, uint start, uint num) {
     1006        assert(colors);
     1007        const SDL_Color *base = _currentPalette + start;
     1008       
     1009        for (uint i = 0; i < num; ++i) {
     1010                colors[i * 4] = base[i].r;
     1011                colors[i * 4 + 1] = base[i].g;
     1012                colors[i * 4 + 2] = base[i].b;
     1013                colors[i * 4 + 3] = 0xFF;
     1014        }
    9851015}
    9861016
    9871017void OSystem_SDL::setCursorPalette(const byte *colors, uint start, uint num) {
  • backends/sdl/sdl-common.h

    diff -d -u --rec -N --exclude=CVS scummvm.old/backends/sdl/sdl-common.h scummvm/backends/sdl/sdl-common.h
    old new  
    7878
    7979        // Set colors of the palette
    8080        void setPalette(const byte *colors, uint start, uint num);
     81       
     82        // Get colors of the palette
     83        void grabPalette(byte *colors, uint start, uint num);
    8184
    8285        // Draw a bitmap to screen.
    8386        // The screen will not be updated to reflect the new bitmap
    8487        void copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h);
     88
     89        // Copies the screen to a buffer
     90        void grabRawScreen(Graphics::Surface *surf);
    8591
    8692        // Clear the screen
    8793        void clearScreen();
  • common/module.mk

    diff -d -u --rec -N --exclude=CVS scummvm.old/common/module.mk scummvm/common/module.mk
    old new  
    2121        common/scaler/hq3x.o \
    2222        common/scaler/scale2x.o \
    2323        common/scaler/scale3x.o \
    24         common/scaler/scalebit.o
     24        common/scaler/scalebit.o \
     25        common/scaler/thumbnail.o
    2526
    2627ifdef HAVE_NASM
    2728MODULE_OBJS += \
  • common/scaler/thumbnail.cpp

    diff -d -u --rec -N --exclude=CVS scummvm.old/common/scaler/thumbnail.cpp scummvm/common/scaler/thumbnail.cpp
    old new  
     1/* ScummVM - Scumm Interpreter
     2 * Copyright (C) 2001  Ludvig Strigeus
     3 * Copyright (C) 2001-2005 The ScummVM project
     4 *
     5 * This program is free software; you can redistribute it and/or
     6 * modify it under the terms of the GNU General Public License
     7 * as published by the Free Software Foundation; either version 2
     8 * of the License, or (at your option) any later version.
     9
     10 * This program is distributed in the hope that it will be useful,
     11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 * GNU General Public License for more details.
     14
     15 * You should have received a copy of the GNU General Public License
     16 * along with this program; if not, write to the Free Software
     17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 *
     19 * $Header: $
     20 *
     21 */
     22
     23#include "stdafx.h"
     24#include "common/scummsys.h"
     25#include "common/system.h"
     26
     27#include "scaler.h"
     28#include "scaler/intern.h"
     29
     30template<int bitFormat>
     31void createThumbnail_2(const uint8* src, uint32 srcPitch, uint8* dstPtr, uint32 dstPitch, int width, int height) {
     32        for (int y = 0; y < height; y += 2) {
     33                for (int x = 0; x < width; x += 2, dstPtr += 2) {
     34                        uint16 colorx1y1 = *(((const uint16*)src) + x);
     35                        uint16 colorx2y1 = *(((const uint16*)src) + x + 1);
     36                       
     37                        uint16 colorx1y2 = *(((const uint16*)(src + srcPitch)) + x);
     38                        uint16 colorx2y2 = *(((const uint16*)(src + srcPitch)) + x + 1);
     39                               
     40                        *((uint16*)dstPtr) = Q_INTERPOLATE<bitFormat>(colorx1y1, colorx2y1, colorx1y2, colorx2y2);                     
     41                }
     42                dstPtr += (dstPitch - 320);
     43                src += 2 * srcPitch;
     44        }
     45}
     46
     47template<int bitFormat>
     48void createThumbnail_4(const uint8* src, uint32 srcPitch, uint8* dstPtr, uint32 dstPitch, int width, int height) {
     49        for (int y = 0; y < height; y += 4) {
     50                for (int x = 0; x < width; x += 4, dstPtr += 2) {
     51                        uint16 colorx1y1 = *(((const uint16*)src) + x);
     52                        uint16 colorx2y1 = *(((const uint16*)src) + x + 1);
     53                        uint16 colorx3y1 = *(((const uint16*)src) + x + 2);
     54                        uint16 colorx4y1 = *(((const uint16*)src) + x + 3);
     55                       
     56                        uint16 colorx1y2 = *(((const uint16*)(src + srcPitch)) + x);
     57                        uint16 colorx2y2 = *(((const uint16*)(src + srcPitch)) + x + 1);
     58                        uint16 colorx3y2 = *(((const uint16*)(src + srcPitch)) + x + 2);
     59                        uint16 colorx4y2 = *(((const uint16*)(src + srcPitch)) + x + 3);
     60                       
     61                        uint16 colorx1y3 = *(((const uint16*)(src + srcPitch * 2)) + x);
     62                        uint16 colorx2y3 = *(((const uint16*)(src + srcPitch * 2)) + x + 1);
     63                        uint16 colorx3y3 = *(((const uint16*)(src + srcPitch * 2)) + x + 2);
     64                        uint16 colorx4y3 = *(((const uint16*)(src + srcPitch * 2)) + x + 3);
     65                       
     66                        uint16 colorx1y4 = *(((const uint16*)(src + srcPitch * 3)) + x);
     67                        uint16 colorx2y4 = *(((const uint16*)(src + srcPitch * 3)) + x + 1);
     68                        uint16 colorx3y4 = *(((const uint16*)(src + srcPitch * 3)) + x + 2);
     69                        uint16 colorx4y4 = *(((const uint16*)(src + srcPitch * 3)) + x + 3);
     70                       
     71                        uint16 upleft = Q_INTERPOLATE<bitFormat>(colorx1y1, colorx2y1, colorx1y2, colorx2y2);
     72                        uint16 upright = Q_INTERPOLATE<bitFormat>(colorx3y1, colorx4y1, colorx3y2, colorx4y2);
     73                        uint16 downleft = Q_INTERPOLATE<bitFormat>(colorx1y3, colorx2y3, colorx1y4, colorx2y4);
     74                        uint16 downright = Q_INTERPOLATE<bitFormat>(colorx3y3, colorx4y3, colorx3y4, colorx4y4);
     75                               
     76                        *((uint16*)dstPtr) = Q_INTERPOLATE<bitFormat>(upleft, upright, downleft, downright);                   
     77                }
     78                dstPtr += (dstPitch - 320);
     79                src += 4 * srcPitch;
     80        }
     81}
     82
     83void createThumbnail(const uint8* src, uint32 srcPitch, uint8* dstPtr, uint32 dstPitch, int width, int height) {
     84        // only 1/2 and 1/4 downscale supported
     85        if (width != 320 && width != 640)
     86                return;
     87       
     88        int downScaleMode = (width == 320) ? 2 : 4;
     89       
     90        if (downScaleMode == 2) {
     91                createThumbnail_2<565>(src, srcPitch, dstPtr, dstPitch, width, height);
     92        } else if (downScaleMode == 4) {
     93                createThumbnail_4<565>(src, srcPitch, dstPtr, dstPitch, width, height);
     94        }
     95}
     96
     97bool createThumbnailFromScreen(Graphics::Surface* surf) {
     98        assert(surf);
     99       
     100        int screenWidth = OSystem::instance().getWidth();
     101        int screenHeight = OSystem::instance().getHeight();
     102       
     103        Graphics::Surface screen;
     104        OSystem::instance().grabScreen(&screen);
     105       
     106        if (!screen.pixels)
     107                return false;
     108
     109        uint16 width = screenWidth;
     110       
     111        if (screenWidth < 320) {
     112                width = 320;
     113               
     114                // center MM NES screen
     115                Graphics::Surface newscreen;
     116                newscreen.create(width, screen.h, screen.bytesPerPixel);
     117               
     118                uint8 *dst = (uint8*)newscreen.getBasePtr((320 - screenWidth) / 2, 0);
     119                uint8 *src = (uint8*)screen.getBasePtr(0, 0);
     120                uint16 height = screen.h;
     121               
     122                while (height--) {
     123                        memcpy(dst, src, screen.pitch);
     124                        dst += newscreen.pitch;
     125                        src += screen.pitch;
     126                }
     127               
     128                screen.free();
     129                screen = newscreen;
     130        }
     131       
     132        uint16 newHeight = !(screenHeight % 240) ? kThumbnailHeight_2 : kThumbnailHeight_1;
     133       
     134        surf->create(kThumbnailWidth, newHeight, sizeof(uint16));
     135        createThumbnail((const uint8*)screen.pixels, width * sizeof(uint16), (uint8*)surf->pixels, surf->pitch, width, screenHeight);   
     136       
     137        screen.free();
     138       
     139        return true;
     140}
  • common/scaler.h

    diff -d -u --rec -N --exclude=CVS scummvm.old/common/scaler.h scummvm/common/scaler.h
    old new  
    2323
    2424#include "common/stdafx.h"
    2525#include "common/scummsys.h"
     26#include "graphics/surface.h"
    2627
    2728extern void InitScalers(uint32 BitFormat);
    2829
     
    5960
    6061extern int stretch200To240(uint8 *buf, uint32 pitch, int width, int height, int srcX, int srcY, int origSrcY);
    6162
     63// creates a 160x100 thumbnail for 320x200 games
     64// and 160x120 thumbnail for 320x240 and 640x480 games
     65// only 565 mode
     66enum {
     67        kThumbnailWidth = 160,
     68        kThumbnailHeight_1 = 100,
     69        kThumbnailHeight_2 = 120
     70};
     71extern void createThumbnail(const uint8* src, uint32 srcPitch, uint8* dstPtr, uint32 dstPitch, int width, int height);
     72
     73/**
     74 * creates a thumbnail from the current screen (without overlay)
     75 * @param surf  a surface (will always have 16 bpp after this for now)
     76 * @return              false if a error occured
     77 */
     78extern bool createThumbnailFromScreen(Graphics::Surface* surf);
    6279
    6380#endif
  • common/system.cpp

    diff -d -u --rec -N --exclude=CVS scummvm.old/common/system.cpp scummvm/common/system.cpp
    old new  
    3333#include "common/system.h"
    3434#include "common/util.h"
    3535
     36#include "graphics/surface.h"
     37
    3638DECLARE_SINGLETON(OSystem);
    3739
    3840OSystem *OSystem::makeInstance() {
     
    9193
    9294SaveFileManager *OSystem::getSavefileManager() {
    9395        return new DefaultSaveFileManager();
     96}
     97
     98void OSystem::grabScreen(Graphics::Surface *surf, int bitsPerPixel) {
     99        Graphics::Surface screen;
     100        grabRawScreen(&screen);
     101       
     102        if (screen.bytesPerPixel != 1 || screen.pixels == 0)
     103                return;
     104       
     105        byte palette[256 * 4];
     106        grabPalette(&palette[0], 0, 256);
     107       
     108        surf->create(screen.w, screen.h, (bitsPerPixel + 1) / 8);
     109       
     110        for (uint y = 0; y < screen.h; ++y) {
     111                for (uint x = 0; x < screen.w; ++x) {
     112                        byte r, g, b;
     113                        r = palette[((uint8*)screen.pixels)[y * screen.pitch + x] * 4];
     114                        g = palette[((uint8*)screen.pixels)[y * screen.pitch + x] * 4 + 1];
     115                        b = palette[((uint8*)screen.pixels)[y * screen.pitch + x] * 4 + 2];
     116                       
     117                        if (bitsPerPixel == 15) {
     118                                ((uint16*)surf->pixels)[y * surf->w + x] = (((r >> 3) & 0x1F) << 10) | (((g >> 3) & 0x1F) << 5) | ((b >> 3) & 0x1F);
     119                        } else if (bitsPerPixel == 16) {
     120                                ((uint16*)surf->pixels)[y * surf->w + x] = (((r >> 3) & 0x1F) << 11) | (((g >> 2) & 0x3F) << 5) | ((b >> 3) & 0x1F);
     121                        } else if (bitsPerPixel == 24) {
     122#ifdef SCUMM_BIG_ENDIAN
     123                                ((uint8*)surf->pixels)[y * surf->pitch + x * surf->bytesPerPixel + 2] = r;
     124                                ((uint8*)surf->pixels)[y * surf->pitch + x * surf->bytesPerPixel + 1] = g;
     125                                ((uint8*)surf->pixels)[y * surf->pitch + x * surf->bytesPerPixel] = b;
     126#else
     127                                ((uint8*)surf->pixels)[y * surf->pitch + x * surf->bytesPerPixel] = r;
     128                                ((uint8*)surf->pixels)[y * surf->pitch + x * surf->bytesPerPixel + 1] = g;
     129                                ((uint8*)surf->pixels)[y * surf->pitch + x * surf->bytesPerPixel + 2] = b;
     130#endif
     131                        } else if (bitsPerPixel == 32) {
     132                                ((uint32*)surf->pixels)[y * surf->w + x] = 0xFF << 24 | r << 16 | g << 8 | b << 8;
     133                        }
     134                }
     135        }
     136       
     137        screen.free();
    94138}
  • common/system.h

    diff -d -u --rec -N --exclude=CVS scummvm.old/common/system.h scummvm/common/system.h
    old new  
    2828#include "common/rect.h"
    2929#include "common/singleton.h"
    3030
     31namespace Graphics {
     32class Surface;
     33} // end of namespace Graphics
     34
    3135class SaveFileManager;
    3236
    3337/**
     
    347351         *       API are probably going to remove it.
    348352         */
    349353        virtual void setPalette(const byte *colors, uint start, uint num) = 0;
     354       
     355        /**
     356         * Grabs a specified part of the palette
     357         * format is like it is discribed in setPalette
     358         *
     359         * @param buf   the buffer
     360         * @param start the first platte entry
     361         * @param num   nummber of the entries
     362         */
     363        virtual void grabPalette(byte *colors, uint start, uint num) = 0;
    350364
    351365        /**
    352366         * Blit a bitmap to the virtual screen.
     
    357371         * @see updateScreen
    358372         */
    359373        virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) = 0;
     374
     375        /**
     376         * Copies the screen to a surface
     377         * @param surf                  the surfce to store the data in it
     378         * @param bitsPerPixel  must be higher than 15 and lower than 32
     379         */
     380        virtual void grabScreen(Graphics::Surface *surf, int bitsPerPixel = 16);
     381       
     382        /**
     383         * Copies the screen to a surface (with original bit depth)
     384         * It should return a 1 byte per pixel surface in all cases
     385         * because currently all games supported by ScummVM are
     386         * using 1 byte per pixel.
     387         *
     388         * @param surf  the surfce to store the data in it
     389         */
     390        virtual void grabRawScreen(Graphics::Surface *surf) = 0;
    360391       
    361392        /**
    362393         * Clear the screen to black.
  • graphics/surface.cpp

    diff -d -u --rec -N --exclude=CVS scummvm.old/graphics/surface.cpp scummvm/graphics/surface.cpp
    old new  
    2424
    2525namespace Graphics {
    2626
     27void Surface::create(uint16 width, uint16 height, uint8 bytesPP) {
     28        free();
     29       
     30        w = width; h = height;
     31        bytesPerPixel = bytesPP;
     32        pitch = w * bytesPP;
     33       
     34        pixels = calloc(width * height, bytesPP);
     35        assert(pixels);
     36}
     37
     38void Surface::free() {
     39        ::free(pixels);
     40        pixels = 0;
     41        w = h = pitch = 0;
     42        bytesPerPixel = 0;
     43}
     44
    2745void Surface::hLine(int x, int y, int x2, uint32 color) const {
    2846        // Clipping
    2947        if (y < 0 || y >= h)
  • graphics/surface.h

    diff -d -u --rec -N --exclude=CVS scummvm.old/graphics/surface.h scummvm/graphics/surface.h
    old new  
    4343                return (void *)((byte *)pixels + y * pitch + x * bytesPerPixel);
    4444        }
    4545       
     46        void create(uint16 width, uint16 height, uint8 bytesPP);
     47        void free();
     48       
    4649        void hLine(int x, int y, int x2, uint32 color) const;
    4750        void vLine(int x, int y, int y2, uint32 color) const;
    4851        void fillRect(const Common::Rect &r, uint32 color) const;
  • gui/newgui.cpp

    diff -d -u --rec -N --exclude=CVS scummvm.old/gui/newgui.cpp scummvm/gui/newgui.cpp
    old new  
    2121#include "stdafx.h"
    2222#include "common/system.h"
    2323#include "common/util.h"
     24#include "common/scaler.h"
    2425#include "gui/newgui.h"
    2526#include "gui/dialog.h"
    2627
     
    434435                                        ptr[x] = color;
    435436                }
    436437        }
     438}
     439
     440//
     441// Copies a Surface to the Overlay
     442//
     443void NewGui::drawSurface(const OverlayColor* data, int x, int y, int width, int height, int pitch) {
     444        if(_scaleFactor == 1) {
     445                uint8* dst = (uint8*)getBasePtr(x, y); 
     446                for (int y_ = 0; y_ < height; ++y_, dst += _screen.pitch) {
     447                        memcpy(dst, &((const uint8*)data)[y_ * pitch], width * sizeof(OverlayColor));
     448                }
     449        } else if(_scaleFactor == 2) {
     450                Normal2x((const uint8*)data, pitch, (uint8*)getBasePtr(x * 2, y * 2), _screen.pitch, width, height);
     451        }       
     452        addDirtyRect(x, y, width, height);
    437453}
    438454
    439455//
  • gui/newgui.h

    diff -d -u --rec -N --exclude=CVS scummvm.old/gui/newgui.h scummvm/gui/newgui.h
    old new  
    146146        int getFontHeight() const;
    147147
    148148        void drawBitmap(uint32 *bitmap, int x, int y, OverlayColor color, int h = 8);
     149        void drawSurface(const OverlayColor* data, int x, int y, int width, int height, int pitch);
    149150
    150151        void addDirtyRect(int x, int y, int w, int h);
    151152};
  • gui/widget.cpp

    diff -d -u --rec -N --exclude=CVS scummvm.old/gui/widget.cpp scummvm/gui/widget.cpp
    old new  
    2424#include "gui/dialog.h"
    2525#include "gui/newgui.h"
    2626
    27 
    2827namespace GUI {
    2928
    3029Widget::Widget(GuiObject *boss, int x, int y, int w, int h)
     
    258257
    259258int SliderWidget::posToValue(int pos) {
    260259        return (pos) * (_valueMax - _valueMin) / (_w - _labelWidth - 4) + _valueMin;
     260}
     261
     262#pragma mark -
     263
     264GraphicsWidget::GraphicsWidget(GuiObject *boss, int x, int y, int w, int h)
     265        : Widget(boss, x, y, w, h), _gfx(0), _gfxWidth(0), _gfxHeight(0), _bpp(0) {
     266        _flags = WIDGET_ENABLED | WIDGET_CLEARBG;
     267        _type = kGraphicsWidget;
     268}
     269
     270GraphicsWidget::~GraphicsWidget() {
     271        delete [] _gfx;
     272}
     273
     274void GraphicsWidget::setGfx(int width, int height, int bpp, const uint8 *data) {
     275        delete [] _gfx;
     276        _gfx = 0;
     277       
     278        if(!data)
     279                return;
     280       
     281        _gfx = new uint8[width * height * bpp];
     282        assert(_gfx);
     283       
     284        _gfxWidth = width;
     285        _gfxHeight = height;
     286        _bpp = bpp;
     287
     288        memcpy(_gfx, data, width * height * bpp);
     289}
     290
     291void GraphicsWidget::drawWidget(bool hilite) {
     292        if(sizeof(OverlayColor) != _bpp || !_gfx) {
     293                g_gui.drawString("No preview", _x, _y + _h / 2 - g_gui.getFontHeight() / 2, _w, g_gui._textcolor, Graphics::kTextAlignCenter);
     294                return;
     295        }
     296       
     297        uint drawWidth = _gfxWidth, drawHeight = _gfxHeight;
     298       
     299        if(_w < _gfxWidth)
     300                drawWidth = _w;
     301        if(_h < _gfxHeight)
     302                drawHeight = _h;
     303       
     304        g_gui.drawSurface((OverlayColor*)_gfx, _x, _y, drawWidth, drawHeight, _gfxWidth * _bpp);
    261305}
    262306
    263307} // End of namespace GUI
  • gui/widget.h

    diff -d -u --rec -N --exclude=CVS scummvm.old/gui/widget.h scummvm/gui/widget.h
    old new  
    5252        kListWidget                     = 'LIST',
    5353        kScrollBarWidget        = 'SCRB',
    5454        kPopUpWidget            = 'POPU',
    55         kTabWidget                      = 'TABW'
     55        kTabWidget                      = 'TABW',
     56        kGraphicsWidget         = 'GFXW'
    5657};
    5758
    5859enum {
     
    208209
    209210        int valueToPos(int value);
    210211        int posToValue(int pos);
     212};
     213
     214/* GraphicsWidget */
     215class GraphicsWidget : public Widget {
     216public:
     217        GraphicsWidget(GuiObject *boss, int x, int y, int w, int h);
     218        ~GraphicsWidget();
     219       
     220        // bpp = _byte_ per pixel
     221        void setGfx(int width, int height, int bpp, const uint8 *data);
     222protected:
     223        void drawWidget(bool hilite);
     224       
     225        uint8 *_gfx;
     226        int _gfxWidth, _gfxHeight, _bpp;
    211227};
    212228
    213229} // End of namespace GUI
  • scumm/dialogs.cpp

    diff -d -u --rec -N --exclude=CVS scummvm.old/scumm/dialogs.cpp scummvm/scumm/dialogs.cpp
    old new  
    2222
    2323#include "common/config-manager.h"
    2424#include "common/system.h"
     25#include "common/scaler.h"
    2526
    2627#include "gui/chooser.h"
    2728#include "gui/newgui.h"
     
    147148
    148149#pragma mark -
    149150
    150 
    151151const Common::String ScummDialog::queryResString(int stringno) {
    152152        byte buf[256];
    153153        byte *result;
     
    199199        kQuitCmd = 'QUIT'
    200200};
    201201
    202 class SaveLoadChooser : public GUI::ChooserDialog {
     202class SaveLoadChooser : public GUI::ChooserDialog, public ScummSaveLoadChooser {
    203203        typedef Common::String String;
    204204        typedef Common::StringList StringList;
    205205protected:
     
    210210       
    211211        virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
    212212        const String &getResultString() const;
     213        void setList(const StringList& list) { GUI::ChooserDialog::setList(list); }
     214        int runModal() { return GUI::ChooserDialog::runModal(); }
    213215};
    214216
    215217SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel, bool saveMode)
     
    250252        }
    251253}
    252254
     255#pragma mark -
     256
     257enum {
     258        kChooseCmd = 'Chos'
     259};
     260
     261// only for use with >= 640x400 resolutions
     262class SaveLoadChooserEx : public GUI::Dialog, public ScummSaveLoadChooser {
     263        typedef Common::String String;
     264        typedef Common::StringList StringList;
     265protected:
     266        bool _saveMode;
     267        GUI::ListWidget         *_list;
     268        GUI::ButtonWidget       *_chooseButton;
     269        GUI::GraphicsWidget     *_gfxWidget;
     270        ScummEngine                     *_scumm;
     271
     272public:
     273        SaveLoadChooserEx(const String &title, const String &buttonLabel, bool saveMode, ScummEngine *engine);
     274       
     275        virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
     276        const String &getResultString() const; 
     277        void setList(const StringList& list);
     278        int runModal();
     279};
     280
     281SaveLoadChooserEx::SaveLoadChooserEx(const String &title, const String &buttonLabel, bool saveMode, ScummEngine *engine)
     282        : Dialog(8, 8, engine->_system->getOverlayWidth() - 2 * 8, engine->_system->getOverlayHeight() - 16), _saveMode(saveMode), _list(0), _chooseButton(0), _gfxWidget(0), _scumm(engine) {
     283       
     284        new StaticTextWidget(this, 10, 6, _w - 2 * 10, kLineHeight, title, kTextAlignCenter);
     285       
     286        // Add choice list
     287        _list = new GUI::ListWidget(this, 10, 18, _w - 2 * 10 - 180, _h - 14 - 24 - 10);
     288        _list->setEditable(saveMode);
     289        _list->setNumberingMode(saveMode ? GUI::kListNumberingOne : GUI::kListNumberingZero);
     290       
     291        // Add the thumbnail displayer
     292        _gfxWidget = new GUI::GraphicsWidget(this, _w - (kThumbnailWidth + 22), _y + 6, kThumbnailWidth + 8, ((_scumm->_system->getHeight() % 200) ? kThumbnailHeight_2 : kThumbnailHeight_1) + 8);
     293        _gfxWidget->setFlags(GUI::WIDGET_BORDER);
     294       
     295        // Buttons
     296        addButton(_w - 2 * (kButtonWidth + 10), _h - 24, "Cancel", kCloseCmd, 0);
     297        _chooseButton = addButton(_w-(kButtonWidth + 10), _h - 24, buttonLabel, kChooseCmd, 0);
     298        _chooseButton->setEnabled(false);
     299}
     300
     301const Common::String &SaveLoadChooserEx::getResultString() const {
     302        return _list->getSelectedString();
     303}
     304
     305void SaveLoadChooserEx::setList(const StringList& list) {
     306        _list->setList(list);
     307}
     308
     309int SaveLoadChooserEx::runModal() {
     310        g_gui.enableScaling(false);
     311        _gfxWidget->setGfx(0, 0, 0, 0);
     312        int ret = GUI::Dialog::runModal();
     313        g_gui.enableScaling(true);
     314        return ret;
     315}
     316
     317void SaveLoadChooserEx::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
     318        int selItem = _list->getSelected();
     319        switch (cmd) {
     320        case GUI::kListItemActivatedCmd:
     321        case GUI::kListItemDoubleClickedCmd:
     322                if (selItem >= 0) {
     323                        if (_saveMode || !getResultString().isEmpty()) {
     324                                _list->endEditMode();
     325                                setResult(selItem);
     326                                close();
     327                        }
     328                }
     329                break;
     330        case kChooseCmd:
     331                _list->endEditMode();
     332                setResult(selItem);
     333                close();
     334                break;
     335        case GUI::kListSelectionChangedCmd:
     336                _scumm->getThumbnail(_saveMode ? selItem + 1 : selItem);
     337                _gfxWidget->setGfx(_scumm->getThumbnailWidth(), _scumm->getThumbnailHeight(), 2, (const uint8*)_scumm->getThumbnail());
     338                _gfxWidget->draw();
     339
     340                if (_saveMode) {
     341                        _list->startEditMode();
     342                }
     343                // Disable button if nothing is selected, or (in load mode) if an empty
     344                // list item is selected. We allow choosing an empty item in save mode
     345                // because we then just assign a default name.
     346                _chooseButton->setEnabled(selItem >= 0 && (_saveMode || !getResultString().isEmpty()));
     347                _chooseButton->draw();
     348                break;
     349        case kCloseCmd:
     350                setResult(-1);
     351        default:
     352                GUI::Dialog::handleCommand(sender, cmd, data);
     353        }
     354}
     355
     356#pragma mark -
     357
    253358Common::StringList generateSavegameList(ScummEngine *scumm, bool saveMode) {
    254359        // Get savegame names
    255360        Common::StringList l;
     
    308413#ifndef DISABLE_HELP
    309414        _helpDialog = new HelpDialog(scumm);
    310415#endif
    311         _saveDialog = new SaveLoadChooser("Save game:", "Save", true);
    312         _loadDialog = new SaveLoadChooser("Load game:", "Load", false);
     416        if(scumm->_system->getOverlayWidth() <= 320) {
     417                _saveDialog = new SaveLoadChooser("Save game:", "Save", true);
     418                _loadDialog = new SaveLoadChooser("Load game:", "Load", false);
     419        } else {
     420                _saveDialog = new SaveLoadChooserEx("Save game:", "Save", true, scumm);
     421                _loadDialog = new SaveLoadChooserEx("Load game:", "Load", false, scumm);
     422        }
    313423}
    314424
    315425MainMenuDialog::~MainMenuDialog() {
  • scumm/dialogs.h

    diff -d -u --rec -N --exclude=CVS scummvm.old/scumm/dialogs.h scummvm/scumm/dialogs.h
    old new  
    5454        const String queryResString(int stringno);
    5555};
    5656
    57 class SaveLoadChooser;
     57// to have a base for all different Save/Load Choosers
     58// currently only for SaveLoadChooser (320x200)
     59// and for SaveLoadChooserEx (640x400/640x480)
     60class ScummSaveLoadChooser
     61{
     62public:
     63        virtual ~ScummSaveLoadChooser() {};
     64       
     65        virtual const Common::String &getResultString() const = 0;
     66        virtual void setList(const Common::StringList& list) = 0;
     67        virtual int runModal() = 0;
     68};
    5869
    5970class MainMenuDialog : public ScummDialog {
    6071public:
     
    6879#ifndef DISABLE_HELP
    6980        GUI::Dialog             *_helpDialog;
    7081#endif
    71         SaveLoadChooser *_saveDialog;
    72         SaveLoadChooser *_loadDialog;
     82        ScummSaveLoadChooser    *_saveDialog;
     83        ScummSaveLoadChooser    *_loadDialog;
    7384
    7485        void save();
    7586        void load();
  • scumm/module.mk

    diff -d -u --rec -N --exclude=CVS scummvm.old/scumm/module.mk scummvm/scumm/module.mk
    old new  
    7878        scumm/smush/smush_player.o \
    7979        scumm/smush/saud_channel.o \
    8080        scumm/smush/smush_mixer.o \
    81         scumm/smush/smush_font.o
     81        scumm/smush/smush_font.o \
     82        scumm/thumbnail.o
    8283
    8384MODULE_DIRS += \
    8485        scumm \
  • scumm/saveload.cpp

    diff -d -u --rec -N --exclude=CVS scummvm.old/scumm/saveload.cpp scummvm/scumm/saveload.cpp
    old new  
    8383        hdr.ver = TO_LE_32(CURRENT_VER);
    8484
    8585        out->write(&hdr, sizeof(hdr));
     86        saveThumbnail(out);
    8687
    8788        Serializer ser(0, out, CURRENT_VER);
    8889        saveOrLoad(&ser, CURRENT_VER);
     
    120121                delete in;
    121122                return false;
    122123        }
     124       
     125        // Sine version 49 a thumbnail is saved directly after the header
     126        if (hdr.ver >= VER(49)) {
     127                if(!loadThumbnail(in)) {
     128                        warning("Can not load thumbnail");
     129                        delete in;
     130                        return false;
     131                }
     132        }
    123133
    124134        // Due to a bug in scummvm up to and including 0.3.0, save games could be saved
    125135        // in the V8/V9 format but were tagged with a V7 mark. Ouch. So we just pretend V7 == V8 here
     
    375385
    376386        memcpy(desc, hdr.name, sizeof(hdr.name));
    377387        desc[sizeof(hdr.name) - 1] = 0;
     388        return true;
     389}
     390
     391bool ScummEngine::getThumbnail(int slot) {
     392        char filename[256];
     393        InSaveFile *in;
     394        SaveGameHeader hdr;
     395        int len;
     396       
     397        if (_thumbnail)
     398                _thumbnail->free();
     399        delete _thumbnail;
     400        _thumbnail = 0;
     401
     402        makeSavegameName(filename, slot, false);
     403        if (!(in = _saveFileMan->openForLoading(filename))) {
     404                return false;
     405        }
     406        len = in->read(&hdr, sizeof(hdr));
     407
     408        if (len != sizeof(hdr) || hdr.type != MKID('SCVM')) {
     409                delete in;
     410                return false;
     411        }
     412
     413        if (hdr.ver > CURRENT_VER)
     414                hdr.ver = TO_LE_32(hdr.ver);
     415        if (hdr.ver < VER(49)) {
     416                delete in;
     417                return false;
     418        }
     419
     420        loadThumbnail(in);
     421
     422        delete in;
    378423        return true;
    379424}
    380425
  • scumm/saveload.h

    diff -d -u --rec -N --exclude=CVS scummvm.old/scumm/saveload.h scummvm/scumm/saveload.h
    old new  
    3333// Can be useful for other ports too :)
    3434
    3535#define VER(x) x
    36 #define CURRENT_VER 48
     36#define CURRENT_VER 49
    3737
    3838// To work around a warning in GCC 3.2 (and 3.1 ?) regarding non-POD types,
    3939// we use a small trick: instead of 0 we use 42. Why? Well, it seems newer GCC
  • scumm/scumm.cpp

    diff -d -u --rec -N --exclude=CVS scummvm.old/scumm/scumm.cpp scummvm/scumm/scumm.cpp
    old new  
    618618          _features(gs.features),
    619619          gdi(this),
    620620          res(this),
    621           _pauseDialog(0), _mainMenuDialog(0), _versionDialog(0),
     621          _pauseDialog(0), _mainMenuDialog(0), _versionDialog(0), _thumbnail(0),
    622622          _targetName(detector->_targetName) {
    623623
    624624        // Copy MD5 checksum
  • scumm/scumm.h

    diff -d -u --rec -N --exclude=CVS scummvm.old/scumm/scumm.h scummvm/scumm/scumm.h
    old new  
    2828#include "common/map.h"
    2929#include "common/rect.h"
    3030#include "common/str.h"
     31#include "graphics/surface.h"
    3132
    3233#include "scumm/gfx.h"
    3334#include "scumm/script.h"
    3435
     36// FIXME:
     37// define it in a other location
     38#define THMB_VERSION 1
     39
    3540namespace GUI {
    3641        class Dialog;
    3742}
    3843using GUI::Dialog;
    3944class GameDetector;
    40 
     45class InSaveFile;
     46class OutSaveFile;
    4147
    4248namespace Scumm {
    4349
     
    593599       
    594600        void requestSave(int slot, const char *name, bool temporary = false);
    595601        void requestLoad(int slot);
     602
     603// thumbnail stuff
     604public:
     605        bool getThumbnail(int slot);
     606        const void* getThumbnail() { if(_thumbnail) return _thumbnail->pixels; return 0; }
     607        uint16 getThumbnailHeight() { if(_thumbnail) return _thumbnail->h; return 0; }
     608        uint16 getThumbnailWidth() { if(_thumbnail) return _thumbnail->w; return 0; }
     609
     610protected:
     611        bool loadThumbnail(InSaveFile *file);
     612        void saveThumbnail(OutSaveFile *file);
     613       
     614        Graphics::Surface *_thumbnail;
     615       
     616        struct ThumbnailHeader {
     617                uint32 type;
     618                uint32 size;
     619                byte version;
     620                uint16 width, height;
     621                byte bpp;
     622        };
     623// ends here
    596624
    597625protected:
    598626        /* Script VM - should be in Script class */
  • scumm/thumbnail.cpp

    diff -d -u --rec -N --exclude=CVS scummvm.old/scumm/thumbnail.cpp scummvm/scumm/thumbnail.cpp
    old new  
     1/* ScummVM - Scumm Interpreter
     2 * Copyright (C) 2001  Ludvig Strigeus
     3 * Copyright (C) 2001-2005 The ScummVM project
     4 *
     5 * This program is free software; you can redistribute it and/or
     6 * modify it under the terms of the GNU General Public License
     7 * as published by the Free Software Foundation; either version 2
     8 * of the License, or (at your option) any later version.
     9
     10 * This program is distributed file the hope that it will be useful,
     11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 * GNU General Public License for more details.
     14
     15 * You should have received a copy of the GNU General Public License
     16 * along with this program; if not, write to the Free Software
     17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 *
     19 * $Header: $
     20 *
     21 */
     22 
     23#include "common/stdafx.h"
     24#include "common/scummsys.h"
     25#include "common/system.h"
     26#include "common/savefile.h"
     27#include "common/scaler.h"
     28#include "scumm.h"
     29
     30namespace Scumm {
     31inline uint16 RGBToColor(const uint8 r, const uint8 g, const uint8 b) {
     32        return ((((r >> 3) & 0x1F) << 11) | (((g >> 2) & 0x3F) << 5) | ((b >> 3) & 0x1F));
     33}
     34
     35inline void colorToRGB(uint16 color, uint8 &r, uint8 &g, uint8 &b) {
     36        r = (((color >> 11) & 0x1F) << 3);
     37        g = (((color >> 5) & 0x3F) << 2);
     38        b = ((color&0x1F) << 3);
     39}
     40
     41bool ScummEngine::loadThumbnail(InSaveFile *file) {
     42        if (_thumbnail)
     43                _thumbnail->free();
     44        delete _thumbnail;     
     45        _thumbnail = 0;
     46
     47        ThumbnailHeader header;
     48        header.type = file->readUint32BE();
     49        if(header.type != MKID('THMB'))
     50                return false;
     51
     52        header.size = file->readUint32BE();
     53        header.version = file->readByte();
     54
     55        if (header.version > THMB_VERSION) {
     56                // TODO: maybe add a skip method to the SaveFile class to get rid of this
     57                byte *buf = new byte[header.size - sizeof(uint32) * 2 - sizeof(byte)];
     58                file->read(buf, header.size - sizeof(uint32) * 2 - sizeof(byte));
     59                delete [] buf; 
     60                warning("Loading a newer thumbnail version");
     61                return true;
     62        }
     63
     64        header.width = file->readUint16BE();
     65        header.height = file->readUint16BE();
     66        header.bpp = file->readByte();
     67       
     68        // TODO: support other bpp values than 2
     69        if(header.bpp != 2) {
     70                // skip all data
     71                // TODO: maybe add a skip method to the SaveFile class to get rid of this
     72                byte *buf = new byte[header.width * header.height * header.bpp];
     73                file->read(buf, header.width * header.height * header.bpp);
     74                delete [] buf;
     75                return true;
     76        }       
     77       
     78        _thumbnail = new Graphics::Surface();
     79        _thumbnail->create(header.width, header.height, sizeof(uint16));
     80        for (uint16 p = 0; p <_thumbnail->w*_thumbnail->h; ++p)
     81                ((uint16*)_thumbnail->pixels)[p] = file->readUint16BE();
     82
     83        uint16* pixels = (uint16*)_thumbnail->pixels;
     84
     85        for (int y = 0; y < _thumbnail->h; ++y) {
     86                for (int x = 0; x < _thumbnail->w; ++x) {
     87                        uint8 r, g, b;
     88                        colorToRGB(((const uint16*)pixels)[y * _thumbnail->w + x], r, g, b);
     89                       
     90                        // converting to current OSystem Color
     91                        pixels[y * _thumbnail->w + x] = _system->RGBToColor(r, g, b);
     92                }
     93        }
     94
     95        return true;
     96}
     97
     98void ScummEngine::saveThumbnail(OutSaveFile *file) {
     99        if (_thumbnail)
     100                _thumbnail->free();
     101        else if (!_thumbnail)
     102                _thumbnail = new Graphics::Surface();
     103 
     104        if (!createThumbnailFromScreen(_thumbnail))
     105                _thumbnail->create(kThumbnailWidth, kThumbnailHeight_2, sizeof(uint16));
     106       
     107        ThumbnailHeader header;
     108        header.type = MKID('THMB');
     109        header.size = sizeof(header) + _thumbnail->w*_thumbnail->h*_thumbnail->bytesPerPixel;
     110        header.version = THMB_VERSION;
     111        header.width = _thumbnail->w;
     112        header.height = _thumbnail->h;
     113        header.bpp = _thumbnail->bytesPerPixel;
     114
     115        file->writeUint32BE(header.type);
     116        file->writeUint32BE(header.size);
     117        file->writeByte(header.version);
     118        file->writeUint16BE(header.width);
     119        file->writeUint16BE(header.height);
     120        file->writeByte(header.bpp);
     121       
     122        // TODO: for later this shouldn't be hardcastet to uint16...
     123        for (uint16 p = 0; p < _thumbnail->w*_thumbnail->h; ++p)
     124                file->writeUint16BE(((uint16*)_thumbnail->pixels)[p]);
     125
     126        if (_thumbnail)
     127                _thumbnail->free();
     128        delete _thumbnail;
     129        _thumbnail = 0;
     130}
     131} // end of namespace Scumm