/* * Copyright 2010 OpenXcom Developers. * * This file is part of OpenXcom. * * OpenXcom is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenXcom is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenXcom. If not, see . */ #include "Screen.h" #include #include #include #include "SDL_rotozoom.h" #include "Exception.h" #include "Surface.h" #include "Action.h" namespace OpenXcom { #define BASE_WIDTH 320.0 #define BASE_HEIGHT 200.0 /** * Initializes a new display screen for the game to render contents to. * @param width Width in pixels. * @param height Height in pixels. * @param bpp Bits-per-pixel. */ Screen::Screen(int width, int height, int bpp) : _xScale(1.0), _yScale(1.0), _fullscreen(false) { _flags = SDL_SWSURFACE|SDL_HWPALETTE; _screen = SDL_SetVideoMode(width, height, bpp, _flags); if (_screen == 0) { throw Exception(SDL_GetError()); } _surface = new Surface(width, height); } /** * Deletes the buffer from memory. The display screen itself * is automatically freed once SDL shuts down. */ Screen::~Screen() { delete _surface; } /** * Returns the screen's internal buffer surface. Any * contents that need to be shown will be blitted to this. * @return Pointer to the buffer surface. */ Surface *const Screen::getSurface() const { return _surface; } /** * Switches fullscreen mode. * @param action Pointer to an action. */ void Screen::handle(Action *action) { if (action->getDetails()->type == SDL_KEYDOWN && action->getDetails()->key.keysym.sym == SDLK_RETURN && (SDL_GetModState() & KMOD_ALT) != 0) { setFullscreen(!_fullscreen); } else if (action->getDetails()->type == SDL_KEYDOWN && action->getDetails()->key.keysym.sym == SDLK_F5) { std::stringstream ss; int i = 0; struct stat info; do { ss.str(""); ss << "./USER/" << "screen" << std::setfill('0') << std::setw(3) << i << ".bmp"; i++; } while (stat(ss.str().c_str(), &info) == 0); SDL_SaveBMP(_screen, ss.str().c_str()); } } /** * Renders the buffer's contents onto the screen, applying * any necessary filters or conversions in the process. * If the scaling factor is bigger than 1, the entire contents * of the buffer are resized by that factor (eg. 2 = doubled) * before being put on screen. */ void Screen::flip() { if (getWidth() != BASE_WIDTH || getHeight() != BASE_HEIGHT) { SDL_Surface* zoom = zoomSurface(_surface->getSurface(), _xScale, _yScale, 0); SDL_BlitSurface(zoom, 0, _screen, 0); SDL_FreeSurface(zoom); } else { SDL_BlitSurface(_surface->getSurface(), 0, _screen, 0); } if (SDL_Flip(_screen) == -1) { throw Exception(SDL_GetError()); } } /** * Clears all the contents out of the internal buffer. */ void Screen::clear() { _surface->clear(); SDL_Rect square; square.x = 0; square.y = 0; square.w = getWidth(); square.h = getHeight(); SDL_FillRect(_screen, &square, 0); } /** * Changes the 8bpp palette used to render the screen's contents. * @param colors Pointer to the set of colors. * @param firstcolor Offset of the first color to replace. * @param ncolors Amount of colors to replace. */ void Screen::setPalette(SDL_Color* colors, int firstcolor, int ncolors) { _surface->setPalette(colors, firstcolor, ncolors); SDL_SetColors(_screen, colors, firstcolor, ncolors); } /** * Returns the screen's 8bpp palette. * @return Pointer to the palette's colors. */ SDL_Color *const Screen::getPalette() const { return _surface->getPalette(); } /** * Returns the width of the screen. * @return Width in pixels. */ int Screen::getWidth() const { return _screen->w; } /** * Returns the height of the screen. * @return Height in pixels */ int Screen::getHeight() const { return _screen->h; } /** * Changes the screen's resolution. The display surface * and palette have to be reset for this to happen properly. * @param width Width in pixels. * @param height Height in pixels. */ void Screen::setResolution(int width, int height) { _xScale = width / BASE_WIDTH; _yScale = height / BASE_HEIGHT; _screen = SDL_SetVideoMode(width, height, _screen->format->BitsPerPixel, _flags); if (_screen == 0) { throw Exception(SDL_GetError()); } setPalette(_surface->getPalette()); } /** * Switches the screen between full-screen and/or windowed. * The screen has to be reset for this to happen properly. * @param full True for full-screen, False for windowed. */ void Screen::setFullscreen(bool full) { _fullscreen = full; if (_fullscreen) { _flags |= SDL_FULLSCREEN; } else { _flags &= ~SDL_FULLSCREEN; } setResolution(getWidth(), getHeight()); } /** * Returns the screen's X scale. * @return Scale factor. */ double Screen::getXScale() const { return _xScale; } /** * Returns the screen's Y scale. * @return Scale factor. */ double Screen::getYScale() const { return _yScale; } }