Ticket #8405: thumbnail-v4-2.patch

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

new standalone patch

  • backends/sdl/graphics.cpp

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/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},
     
    806807        SDL_UnlockSurface(_screen);
    807808}
    808809
     810void OSystem_SDL::grabRawScreen(Graphics::Surface *surf) {
     811        assert(_screen);
     812        assert(surf);
     813       
     814        Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
     815       
     816        surf->create(_screenWidth, _screenHeight, _screen->format->BytesPerPixel);
     817       
     818        // Try to lock the screen surface
     819        if (SDL_LockSurface(_screen) == -1)
     820                error("SDL_LockSurface failed: %s", SDL_GetError());
     821       
     822        memcpy(surf->pixels, _screen->pixels, _screenWidth * _screenHeight * _screen->format->BytesPerPixel);
     823       
     824        // Unlock the screen surface
     825        SDL_UnlockSurface(_screen);
     826}
    809827
    810828void OSystem_SDL::addDirtyRect(int x, int y, int w, int h, bool mouseRect) {
    811829        if (_forceFull)
     
    9901008                blitCursor();
    9911009}
    9921010
     1011void OSystem_SDL::grabPalette(byte *colors, uint start, uint num) {
     1012        assert(colors);
     1013        const SDL_Color *base = _currentPalette + start;
     1014       
     1015        for (uint i = 0; i < num; ++i) {
     1016                colors[i * 4] = base[i].r;
     1017                colors[i * 4 + 1] = base[i].g;
     1018                colors[i * 4 + 2] = base[i].b;
     1019                colors[i * 4 + 3] = 0xFF;
     1020        }
     1021}
     1022
    9931023void OSystem_SDL::setCursorPalette(const byte *colors, uint start, uint num) {
    9941024        assert(colors);
    9951025        const byte *b = colors;
  • backends/sdl/sdl-common.h

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/backends/sdl/sdl-common.h ./scummvm/backends/sdl/sdl-common.h
    old new  
    8080
    8181        // Set colors of the palette
    8282        void setPalette(const byte *colors, uint start, uint num);
     83       
     84        // Get colors of the palette
     85        void grabPalette(byte *colors, uint start, uint num);
    8386
    8487        // Draw a bitmap to screen.
    8588        // The screen will not be updated to reflect the new bitmap
    8689        void copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h);
    8790
     91        // Copies the screen to a buffer
     92        void grabRawScreen(Graphics::Surface *surf);
     93
    8894        // Clear the screen
    8995        void clearScreen();
    9096
  • common/module.mk

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/common/module.mk ./scummvm/common/module.mk
    old new  
    2222        common/scaler/hq3x.o \
    2323        common/scaler/scale2x.o \
    2424        common/scaler/scale3x.o \
    25         common/scaler/scalebit.o
     25        common/scaler/scalebit.o \
     26        common/scaler/thumbnail.o
    2627
    2728ifdef HAVE_NASM
    2829MODULE_OBJS += \
  • common/scaler/thumbnail.cpp

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/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                if (gBitFormat == 565)
     92                        createThumbnail_2<565>(src, srcPitch, dstPtr, dstPitch, width, height);
     93                else if (gBitFormat == 555)
     94                        createThumbnail_2<555>(src, srcPitch, dstPtr, dstPitch, width, height);
     95        } else if (downScaleMode == 4) {
     96                if (gBitFormat == 565)
     97                        createThumbnail_4<565>(src, srcPitch, dstPtr, dstPitch, width, height);
     98                else if (gBitFormat = 555)
     99                        createThumbnail_4<555>(src, srcPitch, dstPtr, dstPitch, width, height);
     100        }
     101}
     102
     103bool createThumbnailFromScreen(Graphics::Surface* surf) {
     104        assert(surf);
     105       
     106        int screenWidth = OSystem::instance().getWidth();
     107        int screenHeight = OSystem::instance().getHeight();
     108       
     109        Graphics::Surface screen;
     110        OSystem::instance().grabScreen(&screen, 16);
     111       
     112        if (!screen.pixels)
     113                return false;
     114
     115        uint16 width = screenWidth;
     116       
     117        if (screenWidth < 320) {
     118                width = 320;
     119               
     120                // center MM NES screen
     121                Graphics::Surface newscreen;
     122                newscreen.create(width, screen.h, screen.bytesPerPixel);
     123               
     124                uint8 *dst = (uint8*)newscreen.getBasePtr((320 - screenWidth) / 2, 0);
     125                uint8 *src = (uint8*)screen.getBasePtr(0, 0);
     126                uint16 height = screen.h;
     127               
     128                while (height--) {
     129                        memcpy(dst, src, screen.pitch);
     130                        dst += newscreen.pitch;
     131                        src += screen.pitch;
     132                }
     133               
     134                screen.free();
     135                screen = newscreen;
     136        }
     137        if (screenWidth == 720) {
     138                width = 640;
     139                screenHeight = 400;
     140               
     141                // cut off menu and so on..
     142                Graphics::Surface newscreen;
     143                newscreen.create(width, 400, screen.bytesPerPixel);
     144
     145                uint8 *dst = (uint8*)newscreen.getBasePtr(0, (400 - 240) / 2);
     146                uint8 *src = (uint8*)screen.getBasePtr(41, 28);
     147
     148                for (int y = 0; y < 240; ++y) {
     149                        memcpy(dst, src, 640 * screen.bytesPerPixel);
     150                        dst += newscreen.pitch;
     151                        src += screen.pitch;
     152                }
     153
     154                screen.free();
     155                screen = newscreen;
     156        }
     157       
     158        uint16 newHeight = !(screenHeight % 240) ? kThumbnailHeight_2 : kThumbnailHeight_1;
     159       
     160        int gBitFormatBackUp = gBitFormat;
     161        gBitFormat = 565;
     162        surf->create(kThumbnailWidth, newHeight, sizeof(uint16));
     163        createThumbnail((const uint8*)screen.pixels, width * sizeof(uint16), (uint8*)surf->pixels, surf->pitch, width, screenHeight);   
     164        gBitFormat = gBitFormatBackUp;
     165       
     166        screen.free();
     167       
     168        return true;
     169}
  • common/scaler.h

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/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 --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/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() {
     
    9294SaveFileManager *OSystem::getSavefileManager() {
    9395        return new DefaultSaveFileManager();
    9496}
     97
     98void OSystem::grabScreen(Graphics::Surface *surf, int bitsPerPixel) {
     99        if (bitsPerPixel != 15 && bitsPerPixel != 16)
     100                error("only 15 and 16 bpp are supported");
     101       
     102        Graphics::Surface screen;
     103        grabRawScreen(&screen);
     104       
     105        if (screen.bytesPerPixel != 1 || screen.pixels == 0)
     106                return;
     107       
     108        byte palette[256 * 4];
     109        grabPalette(&palette[0], 0, 256);
     110       
     111        surf->create(screen.w, screen.h, (bitsPerPixel + 1) / 8);
     112       
     113        for (uint y = 0; y < screen.h; ++y) {
     114                for (uint x = 0; x < screen.w; ++x) {
     115                        byte r, g, b;
     116                        r = palette[((uint8*)screen.pixels)[y * screen.pitch + x] * 4];
     117                        g = palette[((uint8*)screen.pixels)[y * screen.pitch + x] * 4 + 1];
     118                        b = palette[((uint8*)screen.pixels)[y * screen.pitch + x] * 4 + 2];
     119                       
     120                        if (bitsPerPixel == 15) {
     121                                ((uint16*)surf->pixels)[y * surf->w + x] = (((r >> 3) & 0x1F) << 10) | (((g >> 3) & 0x1F) << 5) | ((b >> 3) & 0x1F);
     122                        } else if (bitsPerPixel == 16) {
     123                                ((uint16*)surf->pixels)[y * surf->w + x] = (((r >> 3) & 0x1F) << 11) | (((g >> 2) & 0x3F) << 5) | ((b >> 3) & 0x1F);
     124                        }
     125                }
     126        }
     127       
     128        screen.free();
     129}
  • common/system.h

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/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/**
     
    358362         *       API are probably going to remove it.
    359363         */
    360364        virtual void setPalette(const byte *colors, uint start, uint num) = 0;
     365       
     366        /**
     367         * Grabs a specified part of the palette
     368         * format is like it is described in setPalette
     369         *
     370         * @param buf   the buffer
     371         * @param start the first platte entry
     372         * @param num   nummber of the entries
     373         */
     374        virtual void grabPalette(byte *colors, uint start, uint num) = 0;
    361375
    362376        /**
    363377         * Blit a bitmap to the virtual screen.
     
    368382         * @see updateScreen
    369383         */
    370384        virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) = 0;
     385
     386        /**
     387         * Copies the screen to a surface
     388         * if bitsPerPixel = 15 a RGB555 format is used
     389         * if bitsPerPixel = 16 a RGB565 format is used
     390         * WARNING: surf->free() musst be called by the user
     391         *
     392         * @param surf          the surfce to store the data in it
     393         * @param bitsPerPixel  must be higher than 15 and lower than 16
     394         */
     395        virtual void grabScreen(Graphics::Surface *surf, int bitsPerPixel);
     396       
     397        /**
     398         * Copies the screen to a surface (with original bit depth)
     399         * It should return a 1 byte per pixel surface in all cases
     400         * because currently all games supported by ScummVM are
     401         * using 1 byte per pixel.
     402         * WARNING: surf->free() musst be called by the user
     403         *
     404         * @param surf  the surfce to store the data in it
     405         */
     406        virtual void grabRawScreen(Graphics::Surface *surf) = 0;
    371407       
    372408        /**
    373409         * Clear the screen to black.
  • graphics/surface.cpp

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/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 --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/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 --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/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
     
    341342                return;
    342343       
    343344        assert(s.bytesPerPixel == sizeof(OverlayColor));
    344 
     345       
    345346        OverlayColor *src = (OverlayColor *)s.pixels;
    346347        OverlayColor *dst = getBasePtr(rect.left, rect.top);
    347 
    348348        int w = rect.width();
    349349        int h = rect.height();
    350350
  • gui/widget.cpp

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/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)
     
    276275        return (pos) * (_valueMax - _valueMin) / (_w - _labelWidth - 4) + _valueMin;
    277276}
    278277
     278#pragma mark -
     279
     280GraphicsWidget::GraphicsWidget(GuiObject *boss, int x, int y, int w, int h)
     281        : Widget(boss, x, y, w, h), _gfx() {
     282        _flags = WIDGET_ENABLED | WIDGET_CLEARBG;
     283        _type = kGraphicsWidget;
     284}
     285
     286GraphicsWidget::~GraphicsWidget() {
     287        _gfx.free();
     288}
     289
     290void GraphicsWidget::setGfx(const Graphics::Surface *gfx) {
     291        _gfx.free();
     292       
     293        if(!gfx)
     294                return;
     295        if(!gfx->pixels)
     296                return;
     297       
     298        // TODO: add conversion to OverlayColor
     299        _gfx.create(gfx->w, gfx->h, gfx->bytesPerPixel);
     300        memcpy(_gfx.pixels, gfx->pixels, gfx->h * gfx->pitch);
     301}
     302
     303void GraphicsWidget::drawWidget(bool hilite) {
     304        if(sizeof(OverlayColor) != _gfx.bytesPerPixel || !_gfx.pixels) {
     305                g_gui.drawString("No preview", _x, _y + _h / 2 - g_gui.getFontHeight() / 2, _w, g_gui._textcolor, Graphics::kTextAlignCenter);
     306                return;
     307        }
     308       
     309        uint drawWidth = _gfx.w, drawHeight = _gfx.h;
     310       
     311        if(_w < _gfx.w)
     312                drawWidth = _w;
     313        if(_h < _gfx.h)
     314                drawHeight = _h;
     315       
     316        g_gui.drawSurface(_gfx, _x, _y);
     317}
     318
    279319} // End of namespace GUI
  • gui/widget.h

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/gui/widget.h ./scummvm/gui/widget.h
    old new  
    2424#include "common/scummsys.h"
    2525#include "common/str.h"
    2626#include "graphics/font.h"
     27#include "graphics/surface.h"
    2728#include "gui/object.h"
    2829
    2930namespace GUI {
     
    5253        kListWidget                     = 'LIST',
    5354        kScrollBarWidget        = 'SCRB',
    5455        kPopUpWidget            = 'POPU',
    55         kTabWidget                      = 'TABW'
     56        kTabWidget                      = 'TABW',
     57        kGraphicsWidget         = 'GFXW'
    5658};
    5759
    5860enum {
     
    210212        int posToValue(int pos);
    211213};
    212214
     215/* GraphicsWidget */
     216class GraphicsWidget : public Widget {
     217public:
     218        GraphicsWidget(GuiObject *boss, int x, int y, int w, int h);
     219        ~GraphicsWidget();
     220       
     221        void setGfx(const Graphics::Surface *gfx);
     222protected:
     223        void drawWidget(bool hilite);
     224       
     225        Graphics::Surface _gfx;
     226};
     227
    213228} // End of namespace GUI
    214229
    215230#endif
  • scumm/dialogs.cpp

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/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 BaseSaveLoadChooser {
    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 BaseSaveLoadChooser {
     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        bool wantsScaling() const { return false; }
     281};
     282
     283SaveLoadChooserEx::SaveLoadChooserEx(const String &title, const String &buttonLabel, bool saveMode, ScummEngine *engine)
     284        : Dialog(8, 8, engine->_system->getOverlayWidth() - 2 * 8, engine->_system->getOverlayHeight() - 16), _saveMode(saveMode), _list(0), _chooseButton(0), _gfxWidget(0), _scumm(engine) {
     285       
     286        new StaticTextWidget(this, 10, 6, _w - 2 * 10, kLineHeight, title, kTextAlignCenter);
     287       
     288        // Add choice list
     289        _list = new GUI::ListWidget(this, 10, 18, _w - 2 * 10 - 180, _h - 14 - 24 - 10);
     290        _list->setEditable(saveMode);
     291        _list->setNumberingMode(saveMode ? GUI::kListNumberingOne : GUI::kListNumberingZero);
     292       
     293        // Add the thumbnail display
     294        _gfxWidget = new GUI::GraphicsWidget(this, _w - (kThumbnailWidth + 22), _y + 6, kThumbnailWidth + 8, ((_scumm->_system->getHeight() % 200 && _scumm->_system->getHeight() != 350) ? kThumbnailHeight_2 : kThumbnailHeight_1) + 8);
     295        _gfxWidget->setFlags(GUI::WIDGET_BORDER);
     296       
     297        // Buttons
     298        addButton(_w - 2 * (kButtonWidth + 10), _h - 24, "Cancel", kCloseCmd, 0);
     299        _chooseButton = addButton(_w-(kButtonWidth + 10), _h - 24, buttonLabel, kChooseCmd, 0);
     300        _chooseButton->setEnabled(false);
     301}
     302
     303const Common::String &SaveLoadChooserEx::getResultString() const {
     304        return _list->getSelectedString();
     305}
     306
     307void SaveLoadChooserEx::setList(const StringList& list) {
     308        _list->setList(list);
     309}
     310
     311int SaveLoadChooserEx::runModal() {
     312        _gfxWidget->setGfx(0);
     313        int ret = GUI::Dialog::runModal();
     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->_thumbnail);
     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 --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/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 BaseSaveLoadChooser
     61{
     62public:
     63        virtual ~BaseSaveLoadChooser() {};
     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        BaseSaveLoadChooser     *_saveDialog;
     83        BaseSaveLoadChooser     *_loadDialog;
    7384
    7485        void save();
    7586        void load();
  • scumm/module.mk

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/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 --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/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);
     
    126127                delete in;
    127128                return false;
    128129        }
     130       
     131        // Sine version 52 a thumbnail is saved directly after the header
     132        if (hdr.ver >= VER(52)) {
     133                if(!loadThumbnail(in)) {
     134                        warning("Can not load thumbnail");
     135                        delete in;
     136                        return false;
     137                }
     138        }
    129139
    130140        // Due to a bug in scummvm up to and including 0.3.0, save games could be saved
    131141        // in the V8/V9 format but were tagged with a V7 mark. Ouch. So we just pretend V7 == V8 here
     
    387397        return true;
    388398}
    389399
     400bool ScummEngine::getThumbnail(int slot) {
     401        char filename[256];
     402        InSaveFile *in;
     403        SaveGameHeader hdr;
     404        int len;
     405       
     406        if (_thumbnail)
     407                _thumbnail->free();
     408        delete _thumbnail;
     409        _thumbnail = 0;
     410
     411        makeSavegameName(filename, slot, false);
     412        if (!(in = _saveFileMan->openForLoading(filename))) {
     413                return false;
     414        }
     415        len = in->read(&hdr, sizeof(hdr));
     416
     417        if (len != sizeof(hdr) || hdr.type != MKID('SCVM')) {
     418                delete in;
     419                return false;
     420        }
     421
     422        if (hdr.ver > CURRENT_VER)
     423                hdr.ver = TO_LE_32(hdr.ver);
     424        if (hdr.ver < VER(52)) {
     425                delete in;
     426                return false;
     427        }
     428
     429        loadThumbnail(in);
     430
     431        delete in;
     432        return true;
     433}
     434
    390435void ScummEngine::saveOrLoad(Serializer *s, uint32 savegameVersion) {
    391436        const SaveLoadEntry objectEntries[] = {
    392437                MKLINE(ObjectData, OBIMoffset, sleUint32, VER(8)),
  • scumm/saveload.h

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/scumm/saveload.h ./scummvm/scumm/saveload.h
    old new  
    4343 * only saves/loads those which are valid for the version of the savegame
    4444 * which is being loaded/saved currently.
    4545 */
    46 #define CURRENT_VER 51
     46#define CURRENT_VER 52
    4747
    4848/**
    4949 * An auxillary macro, used to specify savegame versions. We use this instead
  • scumm/scumm.cpp

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/scumm/scumm.cpp ./scummvm/scumm/scumm.cpp
    old new  
    643643          _platform(gs.platform),
    644644          gdi(this),
    645645          res(this),
    646           _pauseDialog(0), _mainMenuDialog(0), _versionDialog(0),
     646          _pauseDialog(0), _mainMenuDialog(0), _versionDialog(0), _thumbnail(0),
    647647          _targetName(detector->_targetName) {
    648648
    649649        // Copy MD5 checksum
  • scumm/scumm.h

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/scumm/scumm.h ./scummvm/scumm/scumm.h
    old new  
    2727#include "common/file.h"
    2828#include "common/rect.h"
    2929#include "common/str.h"
     30#include "graphics/surface.h"
    3031
    3132#include "scumm/gfx.h"
    3233#include "scumm/script.h"
    3334
     35// FIXME:
     36// define it in a other location
     37#define THMB_VERSION 1
     38
    3439namespace GUI {
    3540        class Dialog;
    3641}
    3742using GUI::Dialog;
    3843class GameDetector;
    39 
     44class InSaveFile;
     45class OutSaveFile;
    4046
    4147namespace Scumm {
    4248
     
    5359class ScummDebugger;
    5460class Serializer;
    5561class Sound;
     62class SaveLoadChooserEx;
    5663
    5764struct Box;
    5865struct BoxCoords;
     
    350357        friend class Insane;
    351358        friend class CharsetRenderer;
    352359        friend class ResourceManager;
     360        friend class SaveLoadChooserEx;
    353361       
    354362        void errorString(const char *buf_input, char *buf_output);
    355363public:
     
    574582        void requestSave(int slot, const char *name, bool temporary = false);
    575583        void requestLoad(int slot);
    576584
     585// thumbnail stuff
     586public:
     587        bool getThumbnail(int slot);
     588        const void* getThumbnail() { if(_thumbnail) return _thumbnail->pixels; return 0; }
     589        uint16 getThumbnailHeight() { if(_thumbnail) return _thumbnail->h; return 0; }
     590        uint16 getThumbnailWidth() { if(_thumbnail) return _thumbnail->w; return 0; }
     591
     592protected:
     593        bool loadThumbnail(InSaveFile *file);
     594        void saveThumbnail(OutSaveFile *file);
     595       
     596        Graphics::Surface *_thumbnail;
     597       
     598        struct ThumbnailHeader {
     599                uint32 type;
     600                uint32 size;
     601                byte version;
     602                uint16 width, height;
     603                byte bpp;
     604        };
     605// ends here
     606
    577607protected:
    578608        /* Script VM - should be in Script class */
    579609        uint32 _localScriptOffsets[1024];
  • scumm/thumbnail.cpp

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/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 casted 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