Ticket #8405: thumbnails-v3.patch

File thumbnails-v3.patch, 38.3 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  
    720720        }
    721721}
    722722
     723void OSystem_SDL::grabScreen(byte* buf) {
     724        assert(buf); assert(_screen);
     725        Common::StackLock lock(_graphicsMutex);
     726       
     727        memcpy(buf, _screen->pixels, sizeof(byte) * _screenWidth * _screenHeight);     
     728}
     729
    723730void OSystem_SDL::clearScreen() {
    724731        assert (_transactionMode == kTransactionNone);
    725732
  • 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  
    6767        // The screen will not be updated to reflect the new bitmap
    6868        void copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h);
    6969
     70        // Copies the screen to a buffer
     71        void grabScreen(byte *buf);
     72
    7073        // Clear the screen
    7174        void clearScreen();
    7275
  • common/module.mk

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/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 --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 "scaler.h"
     26#include "scaler/intern.h"
     27
     28template<int bitFormat>
     29void createThumbnail_2(const uint8* src, uint32 srcPitch, uint8* dstPtr, uint32 dstPitch, int width, int height) {
     30        for (int y = 0; y < height; y += 2) {
     31                for (int x = 0; x < width; x += 2, dstPtr += 2) {
     32                        uint16 colorx1y1 = *(((const uint16*)src) + x);
     33                        uint16 colorx2y1 = *(((const uint16*)src) + x + 1);
     34                       
     35                        uint16 colorx1y2 = *(((const uint16*)(src + srcPitch)) + x);
     36                        uint16 colorx2y2 = *(((const uint16*)(src + srcPitch)) + x + 1);
     37                               
     38                        *((uint16*)dstPtr) = Q_INTERPOLATE<bitFormat>(colorx1y1, colorx2y1, colorx1y2, colorx2y2);                     
     39                }
     40                dstPtr += (dstPitch - 320);
     41                src += 2 * srcPitch;
     42        }
     43}
     44
     45template<int bitFormat>
     46void createThumbnail_4(const uint8* src, uint32 srcPitch, uint8* dstPtr, uint32 dstPitch, int width, int height) {
     47        for (int y = 0; y < height; y += 4) {
     48                for (int x = 0; x < width; x += 4, dstPtr += 2) {
     49                        uint16 colorx1y1 = *(((const uint16*)src) + x);
     50                        uint16 colorx2y1 = *(((const uint16*)src) + x + 1);
     51                        uint16 colorx3y1 = *(((const uint16*)src) + x + 2);
     52                        uint16 colorx4y1 = *(((const uint16*)src) + x + 3);
     53                       
     54                        uint16 colorx1y2 = *(((const uint16*)(src + srcPitch)) + x);
     55                        uint16 colorx2y2 = *(((const uint16*)(src + srcPitch)) + x + 1);
     56                        uint16 colorx3y2 = *(((const uint16*)(src + srcPitch)) + x + 2);
     57                        uint16 colorx4y2 = *(((const uint16*)(src + srcPitch)) + x + 3);
     58                       
     59                        uint16 colorx1y3 = *(((const uint16*)(src + srcPitch * 2)) + x);
     60                        uint16 colorx2y3 = *(((const uint16*)(src + srcPitch * 2)) + x + 1);
     61                        uint16 colorx3y3 = *(((const uint16*)(src + srcPitch * 2)) + x + 2);
     62                        uint16 colorx4y3 = *(((const uint16*)(src + srcPitch * 2)) + x + 3);
     63                       
     64                        uint16 colorx1y4 = *(((const uint16*)(src + srcPitch * 3)) + x);
     65                        uint16 colorx2y4 = *(((const uint16*)(src + srcPitch * 3)) + x + 1);
     66                        uint16 colorx3y4 = *(((const uint16*)(src + srcPitch * 3)) + x + 2);
     67                        uint16 colorx4y4 = *(((const uint16*)(src + srcPitch * 3)) + x + 3);
     68                               
     69                        uint16 upleft = Q_INTERPOLATE<bitFormat>(colorx1y1, colorx2y1, colorx1y2, colorx2y2);
     70                        uint16 upright = Q_INTERPOLATE<bitFormat>(colorx3y1, colorx4y1, colorx3y2, colorx4y2);
     71                        uint16 downleft = Q_INTERPOLATE<bitFormat>(colorx1y3, colorx2y3, colorx1y4, colorx2y4);
     72                        uint16 downright = Q_INTERPOLATE<bitFormat>(colorx3y3, colorx4y3, colorx3y4, colorx4y4);
     73                               
     74                        *((uint16*)dstPtr) = Q_INTERPOLATE<bitFormat>(upleft, upright, downleft, downright);                   
     75                }
     76                dstPtr += (dstPitch - 320);
     77                src += 4 * srcPitch;
     78        }
     79}
     80
     81void createThumbnail(const uint8* src, uint32 srcPitch, uint8* dstPtr, uint32 dstPitch, int width, int height) {
     82        // only 1/2 and 1/4 downscale supported
     83        if(width != 320 && width != 640)
     84                return;
     85               
     86        const int downScaleMode = (width == 320) ? 2 : 4;
     87       
     88        if(downScaleMode == 2) {
     89                createThumbnail_2<565>(src, srcPitch, dstPtr, dstPitch, width, height);
     90        } else if(downScaleMode == 4) {
     91                createThumbnail_4<565>(src, srcPitch, dstPtr, dstPitch, width, height);
     92        }
     93}
  • common/scaler.h

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/common/scaler.h ./scummvm/common/scaler.h
    old new  
    5959
    6060extern int stretch200To240(uint8 *buf, uint32 pitch, int width, int height, int srcX, int srcY, int origSrcY);
    6161
     62// creates a 160x100 thumbnail for 320x200 games
     63// and 160x120 thumbnail for 320x240 and 640x480 games
     64// only 565 mode
     65extern void createThumbnail(const uint8* src, uint32 srcPitch, uint8* dstPtr, uint32 dstPitch, int width, int height);
     66
    6267enum {
    6368        GFX_NORMAL = 0,
    6469        GFX_DOUBLESIZE = 1,
  • common/system.h

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/common/system.h ./scummvm/common/system.h
    old new  
    290290         * @see updateScreen
    291291         */
    292292        virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) = 0;
     293
     294        /**
     295         * Copies the screen to a buffer
     296         */
     297        virtual void grabScreen(byte *buf) {}
    293298       
    294299        /**
    295300         * Clear the screen to black.
  • config.h

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/config.h ./scummvm/config.h
    old new  
     1/* This file is automatically generated by configure */
     2/* DO NOT EDIT MANUALLY */
     3
     4#ifndef CONFIG_H
     5#define CONFIG_H
     6
     7#define SCUMM_LITTLE_ENDIAN
     8#undef SCUMM_NEED_ALIGNMENT
     9#define HAVE_X86
     10
     11#undef LINUPY
     12
     13/* Data types */
     14typedef unsigned char byte;
     15typedef unsigned int uint;
     16typedef unsigned char uint8;
     17typedef unsigned short uint16;
     18typedef unsigned int uint32;
     19typedef signed char int8;
     20typedef signed short int16;
     21typedef signed int int32;
     22
     23/* Libs */
     24#define USE_VORBIS
     25#undef USE_FLAC
     26#define USE_MAD
     27#define USE_ALSA
     28#define USE_ZLIB
     29#define USE_MPEG2
     30#define USE_MT32EMU
     31
     32/* Whether we should use i386 assembly routines */
     33#define USE_NASM
     34
     35/* Plugin settings */
     36
     37
     38#endif /* CONFIG_H */
  • gui/ListWidget.cpp

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/gui/ListWidget.cpp ./scummvm/gui/ListWidget.cpp
    old new  
    380380}
    381381
    382382void ListWidget::endEditMode() {
     383        if(!_editMode)
     384                return;
    383385        // send a message that editing finished with a return/enter key press
    384386        _editMode = false;
    385387        _list[_selectedItem] = _editString;
  • gui/ListWidget.h

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/gui/ListWidget.h ./scummvm/gui/ListWidget.h
    old new  
    8686
    8787        // Made startEditMode for SCUMM's SaveLoadChooser
    8888        void startEditMode();
     89        void endEditMode();
    8990
    9091protected:
    9192        void drawWidget(bool hilite);
     
    9394        int findItem(int x, int y) const;
    9495        void scrollBarRecalc();
    9596
    96         void endEditMode();
    9797        void abortEditMode();
    9898       
    9999        Common::Rect getEditRect() 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
     
    405406}
    406407
    407408//
     409// Copies a Surface to the Overlay
     410//
     411void NewGui::drawSurface(const OverlayColor* data, int x, int y, int width, int height, int pitch) {
     412        if(_scaleFactor == 1) {
     413                uint8* dst = (uint8*)getBasePtr(x, y); 
     414                for (int y_ = 0; y_ < height; ++y_, dst += _screen.pitch) {
     415                        memcpy(dst, &((const uint8*)data)[y_ * pitch], width * sizeof(OverlayColor));
     416                }
     417        } else if(_scaleFactor == 2) {
     418                Normal2x((const uint8*)data, pitch, (uint8*)getBasePtr(x * 2, y * 2), _screen.pitch, width, height);
     419        }       
     420        addDirtyRect(x, y, width, height);
     421}
     422
     423//
    408424// Draw the mouse cursor (animated). This is mostly ripped from the cursor code in gfx.cpp
    409425// We could plug in a different cursor here if we like to.
    410426//
  • gui/newgui.cpp.orig

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/gui/newgui.cpp.orig ./scummvm/gui/newgui.cpp.orig
    old new  
     1/* ScummVM - Scumm Interpreter
     2 * Copyright (C) 2002-2005 The ScummVM project
     3 *
     4 * This program is free software; you can redistribute it and/or
     5 * modify it under the terms of the GNU General Public License
     6 * as published by the Free Software Foundation; either version 2
     7 * of the License, or (at your option) any later version.
     8 *
     9 * This program is distributed in the hope that it will be useful,
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 * GNU General Public License for more details.
     13 *
     14 * You should have received a copy of the GNU General Public License
     15 * along with this program; if not, write to the Free Software
     16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17 *
     18 * $Header: /cvsroot/scummvm/scummvm/gui/newgui.cpp,v 1.105 2005/03/25 22:11:07 sev Exp $
     19 */
     20
     21#include "stdafx.h"
     22#include "common/system.h"
     23#include "common/util.h"
     24#include "gui/newgui.h"
     25#include "gui/dialog.h"
     26
     27
     28DECLARE_SINGLETON(GUI::NewGui);
     29
     30namespace GUI {
     31
     32/*
     33 * TODO list
     34 * - add more widgets: edit field, popup, radio buttons, ...
     35 *
     36 * Other ideas:
     37 * - allow multi line (l/c/r aligned) text via StaticTextWidget ?
     38 * - add "close" widget to all dialogs (with a flag to turn it off) ?
     39 * - make dialogs "moveable" ?
     40 * - come up with a new look & feel / theme for the GUI
     41 * - ...
     42 */
     43
     44enum {
     45        kDoubleClickDelay = 500, // milliseconds
     46        kCursorAnimateDelay = 250,
     47        kKeyRepeatInitialDelay = 400,
     48        kKeyRepeatSustainDelay = 100
     49};
     50
     51
     52// Constructor
     53NewGui::NewGui() : _scaleEnable(true), _needRedraw(false),
     54        _stateIsSaved(false), _font(0), _cursorAnimateCounter(0), _cursorAnimateTimer(0) {
     55
     56        _system = &OSystem::instance();
     57
     58        // Clear the cursor
     59        memset(_cursor, 0xFF, sizeof(_cursor));
     60
     61        // Reset key repeat
     62        _currentKeyDown.keycode = 0;
     63
     64        // updates the scaling factor
     65        updateScaleFactor();
     66}
     67
     68void NewGui::updateColors() {
     69        // Setup some default GUI colors.
     70        _bgcolor = _system->RGBToColor(0, 0, 0);
     71        _color = _system->RGBToColor(104, 104, 104);
     72        _shadowcolor = _system->RGBToColor(64, 64, 64);
     73        _textcolor = _system->RGBToColor(32, 160, 32);
     74        _textcolorhi = _system->RGBToColor(0, 255, 0);
     75}
     76
     77void NewGui::updateScaleFactor() {
     78        if(!_scaleEnable) {
     79                _scaleFactor = 1;
     80        } else {
     81                enum {
     82                        kDefaultGUIWidth = 320,
     83                        kDefaultGUIHeight = 200
     84                };
     85       
     86                // NES has 256 pixels width which makes MIN() return 0 here.
     87                _scaleFactor = MAX(MIN(_system->getOverlayWidth() / kDefaultGUIWidth, _system->getOverlayHeight() / kDefaultGUIHeight), 1);
     88        }
     89
     90        // Pick the font depending on the scale factor.
     91        if (_scaleFactor == 1)
     92                _font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont);
     93        else
     94                _font = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont);
     95}
     96
     97void NewGui::runLoop() {
     98        Dialog *activeDialog = _dialogStack.top();
     99        bool didSaveState = false;
     100        int button;
     101
     102        if (activeDialog == 0)
     103                return;
     104
     105        // Setup some default GUI colors. Normally this will be done whenever an
     106        // EVENT_SCREEN_CHANGED is received. However, not yet all backends support
     107        // that event, so we also do it "manually" whenever a run loop is entered.
     108        updateColors();
     109        updateScaleFactor();
     110
     111        if (!_stateIsSaved) {
     112                saveState();
     113                didSaveState = true;
     114        }
     115
     116        while (!_dialogStack.empty() && activeDialog == _dialogStack.top()) {
     117                activeDialog->handleTickle();
     118
     119                if (_needRedraw) {
     120                        // Restore the overlay to its initial state, then draw all dialogs.
     121                        // This is necessary to get the blending right.
     122                        _system->clearOverlay();
     123                        _system->grabOverlay((OverlayColor *)_screen.pixels, _screenPitch);
     124                        for (int i = 0; i < _dialogStack.size(); i++)
     125                                _dialogStack[i]->drawDialog();
     126                        _needRedraw = false;
     127                }
     128
     129                animateCursor();
     130                _system->updateScreen();
     131
     132                OSystem::Event event;
     133                uint32 time = _system->getMillis();
     134
     135                while (_system->pollEvent(event)) {
     136                        Common::Point mouse(event.mouse.x - (activeDialog->_x * _scaleFactor), event.mouse.y - (activeDialog->_y * _scaleFactor));
     137                        mouse.x /= _scaleFactor;
     138                        mouse.y /= _scaleFactor;
     139                       
     140                        switch (event.type) {
     141                        case OSystem::EVENT_KEYDOWN:
     142#if !defined(__PALM_OS__)
     143                                // init continuous event stream
     144                                // not done on PalmOS because keyboard is emulated and keyup is not generated
     145                                _currentKeyDown.ascii = event.kbd.ascii;
     146                                _currentKeyDown.keycode = event.kbd.keycode;
     147                                _currentKeyDown.flags = event.kbd.flags;
     148                                _keyRepeatTime = time + kKeyRepeatInitialDelay;
     149#endif
     150                                activeDialog->handleKeyDown(event.kbd.ascii, event.kbd.keycode, event.kbd.flags);
     151                                break;
     152                        case OSystem::EVENT_KEYUP:
     153                                activeDialog->handleKeyUp(event.kbd.ascii, event.kbd.keycode, event.kbd.flags);
     154                                if (event.kbd.keycode == _currentKeyDown.keycode)
     155                                        // only stop firing events if it's the current key
     156                                        _currentKeyDown.keycode = 0;
     157                                break;
     158                        case OSystem::EVENT_MOUSEMOVE:
     159                                activeDialog->handleMouseMoved(mouse.x, mouse.y, 0);
     160                                break;
     161                        // We don't distinguish between mousebuttons (for now at least)
     162                        case OSystem::EVENT_LBUTTONDOWN:
     163                        case OSystem::EVENT_RBUTTONDOWN:
     164                                button = (event.type == OSystem::EVENT_LBUTTONDOWN ? 1 : 2);
     165                                if (_lastClick.count && (time < _lastClick.time + kDoubleClickDelay)
     166                                                        && ABS(_lastClick.x - event.mouse.x) < 3
     167                                                        && ABS(_lastClick.y - event.mouse.y) < 3) {
     168                                        _lastClick.count++;
     169                                } else {
     170                                        _lastClick.x = event.mouse.x;
     171                                        _lastClick.y = event.mouse.y;
     172                                        _lastClick.count = 1;
     173                                }
     174                                _lastClick.time = time;
     175                                activeDialog->handleMouseDown(mouse.x, mouse.y, button, _lastClick.count);
     176                                break;
     177                        case OSystem::EVENT_LBUTTONUP:
     178                        case OSystem::EVENT_RBUTTONUP:
     179                                button = (event.type == OSystem::EVENT_LBUTTONUP ? 1 : 2);
     180                                activeDialog->handleMouseUp(mouse.x, mouse.y, button, _lastClick.count);
     181                                break;
     182                        case OSystem::EVENT_WHEELUP:
     183                                activeDialog->handleMouseWheel(mouse.x, mouse.y, -1);
     184                                break;
     185                        case OSystem::EVENT_WHEELDOWN:
     186                                activeDialog->handleMouseWheel(mouse.x, mouse.y, 1);
     187                                break;
     188                        case OSystem::EVENT_QUIT:
     189                                _system->quit();
     190                                return;
     191                        case OSystem::EVENT_SCREEN_CHANGED:
     192                                updateColors();
     193                                updateScaleFactor();
     194                                activeDialog->handleScreenChanged();
     195                                break;
     196                        }
     197                }
     198
     199                // check if event should be sent again (keydown)
     200                if (_currentKeyDown.keycode != 0) {
     201                        if (_keyRepeatTime < time) {
     202                                // fire event
     203                                activeDialog->handleKeyDown(_currentKeyDown.ascii, _currentKeyDown.keycode, _currentKeyDown.flags);
     204                                _keyRepeatTime = time + kKeyRepeatSustainDelay;
     205                        }
     206                }
     207
     208                // Delay for a moment
     209                _system->delayMillis(10);
     210        }
     211
     212        if (didSaveState)
     213                restoreState();
     214}
     215
     216#pragma mark -
     217
     218void NewGui::saveState() {
     219
     220        // Backup old cursor
     221        _oldCursorMode = _system->showMouse(true);
     222
     223        // Enable the overlay
     224        _system->showOverlay();
     225
     226        // Create a screen buffer for the overlay data, and fill it with
     227        // whatever is visible on the screen rught now.
     228        _screen.h = _system->getOverlayHeight();
     229        _screen.w = _system->getOverlayWidth();
     230        _screen.bytesPerPixel = sizeof(OverlayColor);
     231        _screen.pitch = _screen.w * _screen.bytesPerPixel;
     232        _screenPitch = _screen.w;
     233        _screen.pixels = (OverlayColor*)calloc(_screen.w * _screen.h, sizeof(OverlayColor));
     234
     235        _system->grabOverlay((OverlayColor *)_screen.pixels, _screenPitch);
     236
     237        _currentKeyDown.keycode = 0;
     238        _lastClick.x = _lastClick.y = 0;
     239        _lastClick.time = 0;
     240        _lastClick.count = 0;
     241
     242        _stateIsSaved = true;
     243}
     244
     245void NewGui::restoreState() {
     246        _system->showMouse(_oldCursorMode);
     247
     248        _system->hideOverlay();
     249        if (_screen.pixels) {
     250                free(_screen.pixels);
     251                _screen.pixels = 0;
     252        }
     253
     254        _system->updateScreen();
     255
     256        _stateIsSaved = false;
     257}
     258
     259void NewGui::openDialog(Dialog *dialog) {
     260        _dialogStack.push(dialog);
     261        _needRedraw = true;
     262}
     263
     264void NewGui::closeTopDialog() {
     265        // Don't do anything if no dialog is open
     266        if (_dialogStack.empty())
     267                return;
     268
     269        // Remove the dialog from the stack
     270        _dialogStack.pop();
     271        _needRedraw = true;
     272}
     273
     274#pragma mark -
     275
     276const Graphics::Font &NewGui::getFont() const {
     277        return *_font;
     278}
     279
     280OverlayColor *NewGui::getBasePtr(int x, int y) {
     281        return (OverlayColor *)_screen.getBasePtr(x, y);
     282}
     283
     284void NewGui::box(int x, int y, int width, int height, OverlayColor colorA, OverlayColor colorB) {
     285        hLine(x + 1, y, x + width - 2, colorA);
     286        hLine(x, y + 1, x + width - 1, colorA);
     287        vLine(x, y + 1, y + height - 2, colorA);
     288        vLine(x + 1, y, y + height - 1, colorA);
     289
     290        hLine(x + 1, y + height - 2, x + width - 1, colorB);
     291        hLine(x + 1, y + height - 1, x + width - 2, colorB);
     292        vLine(x + width - 1, y + 1, y + height - 2, colorB);
     293        vLine(x + width - 2, y + 1, y + height - 1, colorB);
     294}
     295
     296void NewGui::hLine(int x, int y, int x2, OverlayColor color) {
     297        _screen.hLine(x * _scaleFactor, y * _scaleFactor, x2 * _scaleFactor, color);
     298}
     299
     300void NewGui::vLine(int x, int y, int y2, OverlayColor color) {
     301        _screen.vLine(x * _scaleFactor, y * _scaleFactor, y2 * _scaleFactor, color);
     302}
     303
     304void NewGui::blendRect(int x, int y, int w, int h, OverlayColor color, int level) {
     305#ifdef NEWGUI_256
     306        fillRect(x, y, w, h, color);
     307#else
     308        Common::Rect rect(x * _scaleFactor, y * _scaleFactor, (x + w) * _scaleFactor, (y + h) * _scaleFactor);
     309        rect.clip(_screen.w, _screen.h);
     310
     311        if (!rect.isValidRect())
     312                return;
     313
     314        int r, g, b;
     315        uint8 ar, ag, ab;
     316        _system->colorToRGB(color, ar, ag, ab);
     317        r = ar * level;
     318        g = ag * level;
     319        b = ab * level;
     320
     321        OverlayColor *ptr = getBasePtr(rect.left, rect.top);
     322
     323        h = rect.height();
     324        w = rect.width();
     325        while (h--) {
     326                for (int i = 0; i < w; i++) {
     327                        _system->colorToRGB(ptr[i], ar, ag, ab);
     328                        ptr[i] = _system->RGBToColor((ar + r) / (level+1),
     329                                                                                 (ag + g) / (level+1),
     330                                                                                 (ab + b) / (level+1));
     331                }
     332                ptr += _screenPitch;
     333        }
     334#endif
     335}
     336
     337void NewGui::fillRect(int x, int y, int w, int h, OverlayColor color) {
     338        _screen.fillRect(Common::Rect(x * _scaleFactor, y * _scaleFactor, (x+w) * _scaleFactor, (y+h) * _scaleFactor), color);
     339}
     340
     341void NewGui::frameRect(int x, int y, int w, int h, OverlayColor color) {
     342        _screen.frameRect(Common::Rect(x * _scaleFactor, y * _scaleFactor, (x+w) * _scaleFactor, (y+h) * _scaleFactor), color);
     343}
     344
     345void NewGui::addDirtyRect(int x, int y, int w, int h) {
     346        Common::Rect rect(x * _scaleFactor, y * _scaleFactor, (x + w) * _scaleFactor, (y + h) * _scaleFactor);
     347        rect.clip(_screen.w, _screen.h);
     348
     349        if (!rect.isValidRect())
     350                return;
     351
     352        // For now we don't keep yet another list of dirty rects but simply
     353        // blit the affected area directly to the overlay. At least for our current
     354        // GUI/widget/dialog code that is just fine.
     355        OverlayColor *buf = getBasePtr(rect.left, rect.top);
     356        _system->copyRectToOverlay(buf, _screenPitch, rect.left, rect.top, rect.width(), rect.height());
     357}
     358
     359void NewGui::drawChar(byte chr, int xx, int yy, OverlayColor color, const Graphics::Font *font) {
     360        if (font == 0)
     361                font = &getFont();
     362        font->drawChar(&_screen, chr, xx * _scaleFactor, yy * _scaleFactor, color);
     363}
     364
     365int NewGui::getStringWidth(const String &str) const {
     366        return getFont().getStringWidth(str) / _scaleFactor;
     367}
     368
     369int NewGui::getCharWidth(byte c) const {
     370        return getFont().getCharWidth(c) / _scaleFactor;
     371}
     372
     373int NewGui::getFontHeight() const {
     374        return getFont().getFontHeight() / _scaleFactor;
     375}
     376
     377void NewGui::drawString(const String &s, int x, int y, int w, OverlayColor color, TextAlignment align, int deltax, bool useEllipsis) {
     378        getFont().drawString(&_screen, s, x * _scaleFactor, y * _scaleFactor, w * _scaleFactor, color, align, deltax, useEllipsis);
     379}
     380
     381//
     382// Draw an 8x8 bitmap at location (x,y)
     383//
     384void NewGui::drawBitmap(uint32 *bitmap, int tx, int ty, OverlayColor color, int h) {
     385        tx *= _scaleFactor; ty *= _scaleFactor;
     386        h *= _scaleFactor;
     387        OverlayColor *ptr = getBasePtr(tx, ty);
     388
     389        for (int y = 0; y < h; y++, ptr += _screenPitch) {
     390                uint32 mask = 0xF0000000;
     391                if (ty + y < 0 || ty + y >= _screen.h)
     392                        continue;
     393                for (int x = 0; x < 8 * _scaleFactor; x++) {
     394                        if(!(x % 2) && _scaleFactor != 1 && x != 0)
     395                                mask >>= 4;
     396                        else if(_scaleFactor == 1)
     397                                mask >>= 4;
     398
     399                        if (tx + x < 0 || tx + x >= _screen.w)
     400                                continue;
     401                        if (bitmap[y / _scaleFactor] & mask)
     402                                        ptr[x] = color;
     403                }
     404        }
     405}
     406
     407//
     408// Draw the mouse cursor (animated). This is mostly ripped from the cursor code in gfx.cpp
     409// We could plug in a different cursor here if we like to.
     410//
     411void NewGui::animateCursor() {
     412        int time = _system->getMillis();
     413        if (time > _cursorAnimateTimer + kCursorAnimateDelay) {
     414                const byte colors[4] = { 15, 15, 7, 8 };
     415                const byte color = colors[_cursorAnimateCounter];
     416                int i;
     417
     418                for (i = 0; i < 15; i++) {
     419                        if ((i < 6) || (i > 8)) {
     420                                _cursor[16 * 7 + i] = color;
     421                                _cursor[16 * i + 7] = color;
     422                        }
     423                }
     424
     425                _system->setMouseCursor(_cursor, 16, 16, 7, 7);
     426
     427                _cursorAnimateTimer = time;
     428                _cursorAnimateCounter = (_cursorAnimateCounter + 1) % 4;
     429        }
     430}
     431
     432} // End of namespace GUI
  • gui/newgui.h

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/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 --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)
     
    260259        return (pos) * (_valueMax - _valueMin) / (_w - _labelWidth - 4) + _valueMin;
    261260}
    262261
     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);
     305}
     306
    263307} // 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  
    5252        kListWidget                     = 'LIST',
    5353        kScrollBarWidget        = 'SCRB',
    5454        kPopUpWidget            = 'POPU',
    55         kTabWidget                      = 'TABW'
     55        kTabWidget                      = 'TABW',
     56        kGraphicsWidget         = 'GFXW'
    5657};
    5758
    5859enum {
     
    210211        int posToValue(int pos);
    211212};
    212213
     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;
     227};
     228
    213229} // End of namespace GUI
    214230
    215231#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 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 - 182, _y + 6, 168, (_scumm->_system->getHeight() % 200) ? 128 : 108);
     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        _scumm->_hasThumbnail = 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        g_gui.enableScaling(false);
     313        int ret = GUI::Dialog::runModal();
     314        g_gui.enableScaling(true);
     315        return ret;
     316}
     317
     318void SaveLoadChooserEx::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
     319        int selItem = _list->getSelected();
     320        switch (cmd) {
     321        case GUI::kListItemActivatedCmd:
     322        case GUI::kListItemDoubleClickedCmd:
     323                if (selItem >= 0) {
     324                        if (_saveMode || !getResultString().isEmpty()) {
     325                                _list->endEditMode();
     326                                setResult(selItem);
     327                                close();
     328                        }
     329                }
     330                break;
     331        case kChooseCmd:
     332                _list->endEditMode();
     333                setResult(selItem);
     334                close();
     335                break;
     336        case GUI::kListSelectionChangedCmd:
     337                _scumm->loadThumbnailFromSlot(_saveMode ? selItem + 1 : selItem);
     338                _gfxWidget->setGfx(160, (_scumm->_system->getHeight() % 200) ? 120 : 100, 2, _scumm->_hasThumbnail == true ? (const uint8*)_scumm->getThumbnail() : 0);
     339                _gfxWidget->draw();
     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 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 --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/scumm/module.mk ./scummvm/scumm/module.mk
    old new  
    7575        scumm/smush/smush_player.o \
    7676        scumm/smush/saud_channel.o \
    7777        scumm/smush/smush_mixer.o \
    78         scumm/smush/smush_font.o
     78        scumm/smush/smush_font.o \
     79        scumm/thumbnail.o
    7980
    8081MODULE_DIRS += \
    8182        scumm \
  • scumm/saveload.cpp

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/scumm/saveload.cpp ./scummvm/scumm/saveload.cpp
    old new  
    8787        Serializer ser(out, true, CURRENT_VER);
    8888        saveOrLoad(&ser, CURRENT_VER);
    8989        delete out;
     90        // create thumbnail file
     91        makeSavegameName(filename, slot, false);
     92        strcat(filename, ".tmb");       
     93        if (!(out = _saveFileMan->openSavefile(filename, true)))
     94                return false;           
     95        createThumbnail();
     96        for (uint16 p = 0; p < 160*120; ++p)
     97                out->writeUint16LE(_thumbnail[p]);
     98        delete out;
     99        // --------------------
     100
    90101        debug(1, "State saved as '%s'", filename);
    91102        return true;
    92103}
  • scumm/scumm.cpp

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/scumm/scumm.cpp ./scummvm/scumm/scumm.cpp
    old new  
    592592          gdi(this), _pauseDialog(0), _mainMenuDialog(0), _versionDialog(0),
    593593          _targetName(detector->_targetName) {
    594594
     595        // clears thumbnail
     596        memset(_thumbnail, 0, sizeof(uint16)*160*120);
     597
    595598        // Copy MD5 checksum
    596599        memcpy(_gameMD5, md5sum, 16);
    597600
  • scumm/scumm.h

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/scumm/scumm.h ./scummvm/scumm/scumm.h
    old new  
    544544
    545545        void lock(int type, int i);
    546546        void unlock(int type, int i);
    547 
     547       
     548// thumbnail stuff
     549public:
     550        void createThumbnail();
     551        void loadThumbnailFromData(const uint16* data);
     552        void loadThumbnailFromSlot(int slot);
     553        const uint16* getThumbnail() { return _thumbnail; }
     554       
     555        bool _hasThumbnail;
     556protected:
     557        uint16 _thumbnail[160*120];
     558// ends here
     559       
    548560protected:
    549561        /* Heap and memory management */
    550562        uint32 _maxHeapThreshold, _minHeapThreshold;
  • 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 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 "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 {
     31
     32inline uint16 RGBToColor(const uint8 r, const uint8 g, const uint8 b) {
     33        return ((((r >> 3) & 0x1F) << 11) | (((g >> 2) & 0x3F) << 5) | ((b >> 3) & 0x1F));
     34}
     35
     36inline void colorToRGB(uint16 color, uint8 &r, uint8 &g, uint8 &b) {
     37        r = (((color >> 11) & 0x1F) << 3);
     38        g = (((color >> 5) & 0x3F) << 2);
     39        b = ((color&0x1F) << 3);
     40}
     41
     42void ScummEngine::createThumbnail() {
     43        if(sizeof(OverlayColor) != sizeof(uint16))
     44                return;
     45       
     46        byte *temporaryScreen = new byte[_system->getWidth() * _system->getHeight()];
     47        assert(temporaryScreen);
     48       
     49        _system->grabScreen(temporaryScreen);
     50       
     51        uint16 *screen = new uint16[_system->getWidth() * _system->getHeight()];
     52        assert(screen);
     53       
     54        const uint8 *palette = _currentPalette;
     55       
     56        for(int y = 0; y < _system->getHeight(); ++y) {
     57                for(int x = 0; x < _system->getWidth(); ++x) {
     58                        uint8 index = temporaryScreen[y * _system->getWidth() + x];                     
     59                        screen[y * _system->getWidth() + x] = RGBToColor(palette[index * 3], palette[index * 3 + 1], palette[index * 3 + 2]);
     60                }
     61        }
     62       
     63        delete [] temporaryScreen;
     64        temporaryScreen = 0;
     65       
     66        memset(_thumbnail, 0, 160*120*2);       
     67        ::createThumbnail((const uint8*)screen, _system->getWidth() * 2, (uint8*)_thumbnail, 320, _system->getWidth(), _system->getHeight());
     68       
     69        delete [] screen;
     70}
     71
     72void ScummEngine::loadThumbnailFromData(const uint16* data) {
     73        if(sizeof(OverlayColor) != sizeof(uint16))
     74                return;
     75
     76        for (int y = 0; y < 120; ++y) {
     77                for (int x = 0; x < 160; ++x) {
     78                        uint8 r, g, b;
     79                        colorToRGB(data[y * 160 + x], r, g, b);
     80                       
     81                        // converting to current OSystem Color
     82                        _thumbnail[y * 160 + x] = _system->RGBToColor(r, g, b);
     83                }
     84        }
     85}
     86
     87void ScummEngine::loadThumbnailFromSlot(int slot) {
     88        char filename[256];
     89        makeSavegameName(filename, slot, false);
     90        strcat(filename, ".tmb");
     91       
     92        SaveFile *out;
     93        if (!(out = _saveFileMan->openSavefile(filename, false))) {
     94                delete out;
     95                memset(_thumbnail, 0, sizeof(uint16) * 160*120);
     96                _hasThumbnail = false;
     97                return;
     98        }
     99       
     100        for (uint16 p = 0; p < 160*120; ++p)
     101                _thumbnail[p] = out->readUint16LE();   
     102        loadThumbnailFromData(_thumbnail);
     103        _hasThumbnail = true;
     104        delete out;
     105}
     106
     107
     108} // end of namespace Scumm