Ticket #7996: screenshot3.diff

File screenshot3.diff, 6.4 KB (added by eriktorbjorn, 22 years ago)

Patch against a September 26 CVS snapshot

  • scummvm/Makefile

    diff -ur ScummVM-cvs20020926/scummvm/Makefile ScummVM-cvs20020926+hack/scummvm/Makefile
    old new  
    3131DEFINES += -DCOMPRESSED_SOUND_FILE
    3232LIBS    += -lmad
    3333
     34# Uncomment this to activate the PNG lib for screenshots
     35# DEFINES += -DHAVE_LIBPNG
     36# LIBS    += -lpng
     37
    3438# Uncomment this to activate the ALSA lib for midi
    3539# DEFINES += -DUSE_ALSA
    3640# LIBS    += -lasound
  • scummvm/common/engine.cpp

    diff -ur ScummVM-cvs20020926/scummvm/common/engine.cpp ScummVM-cvs20020926+hack/scummvm/common/engine.cpp
    old new  
    1818 * $Header: /cvsroot/scummvm/scummvm/common/engine.cpp,v 1.6 2002/09/26 12:29:10 fingolfin Exp $
    1919 */
    2020
     21#ifdef HAVE_LIBPNG
     22#include <png.h>
     23#endif
     24
    2125#include "stdafx.h"
    2226#include "engine.h"
    2327#include "gameDetector.h"
    2428#include "config-file.h"
     29#include "util.h"
    2530#include "scumm/scumm.h"
    2631#include "simon/simon.h"
    2732#include "sound/mixer.h"
     
    7782        return dir;
    7883}
    7984
     85void Engine::saveScreenshot(OSystem *syst)
     86{
     87#ifdef HAVE_LIBPNG
     88        png_structp png_ptr;
     89        png_infop info_ptr;
     90        char filename[255];
     91        const char *savedir;
     92        int16 *buf;
     93        png_byte *image;
     94        int i, j;
     95
     96        savedir = getSavePath();
     97
     98        // FIXME: Is there a better way of making a temporary filename? Should
     99        // it be made into a separate function?
     100
     101        for (i = 0; i < 1000; i++) {
     102                sprintf(filename, "%sscr%03d.png", savedir, i);
     103                _fp = fopen(filename, "rb");
     104                if (!_fp)
     105                        break;
     106        }
     107
     108        if (_fp) {
     109                warning("Could not create temporary filename for screenshot");
     110                fclose(_fp);
     111                return;
     112        }
     113
     114        _fp = fopen(filename, "wb");
     115        if (!_fp) {
     116                warning("Could not create temporary file for screenshot");
     117                return;
     118        }
     119
     120        // FIXME: We need a way to get the correct screen size. For now, use
     121        // the same dirty hack assumptions as newgui.cpp
     122
     123        int screen_height = 240;
     124        int screen_width = 320;
     125        int screen_pitch = 320;
     126
     127        // Apparently it's possible to slim down libpng quite a bit, but I'm
     128        // going to assume that all the basic features are still there.
     129
     130        png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
     131                (png_voidp) NULL, (png_error_ptr) NULL, (png_error_ptr) NULL);
     132
     133        if (!png_ptr) {
     134                warning("Could not create PNG write struct");
     135                fclose(_fp);
     136                return;
     137        }
     138
     139        info_ptr = png_create_info_struct(png_ptr);
     140        if (!info_ptr) {
     141                warning("Could not create PNG info struct");
     142                fclose(_fp);
     143                png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
     144                return;
     145        }
     146
     147#ifndef PNG_SETJMP_NOT_SUPPORTED
     148#       ifndef png_jmpbuf
     149#               define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
     150#       endif
     151
     152        if (setjmp(png_jmpbuf(png_ptr))) {
     153                warning("Internal libpng error");
     154                fclose(_fp);
     155                png_destroy_write_struct(&png_ptr, &info_ptr);
     156                return;
     157        }
     158#endif
     159
     160        png_init_io(png_ptr, _fp);
     161
     162        buf = (int16 *) malloc(screen_width * screen_height * sizeof(int16));
     163        if (!buf) {
     164                warning("Could not allocate memory for screen buffer");
     165                fclose(_fp);
     166                png_destroy_write_struct(&png_ptr, &info_ptr);
     167                return;
     168        }
     169
     170        image = (png_byte *) calloc(screen_width, 3 * sizeof(png_byte));
     171        if (!image) {
     172                warning("Could not allocate memory for PNG image");
     173                free(buf);
     174                fclose(_fp);
     175                png_destroy_write_struct(&png_ptr, &info_ptr);
     176                return;
     177        }
     178
     179        // Grab a screenshot
     180
     181        // FIXME: I'd really like some way of getting the image that is
     182        // actually being displayed.
     183
     184        syst->show_overlay();
     185        syst->grab_overlay(buf, screen_pitch);
     186        syst->hide_overlay();
     187
     188        png_set_IHDR(png_ptr, info_ptr, screen_width, screen_height, 8,
     189                PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
     190                PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
     191
     192        png_write_info(png_ptr, info_ptr);
     193
     194        for (i = 0; i < screen_height; i++) {
     195                for (j = 0; j < screen_width; j++) {
     196                        image[j * 3 + 0] = RED_FROM_16(buf[i * screen_width + j]);
     197                        image[j * 3 + 1] = GREEN_FROM_16(buf[i * screen_width + j]);
     198                        image[j * 3 + 2] = BLUE_FROM_16(buf[i * screen_width + j]);
     199                }
     200
     201                png_write_rows(png_ptr, &image, 1);
     202        }
     203
     204        png_write_end(png_ptr, info_ptr);
     205        png_destroy_write_struct(&png_ptr, &info_ptr);
     206
     207        free(buf);
     208        free(image);
     209        fclose(_fp);
     210
     211        debug(1, "Saved snapshot in %s", filename);
     212#else
     213        // FIXME: As a fallback, we should have an image-writing function that
     214        // doesn't require any external libraries.
     215        warning("No PNG support! Screenshot feature disabled");
     216#endif
     217}
     218
    80219Engine *Engine::createFromDetector(GameDetector *detector, OSystem *syst)
    81220{
    82221        Engine *engine;
  • scummvm/common/engine.h

    diff -ur ScummVM-cvs20020926/scummvm/common/engine.h ScummVM-cvs20020926+hack/scummvm/common/engine.h
    old new  
    5555
    5656        const char *getGameDataPath() const { return _gameDataPath; }
    5757
     58        void saveScreenshot(OSystem *syst);
     59       
    5860        // Create a new engine object based on the detector - either
    5961        // a Scumm or a SimonState object currently.
    6062        static Engine *createFromDetector(GameDetector *detector, OSystem *syst);
     63       
     64        // Hack to avoid scary GCC warning in saveScreenshot()
     65        FILE *_fp;
    6166};
    6267
    6368#if defined(__GNUC__)
  • scummvm/scumm/scummvm.cpp

    diff -ur ScummVM-cvs20020926/scummvm/scumm/scummvm.cpp ScummVM-cvs20020926+hack/scummvm/scumm/scummvm.cpp
    old new  
    13471347                                                g_debugger.attach(this);
    13481348                                        else if (event.kbd.keycode=='s')
    13491349                                                resourceStats();
     1350                                } else if (event.kbd.flags==OSystem::KBD_ALT) {
     1351                                        if (event.kbd.keycode=='s')
     1352                                                saveScreenshot(_system);
    13501353                                } else
    13511354                                        _keyPressed = event.kbd.ascii;  // Normal key press, pass on to the game.
    13521355                                break;
  • scummvm/simon/simon.cpp

    diff -ur ScummVM-cvs20020926/scummvm/simon/simon.cpp ScummVM-cvs20020926+hack/scummvm/simon/simon.cpp
    old new  
    44074407                                        if (event.kbd.keycode == 'f') {
    44084408                                                _fast_mode ^= 1;
    44094409                                        }
     4410                                } else if (event.kbd.flags == OSystem::KBD_ALT) {
     4411                                        if (event.kbd.keycode == 's') {
     4412                                                saveScreenshot(_system);
     4413                                        }
    44104414                                }
    44114415                                _key_pressed = (byte)event.kbd.ascii;
    44124416                                break;