ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

smacker.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "engines/stark/visual/smacker.h"
00024 
00025 #include "engines/stark/gfx/driver.h"
00026 #include "engines/stark/gfx/surfacerenderer.h"
00027 #include "engines/stark/gfx/texture.h"
00028 #include "engines/stark/scene.h"
00029 #include "engines/stark/services/services.h"
00030 #include "engines/stark/services/settings.h"
00031 
00032 #include "common/str.h"
00033 #include "common/archive.h"
00034 
00035 #include "video/bink_decoder.h"
00036 #include "video/smk_decoder.h"
00037 
00038 namespace Stark {
00039 
00040 VisualSmacker::VisualSmacker(Gfx::Driver *gfx) :
00041         Visual(TYPE),
00042         _gfx(gfx),
00043         _surface(nullptr),
00044         _texture(nullptr),
00045         _decoder(nullptr),
00046         _position(0, 0),
00047         _originalWidth(0),
00048         _originalHeight(0),
00049         _overridenFramerate(-1) {
00050     _surfaceRenderer = _gfx->createSurfaceRenderer();
00051 }
00052 
00053 VisualSmacker::~VisualSmacker() {
00054     delete _texture;
00055     delete _decoder;
00056     delete _surfaceRenderer;
00057 }
00058 
00059 void VisualSmacker::loadSmacker(Common::SeekableReadStream *stream) {
00060     delete _texture;
00061     delete _decoder;
00062 
00063     _decoder = new Video::SmackerDecoder();
00064     _decoder->setSoundType(Audio::Mixer::kSFXSoundType);
00065     _decoder->loadStream(stream);
00066 
00067     init();
00068 }
00069 
00070 void VisualSmacker::loadBink(Common::SeekableReadStream *stream) {
00071     delete _texture;
00072     delete _decoder;
00073 
00074     _decoder = new Video::BinkDecoder();
00075     _decoder->setSoundType(Audio::Mixer::kSFXSoundType);
00076     _decoder->setDefaultHighColorFormat(Gfx::Driver::getRGBAPixelFormat());
00077     _decoder->loadStream(stream);
00078 
00079     init();
00080 }
00081 
00082 void VisualSmacker::init() {
00083     _originalWidth  = _decoder->getWidth();
00084     _originalHeight = _decoder->getHeight();
00085 
00086     rewind();
00087 
00088     _texture = _gfx->createTexture();
00089     _texture->setSamplingFilter(StarkSettings->getImageSamplingFilter());
00090 
00091     update();
00092 }
00093 
00094 void VisualSmacker::readOriginalSize(Common::SeekableReadStream *stream) {
00095     Video::SmackerDecoder smacker;
00096     smacker.loadStream(stream);
00097 
00098     _originalWidth  = smacker.getWidth();
00099     _originalHeight = smacker.getHeight();
00100 }
00101 
00102 void VisualSmacker::render(const Common::Point &position) {
00103     assert(_decoder->getCurFrame() >= 0);
00104 
00105     // The position argument contains the scroll offset
00106     _surfaceRenderer->render(_texture, _position - position, _originalWidth, _originalHeight);
00107 }
00108 
00109 void VisualSmacker::update() {
00110     if (_decoder->needsUpdate()) {
00111         _surface = _decoder->decodeNextFrame();
00112         const byte *palette = _decoder->getPalette();
00113 
00114         if (palette) {
00115             // Convert the surface to RGBA
00116             Graphics::Surface convertedSurface;
00117             convertedSurface.create(_surface->w, _surface->h, Gfx::Driver::getRGBAPixelFormat());
00118 
00119             for (int y = 0; y < _surface->h; y++) {
00120                 const byte *srcRow = (const byte *)_surface->getBasePtr(0, y);
00121                 byte *dstRow = (byte *)convertedSurface.getBasePtr(0, y);
00122 
00123                 for (int x = 0; x < _surface->w; x++) {
00124                     byte index = *srcRow++;
00125 
00126                     byte r = palette[index * 3];
00127                     byte g = palette[index * 3 + 1];
00128                     byte b = palette[index * 3 + 2];
00129 
00130                     if (r != 0 || g != 255 || b != 255) {
00131                         *dstRow++ = r;
00132                         *dstRow++ = g;
00133                         *dstRow++ = b;
00134                         *dstRow++ = 0xFF;
00135                     } else {
00136                         // Cyan is the transparent color
00137                         *dstRow++ = 0;
00138                         *dstRow++ = 0;
00139                         *dstRow++ = 0;
00140                         *dstRow++ = 0;
00141                     }
00142                 }
00143             }
00144 
00145             _texture->update(&convertedSurface);
00146 
00147             convertedSurface.free();
00148         } else {
00149             _texture->update(_surface);
00150         }
00151     }
00152 }
00153 
00154 bool VisualSmacker::isPointSolid(const Common::Point &point) const {
00155     if (!_decoder || !_surface) {
00156         return false;
00157     }
00158 
00159     Common::Point scaledPoint;
00160     scaledPoint.x = point.x * _surface->w / _originalWidth;
00161     scaledPoint.y = point.y * _surface->h / _originalHeight;
00162     scaledPoint.x = CLIP<uint16>(scaledPoint.x, 0, _surface->w);
00163     scaledPoint.y = CLIP<uint16>(scaledPoint.y, 0, _surface->h);
00164 
00165     const byte *ptr = (const byte *)_surface->getBasePtr(scaledPoint.x, scaledPoint.y);
00166     const byte *palette = _decoder->getPalette();
00167     if (palette) {
00168         byte r = palette[*ptr * 3];
00169         byte g = palette[*ptr * 3 + 1];
00170         byte b = palette[*ptr * 3 + 2];
00171 
00172         // Cyan is the transparent color
00173         return r != 0x00 || g != 0xFF || b != 0xFF;
00174     } else {
00175         // Maybe implement this method in some other way to avoid having to keep the surface in memory
00176         return *(ptr + 3) == 0xFF;
00177     }
00178 }
00179 
00180 int VisualSmacker::getFrameNumber() const {
00181     if (_decoder && _decoder->isPlaying()) {
00182         return _decoder->getCurFrame();
00183     }
00184     return -1;
00185 }
00186 
00187 bool VisualSmacker::isDone() {
00188     return getCurrentTime() >= getDuration();
00189 }
00190 
00191 int VisualSmacker::getWidth() const {
00192     return _originalWidth;
00193 }
00194 
00195 int VisualSmacker::getHeight() const {
00196     return _originalHeight;
00197 }
00198 
00199 uint32 VisualSmacker::getDuration() const {
00200     return (_decoder->getRate().getInverse() * _decoder->getDuration().msecs()).toInt();
00201 }
00202 
00203 void VisualSmacker::rewind() {
00204     _decoder->rewind();
00205     _decoder->start();
00206 
00207     if (_overridenFramerate != -1) {
00208         Common::Rational originalFrameRate;
00209 
00210         Video::SmackerDecoder *smacker = dynamic_cast<Video::SmackerDecoder *>(_decoder);
00211         if (smacker) {
00212             originalFrameRate = smacker->getFrameRate();
00213         }
00214 
00215         Video::BinkDecoder *bink = dynamic_cast<Video::BinkDecoder *>(_decoder);
00216         if (bink) {
00217             originalFrameRate = bink->getFrameRate();
00218         }
00219 
00220         Common::Rational playbackRate = _overridenFramerate / originalFrameRate;
00221         _decoder->setRate(playbackRate);
00222     }
00223 }
00224 
00225 uint32 VisualSmacker::getCurrentTime() const {
00226     return (_decoder->getRate().getInverse() * _decoder->getTime()).toInt();
00227 }
00228 
00229 void VisualSmacker::overrideFrameRate(int32 framerate) {
00230     _overridenFramerate = framerate;
00231 }
00232 
00233 void VisualSmacker::pause(bool pause) {
00234     _decoder->pauseVideo(pause);
00235 }
00236 
00237 } // End of namespace Stark


Generated on Sat Apr 20 2019 05:03:55 for ResidualVM by doxygen 1.7.1
curved edge   curved edge