From 06ef80fa6170bec33f9ac117400fa86f965c4aa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Ko=C5=82odziejski?= Date: Mon, 17 Mar 2003 12:28:50 +0000 Subject: [PATCH] reorg/clenup, changed main loop in smush code svn-id: r6817 --- scumm/smush/brenderer.cpp | 77 -- scumm/smush/brenderer.h | 81 -- scumm/smush/channel.h | 70 +- scumm/smush/chunk.cpp | 77 +- scumm/smush/chunk.h | 72 +- scumm/smush/codec1.cpp | 29 +- scumm/smush/codec1.h | 48 -- scumm/smush/codec37.cpp | 72 +- scumm/smush/codec37.h | 35 +- scumm/smush/codec44.cpp | 62 -- scumm/smush/codec44.h | 34 - scumm/smush/codec47.cpp | 67 +- scumm/smush/codec47.h | 27 +- scumm/smush/color.cpp | 37 - scumm/smush/color.h | 55 -- scumm/smush/decoder.h | 51 -- scumm/smush/frenderer.cpp | 399 --------- scumm/smush/frenderer.h | 165 ---- scumm/smush/imuse_channel.cpp | 18 +- scumm/smush/mixer.h | 58 -- scumm/smush/palette.h | 57 -- scumm/smush/player.h | 109 --- scumm/smush/renderer.h | 125 --- scumm/smush/saud_channel.cpp | 52 +- scumm/smush/scumm_renderer.cpp | 320 ------- scumm/smush/scumm_renderer.h | 65 -- scumm/smush/smush_font.cpp | 489 +++++++++++ scumm/smush/smush_font.h | 67 ++ scumm/smush/smush_mixer.cpp | 166 ++++ scumm/smush/{config.h => smush_mixer.h} | 42 +- scumm/smush/{player.cpp => smush_player.cpp} | 847 +++++++++---------- scumm/smush/smush_player.h | 105 +++ 32 files changed, 1491 insertions(+), 2487 deletions(-) delete mode 100644 scumm/smush/brenderer.cpp delete mode 100644 scumm/smush/brenderer.h delete mode 100644 scumm/smush/codec1.h delete mode 100644 scumm/smush/codec44.cpp delete mode 100644 scumm/smush/codec44.h delete mode 100644 scumm/smush/color.cpp delete mode 100644 scumm/smush/color.h delete mode 100644 scumm/smush/decoder.h delete mode 100644 scumm/smush/frenderer.cpp delete mode 100644 scumm/smush/frenderer.h delete mode 100644 scumm/smush/mixer.h delete mode 100644 scumm/smush/palette.h delete mode 100644 scumm/smush/player.h delete mode 100644 scumm/smush/renderer.h delete mode 100644 scumm/smush/scumm_renderer.cpp delete mode 100644 scumm/smush/scumm_renderer.h create mode 100644 scumm/smush/smush_font.cpp create mode 100644 scumm/smush/smush_font.h create mode 100644 scumm/smush/smush_mixer.cpp rename scumm/smush/{config.h => smush_mixer.h} (64%) rename scumm/smush/{player.cpp => smush_player.cpp} (56%) create mode 100644 scumm/smush/smush_player.h diff --git a/scumm/smush/brenderer.cpp b/scumm/smush/brenderer.cpp deleted file mode 100644 index 45bd5be1671..00000000000 --- a/scumm/smush/brenderer.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2002-2003 The ScummVM project - * - * This program 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 2 - * of the License, or (at your option) any later version. - - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - * - */ - -#include -#include "brenderer.h" - -#include "common/engine.h" // for debug, warning, error - -#include - -void BaseRenderer::clean() { - if(_data) { - delete[] _data; - _data = 0; - _width = _height = 0; - } -} - -BaseRenderer::BaseRenderer() : - _data(0), - _frame(0), - _nbframes(0), - _width(0), - _height(0) { -} - -BaseRenderer::~BaseRenderer() { - clean(); -} - -bool BaseRenderer::initFrame(const Point &p) { - clean(); - _width = p.getX(); - _height = p.getY(); - assert(_width && _height); - _data = new byte[_width * _height]; - if(!_data) error("base_renderer unable to allocate frame buffer"); - return true; -} - -byte *BaseRenderer::lockFrame(int32 frame) { - _frame = frame; - if(!_data) error("no allocated image buffer in lock_frame"); - return _data; -} - -bool BaseRenderer::unlockFrame() { - return true; -} - -bool BaseRenderer::flipFrame() { - save(); - return true; -} - -bool BaseRenderer::setPalette(const Palette & pal) { - _pal = pal; - return true; -} diff --git a/scumm/smush/brenderer.h b/scumm/smush/brenderer.h deleted file mode 100644 index 9fd616552e5..00000000000 --- a/scumm/smush/brenderer.h +++ /dev/null @@ -1,81 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2002-2003 The ScummVM project - * - * This program 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 2 - * of the License, or (at your option) any later version. - - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - * - */ - -#ifndef BRENDERER_H -#define BRENDERER_H - -#include "config.h" - -#include "renderer.h" -#include "palette.h" - -/*! @brief base class for easily creating ::renderer instances - - This class implements some function available in the ::renderer abstract class, so that - creation of subclasses of ::renderer is easier. -*/ -class BaseRenderer : public Renderer { -protected: - Palette _pal; //!< The current palette - byte *_data; //!< The current frame buffer - int32 _frame; //!< The current frame number - int32 _nbframes; //!< The number of frames in the animation - int32 _width; //!< The current frame's width - int32 _height; //!< The current frame's height - const char *_fname; //!< The filename of the animation being played -protected: - virtual void save() = 0; - -protected: - const char *getFilename() const { return _fname; }; //!< accessor for animation filename - int32 getNbframes() const { return _nbframes; }; //!< accessor for number of frames - void clean(); //!< memory cleanup (deletes frame buffer) - void setFrame(int32 f) { _frame = f; }; //!< allows to change the frame number -public: - int32 getFrame() const { return _frame; }; //!< accessor for current frame number - BaseRenderer(); - virtual ~BaseRenderer(); - - virtual bool initFrame(const Point &size); - virtual byte *lockFrame(int32 frame); - virtual bool unlockFrame(); - virtual bool flipFrame(); - virtual bool setPalette(const Palette &pal); - virtual bool startDecode(const char *fname, int32 version, int32 nbframes) { _fname = fname; _nbframes = nbframes; return true; } - virtual Mixer *getMixer() { return 0; }; - virtual bool prematureClose() { return false; }; -}; - -/*! @brief A null ::renderer - - This class completely implements ::renderer, without actually doing anything. - This class is useful for performance measurements. -*/ -class NullRenderer : public BaseRenderer { -protected: - void save() {}; -public: - NullRenderer() {}; - virtual ~NullRenderer() {}; - bool wait(int32 ms) { return true; }; -}; - -#endif diff --git a/scumm/smush/channel.h b/scumm/smush/channel.h index 03b93280ee4..c0ce8ca7fb3 100644 --- a/scumm/smush/channel.h +++ b/scumm/smush/channel.h @@ -19,63 +19,47 @@ * */ -#ifndef CHANNEL_H -#define CHANNEL_H +#ifndef SMUSH_CHANNEL_H +#define SMUSH_CHANNEL_H -#include "config.h" -#include "common/engine.h" // for debug, warning, error - -#ifdef DEBUG -# ifndef NO_DEBUG_CHANNEL -# define DEBUG_CHANNEL -# endif -#else -# ifdef DEBUG_CHANNEL -# error DEBUG_CHANNEL defined without DEBUG -# endif -#endif +#include "common/engine.h" class Chunk; class ContChunk; -/*! @brief int32erface for a sound channel (a track) - - This is the int32erface for sound channels. -*/ -class _Channel { +class SmushChannel { public: - virtual ~_Channel() {}; - // called by the smush_player + + virtual ~SmushChannel() {}; virtual bool appendData(Chunk &b, int32 size) = 0; virtual bool setParameters(int32, int32, int32, int32) = 0; virtual bool checkParameters(int32, int32, int32, int32, int32) = 0; - // called by the mixer virtual bool isTerminated() const = 0; virtual int32 availableSoundData() const = 0; - virtual void getSoundData(int16 *sound_buffer, int32 size) = 0; // size is in sample + virtual void getSoundData(int16 *sound_buffer, int32 size) = 0; virtual void getSoundData(int8 *sound_buffer, int32 size) = 0; virtual int32 getRate() = 0; virtual bool getParameters(int32 &rate, bool &stereo, bool &is_16bit) = 0; virtual int32 getTrackIdentifier() const = 0; }; -class SaudChannel : public _Channel { +class SaudChannel : public SmushChannel { private: - int32 _track; //!< The track identifier - int32 _nbframes; //!< number of frames of the track (unused) - int32 _dataSize; //!< the size of the sound buffer - int32 _frequency; //!< the frequency target of the track (always 22050) - bool _inData; //!< are we processing data ? - bool _markReached; //!< set to \c true when the SMRK tag is reached - int32 _flags; //!< current flags of the track (unused) - int32 _volume; //!< the current track volume - int32 _balance; //!< the current track balance - int32 _index; //!< the current PSAD index (for coherency checking) - int16 _voltable[2][256]; //!< the precalculated volume table (stereo 16 bits) - byte *_tbuffer; //!< data temporary buffer - int32 _tbufferSize; //!< temporary buffer size - byte *_sbuffer; //!< sound buffer - int32 _sbufferSize; //!< sound buffer size + int32 _track; + int32 _nbframes; + int32 _dataSize; + int32 _frequency; + bool _inData; + bool _markReached; + int32 _flags; + int32 _volume; + int32 _balance; + int32 _index; + int16 _voltable[2][256]; + byte *_tbuffer; + int32 _tbufferSize; + byte *_sbuffer; + int32 _sbufferSize; protected: void handleStrk(Chunk &c); @@ -105,13 +89,7 @@ public: virtual int32 getTrackIdentifier() const { return _track; }; }; -/*! @brief class for a IACT sound ::channel (a The Dig track) - - This class implements a channel specifically for The Dig. - - \bug for unknown reason, some sound have a too long duration, or repeat themselves. -*/ -class ImuseChannel : public _Channel { +class ImuseChannel : public SmushChannel { private: int32 _track; //!< the track number byte *_tbuffer; //!< data temporary buffer diff --git a/scumm/smush/chunk.cpp b/scumm/smush/chunk.cpp index f35e91fffae..0f3bfbf7346 100644 --- a/scumm/smush/chunk.cpp +++ b/scumm/smush/chunk.cpp @@ -22,35 +22,34 @@ #include #include "chunk.h" -#include "common/engine.h" // for debug, warning, error +#include "common/engine.h" #include "common/file.h" #include "common/str.h" -#include // for FILE, fopen, fclose, fseek and ftell -#include // for memcpy - -/*! @brief very small and fast wrapper for a ifstream. - - implements reference counting, so that ::file_Chunk does not leak memory ! -*/ class FilePtr { ScummVM::String _filename; File _ifs; int32 _refcount; int32 _curPos; public: - FilePtr(const char *fname, const char *directory) : _filename(fname), _refcount(1), _curPos(0) { - debug(9, "FilePtr created for %s", fname); - _ifs.open(fname, directory); - if(_ifs.isOpen() == false) error("FilePtr unable to read file %s", fname); - } + FilePtr(const char *fname, const char *directory) : + _filename(fname), + _refcount(1), + _curPos(0) { + debug(9, "FilePtr created for %s", fname); + _ifs.open(fname, directory); + if(_ifs.isOpen() == false) error("FilePtr unable to read file %s", fname); + } + ~FilePtr() { debug(9, "FilePtr destroyed for %s", _filename.c_str()); _ifs.close(); } + int32 tell() { return _curPos; } + bool seek(int32 pos) { if(pos != _curPos) { _ifs.seek(pos, SEEK_SET); @@ -58,14 +57,17 @@ public: } return true; } + bool read(void *ptr, int32 size) { _ifs.read(ptr, size); _curPos += size; return true; } + void incRef() { _refcount++; } + void decRef() { if(--_refcount == 0) delete this; @@ -82,11 +84,16 @@ const char *Chunk::ChunkString(Chunk::type t) { return data; } -FileChunk::FileChunk() : _data(0), _type(0), _size(0), _curPos(0) { +FileChunk::FileChunk() : + _data(0), + _type(0), + _size(0), + _curPos(0) { } FileChunk::~FileChunk() { - if(_data) _data->decRef(); + if(_data) + _data->decRef(); } FileChunk::FileChunk(const char *fname, const char *directory) { @@ -137,11 +144,15 @@ bool FileChunk::seek(int32 delta, seek_type dir) { _curPos += delta; break; case seek_start: - if(delta < 0) error("invalid seek request"); + if(delta < 0) + error("invalid seek request"); + _curPos = (uint32)delta; break; case seek_end: - if(delta > 0 || (_size + delta) < 0) error("invalid seek request"); + if(delta > 0 || (_size + delta) < 0) + error("invalid seek request"); + _curPos = (uint32)(_size + delta); break; } @@ -154,6 +165,7 @@ bool FileChunk::seek(int32 delta, seek_type dir) { bool FileChunk::read(void *buffer, uint32 size) { if(size <= 0 || (_curPos + size) > _size) error("invalid buffer read request"); + _data->seek(_offset + _curPos); _data->read(buffer, size); _curPos += size; @@ -163,6 +175,7 @@ bool FileChunk::read(void *buffer, uint32 size) { int8 FileChunk::getChar() { if(_curPos >= _size) error("invalid char read request"); + _data->seek(_offset + _curPos); int8 buffer; _data->read(&buffer, sizeof(buffer)); @@ -173,6 +186,7 @@ int8 FileChunk::getChar() { byte FileChunk::getByte() { if(_curPos >= _size) error("invalid byte read request"); + _data->seek(_offset + _curPos); byte buffer; _data->read(&buffer, sizeof(buffer)); @@ -188,6 +202,7 @@ int16 FileChunk::getShort() { uint16 FileChunk::getWord() { if(_curPos >= _size - 1) error("invalid word read request"); + _data->seek(_offset + _curPos); uint16 buffer; _data->read(&buffer, sizeof(buffer)); @@ -198,6 +213,7 @@ uint16 FileChunk::getWord() { uint32 FileChunk::getDword() { if(_curPos >= _size - 3) error("invalid dword read request"); + _data->seek(_offset + _curPos); uint32 buffer; _data->read(&buffer, sizeof(buffer)); @@ -207,7 +223,8 @@ uint32 FileChunk::getDword() { ContChunk::ContChunk(byte *data) { if(data == 0) - error("Chunk() called with NULL point32er"); + error("Chunk() called with NULL pointer"); + _type = (Chunk::type)READ_BE_UINT32(data); _size = READ_BE_UINT32(data + 4); _data = data + sizeof(Chunk::type) + sizeof(uint32); @@ -257,39 +274,51 @@ bool ContChunk::seek(int32 delta, seek_type dir) { } bool ContChunk::read(void *buffer, uint32 size) { - if(size <= 0 || (_curPos + size) > _size) error("invalid buffer read request"); + if(size <= 0 || (_curPos + size) > _size) + error("invalid buffer read request"); + memcpy(buffer, _data + _curPos, size); _curPos += size; return true; } int8 ContChunk::getChar() { - if(_curPos >= _size) error("invalid char read request"); + if(_curPos >= _size) + error("invalid char read request"); + return _data[_curPos++]; } byte ContChunk::getByte() { - if(_curPos >= _size) error("invalid byte read request"); + if(_curPos >= _size) + error("invalid byte read request"); + byte *ptr = (byte *)(_data + _curPos); _curPos += 1; return *ptr; } int16 ContChunk::getShort() { - if(_curPos >= _size - 1) error("invalid int16 read request"); + if(_curPos >= _size - 1) + error("invalid int16 read request"); + int16 buffer = getWord(); return *((int16 *)&buffer); } uint16 ContChunk::getWord() { - if(_curPos >= _size - 1) error("invalid word read request"); + if(_curPos >= _size - 1) + error("invalid word read request"); + uint16 *ptr = (uint16 *)(_data + _curPos); _curPos += 2; return READ_LE_UINT16(ptr); } uint32 ContChunk::getDword() { - if(_curPos >= _size - 3) error("invalid dword read request"); + if(_curPos >= _size - 3) + error("invalid dword read request"); + uint32 *ptr = (uint32 *)(_data + _curPos); _curPos += 4; return READ_LE_UINT32(ptr); diff --git a/scumm/smush/chunk.h b/scumm/smush/chunk.h index 44a9150392b..0549c887161 100644 --- a/scumm/smush/chunk.h +++ b/scumm/smush/chunk.h @@ -22,69 +22,54 @@ #ifndef CHUNK_H #define CHUNK_H -#include "config.h" +#include "common/scummsys.h" -/*! @brief Interface for Chunk handling - - This class is an interface for reading from a Chunk. - - \todo handle big endian system. -*/ class Chunk { public: - enum seek_type { seek_start, seek_end, seek_cur }; - virtual ~Chunk() {}; - typedef uint32 type; //!< type of a Chunk (i.e. The first 4byte field of the Chunk structure). - /*! @brief convert a type to a string - - Utility function that convert a type to a string. - - @param t the type to convert to a string - - @return the converted string - */ - static const char * ChunkString(type t); - virtual type getType() const = 0; //!< return the type of the Chunk - virtual uint32 getSize() const = 0; //!< return the size of the Chunk - virtual Chunk * subBlock() = 0; //!< extract a subChunk from the current read position - virtual bool eof() const = 0; //!< is the Chunk completely read ? - virtual uint32 tell() const = 0; //!< get the Chunk current read position - virtual bool seek(int32 delta, seek_type dir = seek_cur) = 0; //!< move the current read position inside the Chunk - virtual bool read(void * buffer, uint32 size) = 0; //!< read some data for the current read position - virtual int8 getChar() = 0; //!< extract the character at the current read position - virtual byte getByte() = 0; //!< extract the byte at the current read position - virtual int16 getShort() = 0; //!< extract the short at the current read position - virtual uint16 getWord() = 0; //!< extract the word at the current read position - virtual uint32 getDword()= 0; //!< extract the dword at the current read position + virtual ~Chunk() {}; + enum seek_type { seek_start, seek_end, seek_cur }; + typedef uint32 type; + static const char *ChunkString(type t); + virtual type getType() const = 0; + virtual uint32 getSize() const = 0; + virtual Chunk *subBlock() = 0; + virtual bool eof() const = 0; + virtual uint32 tell() const = 0; + virtual bool seek(int32 delta, seek_type dir = seek_cur) = 0; + virtual bool read(void *buffer, uint32 size) = 0; + virtual int8 getChar() = 0; + virtual byte getByte() = 0; + virtual int16 getShort() = 0; + virtual uint16 getWord() = 0; + virtual uint32 getDword()= 0; }; class FilePtr; -/*! @brief file based ::Chunk - - This class is an implementation of ::Chunk that handles file. - -*/ class FileChunk : public Chunk { private: - FilePtr * _data; + FilePtr *_data; type _type; uint32 _size; uint32 _offset; uint32 _curPos; + protected: + FileChunk(); + public: - FileChunk(const char * fname, const char * directory); + + FileChunk(const char *fname, const char *directory); virtual ~FileChunk(); type getType() const; uint32 getSize() const; - Chunk * subBlock(); + Chunk *subBlock(); bool eof() const; uint32 tell() const; bool seek(int32 delta, seek_type dir = seek_cur); - bool read(void * buffer, uint32 size); + bool read(void *buffer, uint32 size); int8 getChar(); byte getByte(); short getShort(); @@ -92,17 +77,16 @@ public: uint32 getDword(); }; -/*! @brief memory based ::Chunk - - This class is an implementation of ::Chunk that handles a memory buffer. -*/ class ContChunk : public Chunk { private: + byte *_data; Chunk::type _type; uint32 _size; uint32 _curPos; + public: + ContChunk(byte *data); Chunk::type getType() const; uint32 getSize() const; diff --git a/scumm/smush/codec1.cpp b/scumm/smush/codec1.cpp index 589ec2ee51d..673a9c1d0ee 100644 --- a/scumm/smush/codec1.cpp +++ b/scumm/smush/codec1.cpp @@ -20,44 +20,28 @@ */ #include -#include "codec1.h" +#include "common/scummsys.h" -Codec1Decoder::~Codec1Decoder() { -} - -bool Codec1Decoder::decode(byte *dst, const byte *src, int) { - byte val; - int32 size_line; - int32 code, length; - int32 h, height = getRect().height(); +void smush_decode_codec1(byte *dst, byte *src, int height) { + byte val, code; + int32 length; + int h = height, size_line; for(h = 0; h < height; h++) { - size_line = READ_LE_UINT16(src); // size of compressed line ! + size_line = READ_LE_UINT16(src); src += 2; -#ifdef DEBUG_CODEC1 - debug(7, "codec1 : h == %d, size_line == %d", h, size_line); -#endif while(size_line > 0) { code = *src++; size_line--; length = (code >> 1) + 1; -#ifdef DEBUG_CODEC1 - debug(7, "codec1 : length == %d", length); -#endif if(code & 1) { val = *src++; size_line--; if (val) memset(dst, val, length); dst += length; -#ifdef DEBUG_CODEC1 - debug(7, "codec1 : blitting %d times %d", length, val); -#endif } else { size_line -= length; -#ifdef DEBUG_CODEC1 - debug(7, "codec1 : blitting %d entries", length); -#endif while(length--) { val = *src++; if (val) @@ -67,5 +51,4 @@ bool Codec1Decoder::decode(byte *dst, const byte *src, int) { } } } - return true; } diff --git a/scumm/smush/codec1.h b/scumm/smush/codec1.h deleted file mode 100644 index ee2b806868c..00000000000 --- a/scumm/smush/codec1.h +++ /dev/null @@ -1,48 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2002-2003 The ScummVM project - * - * This program 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 2 - * of the License, or (at your option) any later version. - - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - * - */ - -#ifndef CODEC1_H -#define CODEC1_H - -#include "config.h" - -#ifdef DEBUG -# ifndef NO_DEBUG_CODEC1 -# define DEBUG_CODEC1 -# endif -#else -# ifdef DEBUG_CODEC1 -# error DEBUG_CODEC1 defined without DEBUG -# endif -#endif - -#include "decoder.h" - -/*! @brief ::decoder for codec 1 and 3. - -*/ -class Codec1Decoder : public Decoder { -public: - virtual ~Codec1Decoder(); - bool decode(byte *dst, const byte *src, int length); -}; - -#endif diff --git a/scumm/smush/codec37.cpp b/scumm/smush/codec37.cpp index 03a23410e26..a2087c4b517 100644 --- a/scumm/smush/codec37.cpp +++ b/scumm/smush/codec37.cpp @@ -24,35 +24,24 @@ #include "common/engine.h" -#include -#include - -bool Codec37Decoder::initSize(const Point &p, const Rect &r) { - if(r.width() != getRect().width() && r.height() != getRect().height()) { - if( - (r.width() != 320 || r.height() != 200) && - (r.width() != 384 || r.height() != 242) && - (r.width() != 640 || r.height() != 480) - ) - return false; - Decoder::initSize(p, r); - clean(); - int32 frame_size = getRect().width() * getRect().height(); - _deltaSize = frame_size * 3 + 0x13600; - _deltaBuf = new byte[_deltaSize]; - memset(_deltaBuf, 0, _deltaSize); - if(_deltaBuf == 0) error("unable to allocate decoder buffer"); - _deltaBufs[0] = _deltaBuf + 0x4D80; - _deltaBufs[1] = _deltaBuf + 0xE880 + frame_size; - _offsetTable = new int16[255]; - _curtable = 0; - if(_offsetTable == 0) - error("unable to allocate decoder offset table"); - _tableLastPitch = -1; - _tableLastIndex = -1; - return true; - } - return false; +void Codec37Decoder::init(int width, int height) { + deinit(); + _width = width; + _height = height; + _frameSize = _width * _height; + _deltaSize = _frameSize * 3 + 0x13600; + _deltaBuf = new byte[_deltaSize]; + memset(_deltaBuf, 0, _deltaSize); + if(_deltaBuf == 0) + error("unable to allocate decoder buffer"); + _deltaBufs[0] = _deltaBuf + 0x4D80; + _deltaBufs[1] = _deltaBuf + 0xE880 + _frameSize; + _offsetTable = new int16[255]; + _curtable = 0; + if(_offsetTable == 0) + error("unable to allocate decoder offset table"); + _tableLastPitch = -1; + _tableLastIndex = -1; } Codec37Decoder::Codec37Decoder() { @@ -67,7 +56,7 @@ Codec37Decoder::Codec37Decoder() { _prevSeqNb = 0; } -void Codec37Decoder::clean() { +void Codec37Decoder::deinit() { if(_offsetTable) { delete []_offsetTable; _offsetTable = 0; @@ -84,10 +73,10 @@ void Codec37Decoder::clean() { } Codec37Decoder::~Codec37Decoder() { - clean(); + deinit(); } -void Codec37Decoder::maketable(int32 pitch, int32 index) { +void Codec37Decoder::maketable(int pitch, int index) { static const int8 maketable_bytes[] = { 0, 0, 1, 0, 2, 0, 3, 0, 5, 0, 8, 0, 13, 0, 21, 0, -1, 0, -2, 0, @@ -246,6 +235,7 @@ void Codec37Decoder::maketable(int32 pitch, int32 index) { if (_tableLastPitch == pitch && _tableLastIndex == index) return; + _tableLastPitch = pitch; _tableLastIndex = index; index *= 255; @@ -368,7 +358,7 @@ void Codec37Decoder::bompDecode(byte *dst, const byte *src, int len) { dst += 4; \ } while(0) -void Codec37Decoder::proc3WithFDFE(byte *dst, const byte *src, int32 next_offs, int32 bw, int32 bh, int32 pitch, int16 *offset_table) { +void Codec37Decoder::proc3WithFDFE(byte *dst, const byte *src, int32 next_offs, int bw, int bh, int pitch, int16 *offset_table) { do { int32 i = bw; do { @@ -388,7 +378,7 @@ void Codec37Decoder::proc3WithFDFE(byte *dst, const byte *src, int32 next_offs, } while (--bh); } -void Codec37Decoder::proc3WithoutFDFE(byte *dst, const byte *src, int32 next_offs, int32 bw, int32 bh, int32 pitch, int16 *offset_table) { +void Codec37Decoder::proc3WithoutFDFE(byte *dst, const byte *src, int32 next_offs, int bw, int bh, int pitch, int16 *offset_table) { do { int32 i = bw; do { @@ -404,7 +394,7 @@ void Codec37Decoder::proc3WithoutFDFE(byte *dst, const byte *src, int32 next_off } while (--bh); } -void Codec37Decoder::proc4WithFDFE(byte *dst, const byte *src, int32 next_offs, int32 bw, int32 bh, int32 pitch, int16 *offset_table) { +void Codec37Decoder::proc4WithFDFE(byte *dst, const byte *src, int32 next_offs, int bw, int bh, int pitch, int16 *offset_table) { do { int32 i = bw; do { @@ -440,7 +430,7 @@ void Codec37Decoder::proc4WithFDFE(byte *dst, const byte *src, int32 next_offs, } while (--bh); } -void Codec37Decoder::proc4WithoutFDFE(byte *dst, const byte *src, int32 next_offs, int32 bw, int32 bh, int32 pitch, int16 *offset_table) { +void Codec37Decoder::proc4WithoutFDFE(byte *dst, const byte *src, int32 next_offs, int bw, int bh, int pitch, int16 *offset_table) { do { int32 i = bw; do { @@ -472,10 +462,8 @@ void Codec37Decoder::proc4WithoutFDFE(byte *dst, const byte *src, int32 next_off } while (--bh); } -bool Codec37Decoder::decode(byte *dst, const byte *src, int length) { - int32 width = getRect().width(); - int32 height = getRect().height(); - int32 bw = (width + 3) >> 2, bh = (height + 3) >> 2; +void Codec37Decoder::decode(byte *dst, const byte *src) { + int32 bw = (_width + 3) >> 2, bh = (_height + 3) >> 2; int32 pitch = bw << 2; int16 seq_nb = READ_LE_UINT16(src + 2); @@ -543,8 +531,6 @@ bool Codec37Decoder::decode(byte *dst, const byte *src, int length) { } _prevSeqNb = seq_nb; - memcpy(dst, _deltaBufs[_curtable], width * height); - - return true; + memcpy(dst, _deltaBufs[_curtable], _frameSize); } diff --git a/scumm/smush/codec37.h b/scumm/smush/codec37.h index 0773f50f220..52f4504665d 100644 --- a/scumm/smush/codec37.h +++ b/scumm/smush/codec37.h @@ -19,36 +19,39 @@ * */ -#ifndef CODEC37_H -#define CODEC37_H +#ifndef SMUSH_CODEC37_H +#define SMUSH_CODEC37_H -#include "decoder.h" +#include "common/scummsys.h" -class Codec37Decoder : public Decoder { +class Codec37Decoder { private: + int32 _deltaSize; byte *_deltaBufs[2]; byte *_deltaBuf; int16 *_offsetTable; - int32 _curtable; + int _curtable; uint16 _prevSeqNb; - int32 _tableLastPitch; - int32 _tableLastIndex; + int _tableLastPitch; + int _tableLastIndex; + int32 _frameSize; + int _width, _height; public: - bool initSize(const Point &, const Rect &); Codec37Decoder(); - void clean(); - virtual ~Codec37Decoder(); + ~Codec37Decoder(); + void init(int width, int height); + void deinit(); protected: - void maketable(int32, int32); + void maketable(int, int); void bompDecode(byte *dst, const byte *src, int len); - void proc3WithFDFE(byte *dst, const byte *src, int32, int32, int32, int32, int16 *); - void proc3WithoutFDFE(byte *dst, const byte *src, int32, int32, int32, int32, int16 *); - void proc4WithFDFE(byte *dst, const byte *src, int32, int32, int32, int32, int16 *); - void proc4WithoutFDFE(byte *dst, const byte *src, int32, int32, int32, int32, int16 *); + void proc3WithFDFE(byte *dst, const byte *src, int32, int, int, int, int16 *); + void proc3WithoutFDFE(byte *dst, const byte *src, int32, int, int, int, int16 *); + void proc4WithFDFE(byte *dst, const byte *src, int32, int, int, int, int16 *); + void proc4WithoutFDFE(byte *dst, const byte *src, int32, int, int, int, int16 *); public: - bool decode(byte *dst, const byte *src, int length); + void decode(byte *dst, const byte *src); }; #endif diff --git a/scumm/smush/codec44.cpp b/scumm/smush/codec44.cpp deleted file mode 100644 index dae835bb555..00000000000 --- a/scumm/smush/codec44.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2002-2003 The ScummVM project - * - * This program 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 2 - * of the License, or (at your option) any later version. - - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - * - */ - -#include -#include "codec44.h" - -bool Codec44Decoder::decode(byte *dst, const byte *src, int length) { - int32 size_line, num; - int32 width = getRect().width(); - int32 height = getRect().height(); - const byte *src2 = src; - byte *dst2 = _buffer; - byte val; - - do { - size_line = READ_LE_UINT16(src2); - src2 += 2; - length -= 2; - - while (size_line != 0) { - num = *src2++; - val = *src2++; - memset(dst2, val, num); - dst2 += num; - length -= 2; - size_line -= 2; - if (size_line != 0) { - num = READ_LE_UINT16(src2) + 1; - src2 += 2; - memcpy(dst2, src2, num); - dst2 += num; - src2 += num; - length -= num + 2; - size_line -= num + 2; - } - } - dst2--; - - } while (length > 1); - - memcpy(dst, _buffer, width * height); - - return true; -} diff --git a/scumm/smush/codec44.h b/scumm/smush/codec44.h deleted file mode 100644 index b4ecd7fbc17..00000000000 --- a/scumm/smush/codec44.h +++ /dev/null @@ -1,34 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2002-2003 The ScummVM project - * - * This program 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 2 - * of the License, or (at your option) any later version. - - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - * - */ - -#ifndef CODEC44_H -#define CODEC44_H - -#include "decoder.h" - -class Codec44Decoder : public Decoder { - byte _buffer[1000]; - -public: - bool decode(byte *dst, const byte *src, int length); -}; - -#endif diff --git a/scumm/smush/codec47.cpp b/scumm/smush/codec47.cpp index 30983412c34..a7a98b72891 100644 --- a/scumm/smush/codec47.cpp +++ b/scumm/smush/codec47.cpp @@ -601,16 +601,16 @@ void Codec47Decoder::level1(byte *d_dst) { } } -void Codec47Decoder::decode2(byte *dst, const byte *src, int32 width, int32 height, const byte *param_ptr) { +void Codec47Decoder::decode2(byte *dst, const byte *src, int width, int height, const byte *param_ptr) { _d_src = src; _paramPtr = param_ptr - 0xf8; - int32 bw = (width + 7) >> 3; - int32 bh = (height + 7) >> 3; - int32 next_line = width * 7; + int bw = (width + 7) >> 3; + int bh = (height + 7) >> 3; + int next_line = width * 7; _d_pitch = width; do { - int32 tmp_bw = bw; + int tmp_bw = bw; do { level1(dst); dst += 8; @@ -619,35 +619,26 @@ void Codec47Decoder::decode2(byte *dst, const byte *src, int32 width, int32 heig } while (--bh); } -bool Codec47Decoder::initSize(const Point &p, const Rect &r) { - if(r.width() != getRect().width() && r.height() != getRect().height()) { - if( - (r.width() != 640 || r.height() != 480) - ) - return false; - Decoder::initSize(p, r); - clean(); +void Codec47Decoder::init(int width, int height) { + deinit(); + _width = width; + _height = height; + makeTables37(4); + makeTables37(8); - makeTables37(4); - makeTables37(8); - - int32 frame_size = getRect().width() * getRect().height(); - _deltaSize = frame_size * 3; - _deltaBuf = new byte[_deltaSize]; - _deltaBufs[0] = _deltaBuf; - _deltaBufs[1] = _deltaBuf + frame_size; - _curBuf = _deltaBuf + frame_size * 2; - - return true; - } - return false; + _frameSize = _width * _height; + _deltaSize = _frameSize * 3; + _deltaBuf = new byte[_deltaSize]; + _deltaBufs[0] = _deltaBuf; + _deltaBufs[1] = _deltaBuf + _frameSize; + _curBuf = _deltaBuf + _frameSize * 2; } Codec47Decoder::Codec47Decoder() { _deltaBuf = 0; } -void Codec47Decoder::clean() { +void Codec47Decoder::deinit() { _lastTableWidth = -1; if(_deltaBuf) { delete []_deltaBuf; @@ -659,12 +650,10 @@ void Codec47Decoder::clean() { } Codec47Decoder::~Codec47Decoder() { - clean(); + deinit(); } -bool Codec47Decoder::decode(byte *dst, const byte *src, int length) { - int32 width = getRect().width(); - int32 height = getRect().height(); +bool Codec47Decoder::decode(byte *dst, const byte *src) { _offset1 = _deltaBufs[1] - _curBuf; _offset2 = _deltaBufs[0] - _curBuf; @@ -674,9 +663,9 @@ bool Codec47Decoder::decode(byte *dst, const byte *src, int length) { byte *tmp_ptr; if (seq_nb == 0) { - makeTables47(width); - memset(_deltaBufs[0], src[12], width * height); - memset(_deltaBufs[1], src[13], width * height); + makeTables47(_width); + memset(_deltaBufs[0], src[12], _frameSize); + memset(_deltaBufs[1], src[13], _frameSize); _prevSeqNb = -1; } @@ -686,28 +675,28 @@ bool Codec47Decoder::decode(byte *dst, const byte *src, int length) { switch(src[2]) { case 0: - memcpy(_curBuf, gfx_data, width * height); + memcpy(_curBuf, gfx_data, _frameSize); break; case 1: warning("codec47: not implemented decode1 proc"); break; case 2: if (seq_nb == _prevSeqNb + 1) { - decode2(_curBuf, gfx_data, width, height, src + 8); + decode2(_curBuf, gfx_data, _width, _height, src + 8); } break; case 3: - memcpy(_curBuf, _deltaBufs[1], width * height); + memcpy(_curBuf, _deltaBufs[1], _frameSize); break; case 4: - memcpy(_curBuf, _deltaBufs[0], width * height); + memcpy(_curBuf, _deltaBufs[0], _frameSize); break; case 5: bompDecode(_curBuf, gfx_data, READ_LE_UINT32(src + 14)); break; } - memcpy(dst, _curBuf, width * height); + memcpy(dst, _curBuf, _frameSize); if (seq_nb == _prevSeqNb + 1) { if (src[3] == 1) { diff --git a/scumm/smush/codec47.h b/scumm/smush/codec47.h index c1a395289d2..425f0daacf3 100644 --- a/scumm/smush/codec47.h +++ b/scumm/smush/codec47.h @@ -19,27 +19,28 @@ * */ -#ifndef CODEC_47_H -#define CODEC_47_H +#ifndef SMUSH_CODEC_47_H +#define SMUSH_CODEC_47_H -#include "config.h" +#include "common/scummsys.h" -#include "decoder.h" - -class Codec47Decoder : public Decoder { +class Codec47Decoder { private: + int32 _deltaSize; byte *_deltaBufs[2]; byte *_deltaBuf; byte *_curBuf; int32 _prevSeqNb; - int32 _lastTableWidth; + int _lastTableWidth; const byte *_d_src, *_paramPtr; - int32 _d_pitch; + int _d_pitch; int32 _offset1, _offset2; byte _tableBig[99328]; byte _tableSmall[32768]; int16 _table[256]; + int32 _frameSize; + int _width, _height; void makeTables47(int32 width); void makeTables37(int32 param); @@ -47,14 +48,14 @@ private: void level1(byte *d_dst); void level2(byte *d_dst); void level3(byte *d_dst); - void decode2(byte *dst, const byte *src, int32 width, int32 height, const byte *param_ptr); + void decode2(byte *dst, const byte *src, int width, int height, const byte *param_ptr); public: Codec47Decoder(); - virtual ~Codec47Decoder(); - bool initSize(const Point &, const Rect &); - void clean(); - bool decode(byte *dst, const byte *src, int length); + ~Codec47Decoder(); + void init(int width, int height); + void deinit(); + bool decode(byte *dst, const byte *src); }; #endif diff --git a/scumm/smush/color.cpp b/scumm/smush/color.cpp deleted file mode 100644 index 601f312defc..00000000000 --- a/scumm/smush/color.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2002-2003 The ScummVM project - * - * This program 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 2 - * of the License, or (at your option) any later version. - - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - * - */ - -#include -#include "color.h" - -#define UPDATE_COLOR(c, inc) (((int32)((c)) << 7) + (c) + (inc)) >> 7 -#define CHECK_BOUNDS(c) (((c) > 255) ? 255 : (((c) < 0) ? 0 : (c))) - -void Color::delta(int16 * ptr) { - // This is a very specific method for XPALs. - int16 t; - t = UPDATE_COLOR(_r, ptr[0]); - _r = CHECK_BOUNDS(t); - t = UPDATE_COLOR(_g, ptr[1]); - _g = CHECK_BOUNDS(t); - t = UPDATE_COLOR(_b, ptr[2]); - _b = CHECK_BOUNDS(t); -} diff --git a/scumm/smush/color.h b/scumm/smush/color.h deleted file mode 100644 index 78e82a461bd..00000000000 --- a/scumm/smush/color.h +++ /dev/null @@ -1,55 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2002-2003 The ScummVM project - * - * This program 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 2 - * of the License, or (at your option) any later version. - - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - * - */ - -#ifndef COLOR_H -#define COLOR_H - -#include "config.h" - -/*! @brief simple class for handling a Chunk. - - This small class is an helper for Chunks. -*/ -class Color { -public: - typedef byte value_type; //!< The type of the Chunk components. -private: - value_type _r; //!< The red component. - value_type _g; //!< The green component. - value_type _b; //!< The blue component. -public: - Color() : _r(0), _g(0), _b(0) {} - Color(value_type r, value_type g, value_type b) : _r(r), _g(g), _b(b) {} - - inline value_type red() const { return _r; } - inline value_type green() const { return _g; } - inline value_type blue() const { return _b; } - /*! @brief handle delta palette modification - - This method is used specifically by player::handleDeltaPalette(). - It updates the Chunk component using delta values given as short. - - @param ptr pointer to a table of 3 shorts that contain delta values to use. - */ - void delta(int16 * ptr); -}; - -#endif diff --git a/scumm/smush/decoder.h b/scumm/smush/decoder.h deleted file mode 100644 index ebf9645dcdb..00000000000 --- a/scumm/smush/decoder.h +++ /dev/null @@ -1,51 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2002-2003 The ScummVM project - * - * This program 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 2 - * of the License, or (at your option) any later version. - - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - * - */ - -#ifndef DECODER_H -#define DECODER_H - -#include "config.h" - -#include "common/rect.h" - -using ScummVM::Point; -using ScummVM::Rect; - -/*! @brief base class for codec decompression. - - This class provides an interface for codec decompression. - -*/ -class Decoder { -private: - Rect _r; //!< current size of the frame object to decode - Point _p; //!< position of the frame object to decode -protected: - const Rect & getRect() const{ return _r; } - const Point & getSize() const { return _p; } -public: - Decoder() {}; - virtual ~Decoder() {}; - virtual bool initSize(const Point &p, const Rect &r) { _p = p; _r = r; return true; }; - virtual bool decode(byte *dst, const byte *src, int length) = 0; -}; - -#endif diff --git a/scumm/smush/frenderer.cpp b/scumm/smush/frenderer.cpp deleted file mode 100644 index 212ad8f7c09..00000000000 --- a/scumm/smush/frenderer.cpp +++ /dev/null @@ -1,399 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2002-2003 The ScummVM project - * - * This program 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 2 - * of the License, or (at your option) any later version. - - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - * - */ - -#include -#include "common/util.h" -#include "common/engine.h" // for debug, warning, error -#include "scumm/scumm.h" - -#include "frenderer.h" - -#include -#include - -FontRenderer::FontRenderer(bool use_original_colors) : - _nbChars(0), - _color(-1), - _original(use_original_colors) { -} - -FontRenderer::~FontRenderer() { - for(int32 i = 0; i < _nbChars; i++) { - if(_chars[i].chr) delete []_chars[i].chr; - } -} - -void FontRenderer::save() { - _chars[_nbChars].width = _width; - _chars[_nbChars].height = _height; - int size = _width * _height; - _chars[_nbChars].chr = new byte[size]; - memcpy(_chars[_nbChars].chr, _data, size); - _nbChars++; -} - -int32 FontRenderer::charWidth(int32 v) const { - if(v < 0) v = 256 + v; - if(v < 0 || v >= _nbChars) error("invalid character in FontRenderer::charWidth : %d (%d)", v, _nbChars); - return _chars[v].width; -} - -int32 FontRenderer::charHeight(int32 v) const { - if(v < 0) v = 256 + v; - if(v < 0 || v >= _nbChars) error("invalid character in FontRenderer::charHeight : %d (%d)", v, _nbChars); - return _chars[v].height; -} - -int32 FontRenderer::stringWidth(const char *str) const { - int32 ret = 0; - - while(*str) { - ret += charWidth(*str++); - } - - return ret; -} - -int32 FontRenderer::stringHeight(const char *str) const { - int32 ret = 0; - - for(int32 i = 0; str[i] != 0; i++) { - int32 h = charHeight(str[i]); - ret = MAX(ret, h); - } - - return ret; -} - -int32 FontRenderer::drawChar(byte *buffer, const Point &size, int32 x, int32 y, int32 chr) const { - int32 w = _chars[chr].width; - int32 h = _chars[chr].height; - byte *src = _chars[chr].chr; - byte *dst = buffer + size.getX() * y + x; - - if(_original) { - for(int32 j = 0; j < h; j++) { - for(int32 i = 0; i < w; i++) { - char value = *src++; - if(value) dst[i] = value; - } - dst += size.getX(); - } - } else { - char color = (_color != -1) ? _color : 1; - if (g_scumm->_gameId == GID_CMI) { - for(int32 j = 0; j < h; j++) { - for(int32 i = 0; i < w; i++) { - char value = *src++; - if(value == -color) { - dst[i] = 0xFF; - } else if(value == -31) { - dst[i] = 0; - } else if(value) { - dst[i] = value; - } - } - dst += size.getX(); - } - } else { - for(int32 j = 0; j < h; j++) { - for(int32 i = 0; i < w; i++) { - char value = *src++; - if(value == 1) { - dst[i] = color; - } else if(value) { - dst[i] = 0; - } - } - dst += size.getX(); - } - } - } - return w; -} - -static char **split(const char *str, char sep) { - char **ret = new char *[62]; - int32 n = 0; - const char *i = str, *j = strchr(i, sep); - - while(j != NULL) { - assert(n < 60); - ret[n] = new char[j - i + 1]; - memcpy(ret[n], i, j - i); - ret[n++][j - i] = 0; - i = j+1; - j = strchr(i, sep); - } - - ret[n] = new char[strlen(i) + 1]; - memcpy(ret[n], i, strlen(i)); - ret[n++][strlen(i)] = 0; - ret[n] = 0; - return ret; -} - -void FontRenderer::drawSubstring(const byte *str, byte *buffer, const Point &size, int32 x, int32 y) const { - for(int32 i = 0; str[i] != 0; i++) - x += drawChar(buffer, size, x, y, str[i]); -} - -bool FontRenderer::drawStringAbsolute(const char *str, byte *buffer, const Point &size, int32 x, int32 y) const { - debug(9, "FontRenderer::drawStringAbsolute(%s, %d, %d)", str, x, y); - while(str) { - char line[256]; - char *pos = strchr(str, '\n'); - if(pos) { - memcpy(line, str, pos - str - 1); - line[pos - str - 1] = 0; - str = pos + 1; - } else { - strcpy(line, str); - str = 0; - } - drawSubstring((const byte *)line, buffer, size, x, y); - y += stringHeight(line); - } - return true; -} - -bool FontRenderer::drawStringCentered(const char *str, byte *buffer, const Point &size, int32 y, int32 xmin, int32 width, int32 offset) const { - debug(9, "FontRenderer::drawStringCentered(%s, %d, %d)", str, xmin, y); - if ((strchr(str, '\n') != 0)) { - char *j = strchr(str, '\n'); - *j = 0; - } - char **words = split(str, ' '); - int32 nb_sub = 0; - - while(words[nb_sub]) nb_sub++; - - int32 *sizes = new int32[nb_sub]; - int32 i = 0, max_width = 0, height = 0, nb_subs = 0; - - for(i = 0; i < nb_sub; i++) - sizes[i] = stringWidth(words[i]); - - char **substrings = new char *[nb_sub]; - int32 *substr_widths = new int32[nb_sub]; - int32 space_width = charWidth(' '); - - i = 0; - while(i < nb_sub) { - int32 substr_width = sizes[i]; - char *substr = new char[1000]; - strcpy(substr, words[i]); - int32 j = i + 1; - - while(j < nb_sub && (substr_width + space_width + sizes[j]) < width) { - substr_width += sizes[j++] + space_width; - } - - for(int32 k = i + 1; k < j; k++) { - strcat(substr, " "); - strcat(substr, words[k]); - } - - substrings[nb_subs] = substr; - substr_widths[nb_subs++] = substr_width; - if(substr_width > max_width) - max_width = substr_width; - i = j; - height += stringHeight(substr); - } - - delete []sizes; - for(i = 0; i < nb_sub; i++) { - delete []words[i]; - } - delete []words; - - max_width = (max_width + 1) >> 1; - // we have a box from 0 -> max_width - // we want a box from (xmin + offset) - max_width / 2, (xmin + offset) + max_width / 2 - int x = xmin + width / 2; - x += offset - size.getX() / 2; - - if(x < max_width) x = max_width; - if(x + max_width > size.getX()) { - x = size.getX() - max_width; - } - - if(y + height > size.getY()) { - y = size.getY() - height; - } - - for(i = 0; i < nb_subs; i++) { - int32 substr_width = substr_widths[i]; - drawSubstring((const byte *)substrings[i], buffer, size, x - substr_width / 2, y); - y += stringHeight(substrings[i]); - delete []substrings[i]; - } - - delete []substr_widths; - delete []substrings; - return true; -} - -bool FontRenderer::drawStringWrap(const char *str, byte *buffer, const Point &size, int32 x, int32 y, int32 width) const { - debug(9, "FontRenderer::drawStringWrap(%s, %d, %d)", str, x, y); - if ((strchr(str, '\n') != 0)) { - char *j = strchr(str, '\n'); - *j = 0; - } - char * * words = split(str, ' '); - int32 nb_sub = 0; - - while(words[nb_sub]) nb_sub++; - - int32 *sizes = new int32[nb_sub]; - int32 i = 0, max_width = 0, height = 0, nb_subs = 0, left_x; - - for(i = 0; i < nb_sub; i++) - sizes[i] = stringWidth(words[i]); - - char **substrings = new char *[nb_sub]; - int32 *substr_widths = new int32[nb_sub]; - int32 space_width = charWidth(' '); - - i = 0; - while(i < nb_sub) { - int32 substr_width = sizes[i]; - char *substr = new char[1000]; - strcpy(substr, words[i]); - int32 j = i + 1; - - while(j < nb_sub && (substr_width + space_width + sizes[j]) < width) { - substr_width += sizes[j++] + space_width; - } - - for(int32 k = i + 1; k < j; k++) { - strcat(substr, " "); - strcat(substr, words[k]); - } - - substrings[nb_subs] = substr; - substr_widths[nb_subs++] = substr_width; - i = j; - height += stringHeight(substr); - } - - delete []sizes; - for(i = 0; i < nb_sub; i++) { - delete []words[i]; - } - delete []words; - - if(y + height > size.getY()) { - y = size.getY() - height; - } - - for(i = 0; i < nb_subs; i++) - max_width = MAX(max_width, substr_widths[i]); - - if(max_width + x > size.getX()) - left_x = size.getX() - max_width + charWidth(' '); - else - left_x = x; - - if(max_width + left_x > size.getX()) - left_x = size.getX() - max_width; - - for(i = 0; i < nb_subs; i++) { - drawSubstring((const byte *)substrings[i], buffer, size, left_x, y); - y += stringHeight(substrings[i]); - delete []substrings[i]; - } - - delete []substr_widths; - delete []substrings; - return true; -} - -bool FontRenderer::drawStringWrapCentered(const char *str, byte *buffer, const Point &size, int32 x, int32 y, int32 width) const { - int32 max_substr_width = 0; - debug(9, "FontRenderer::drawStringWrapCentered(%s, %d, %d)", str, x, y); - if ((strchr(str, '\n') != 0)) { - char *j = strchr(str, '\n'); - *j = 0; - } - char **words = split(str, ' '); - int32 nb_sub = 0; - - while(words[nb_sub]) nb_sub++; - - int32 *sizes = new int32[nb_sub]; - int32 i = 0, height = 0, nb_subs = 0; - - for(i = 0; i < nb_sub; i++) - sizes[i] = stringWidth(words[i]); - - char **substrings = new char *[nb_sub]; - int32 *substr_widths = new int32[nb_sub]; - int32 space_width = charWidth(' '); - - i = 0; - width = MIN(width, size.getX()); - while(i < nb_sub) { - int32 substr_width = sizes[i]; - char *substr = new char[1000]; - strcpy(substr, words[i]); - int32 j = i + 1; - - while(j < nb_sub && (substr_width + space_width + sizes[j]) < width) { - substr_width += sizes[j++] + space_width; - } - - for(int32 k = i + 1; k < j; k++) { - strcat(substr, " "); - strcat(substr, words[k]); - } - - substrings[nb_subs] = substr; - substr_widths[nb_subs++] = substr_width; - max_substr_width = MAX(substr_width, max_substr_width); - i = j; - height += stringHeight(substr); - } - - delete []sizes; - for(i = 0; i < nb_sub; i++) { - delete []words[i]; - } - delete []words; - - if(y + height > size.getY()) { - y = size.getY() - height; - } - - x = (size.getX() - max_substr_width) / 2; - - for(i = 0; i < nb_subs; i++) { - int32 substr_width = substr_widths[i]; - drawSubstring((const byte *)substrings[i], buffer, size, x + (max_substr_width - substr_width) / 2, y); - y += stringHeight(substrings[i]); - delete []substrings[i]; - } - - delete []substr_widths; - delete []substrings; - return true; -} diff --git a/scumm/smush/frenderer.h b/scumm/smush/frenderer.h deleted file mode 100644 index 93f3b954001..00000000000 --- a/scumm/smush/frenderer.h +++ /dev/null @@ -1,165 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2002-2003 The ScummVM project - * - * This program 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 2 - * of the License, or (at your option) any later version. - - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - * - */ - -#ifndef FRENDERER_H -#define FRENDERER_H - -#include "config.h" - -#ifdef DEBUG -# ifndef NO_DEBUG_FONT_RENDERER -# define DEBUG_FONT_RENDERER -# endif -#else -# ifdef DEBUG_FONT_RENDERER -# error DEBUG_FONT_RENDERER defined without DEBUG -# endif -#endif - -#include "brenderer.h" -#include "common/util.h" - -/*! @brief ::renderer implementation specifically designed for font files. - - This class is a valid ::renderer implementation. The frames are kept in memory, as bitmap representing characters, so that - they can be rendered again in another frame as strings. - - This class also contains some functions useful for printing strings. This is used to show subtitles and more generally texts - in animations. - - @todo update the mehod to use the ::blitter class, instead of direct pointers. -*/ -class FontRenderer : public BaseRenderer { -private: - int32 _nbChars; //!< The number of frames in the font - int32 _color; //!< A color parameter used for font printing. - bool _original; //!< flag for color selection - struct { - int32 width; - int32 height; - byte *chr; - } _chars[256]; //!< array that contains the size of the different frames (i.e. characters) of the font. -public: - /*! @brief font_renderer constructor - - @param use_original_colors flag to indicate if the font use it's own color, or if the base color are set at runtime. - */ - FontRenderer(bool use_original_colors = false); - virtual ~FontRenderer(); - virtual bool wait(int32 ms) { return true; }; -protected: - virtual void save(); - /*! @brief get the width of a character. - - @param c the character we want the width from. - - @return the width of the character - */ - int32 charWidth(int32 c) const; - /*! @brief get the width of a string. - - @param str the string we want the width from. - - @return the complete width of the string - */ - int32 stringWidth(const char *str) const; - /*! @brief get the height of a character. - - @param c the character we want the height from. - - @return the height of the character - */ - int32 charHeight(int32 c) const; - /*! @brief get the height of a string. - - @param str the string we want the height from. - - @return the complete height of the string - */ - int32 stringHeight(const char *str) const; - /*! @brief draw a character in the given frame buffer. - - @param buffer the frame buffer to draw into. - @param size the size of the frame buffer. - @param x the horizontal position of the topleft corner of the character. - @param y the vertical position of the topleft corner of the character. - @param c the character to draw. - - @bug This method does not clip. This is not really a bug, as it should always be correctly called, but some asserts would be welcome. - - @return the width of the character - */ - int32 drawChar(byte *buffer, const Point &size, int32 x, int32 y, int32 c) const; - /*! @brief draw a string in the given frame buffer. - - @param str the string to draw. - @param buffer the frame buffer to draw into. - @param size the size of the frame buffer. - @param x the horizontal position of the topleft corner of the string. - @param y the vertical position of the topleft corner of the string. - - @bug This method does not clip. This is not really a bug, as it should always be correctly called, but some asserts would be welcome. - */ - void drawSubstring(const byte *str, byte *buffer, const Point &size, int32 x, int32 y) const; -public: - /*! @brief change the programmable color of the font. - - @param c the new color to use. - - @return \c true if everything went fine, \c false otherwise - */ - bool setColor(int32 c) { _color = c; return true; } - /*! @brief draw a centered and possibly using multiple lines string. - - This method performs calculation of the string size before choosing where to draw it. - As I still not have figured out exactly what is the meaning of the fields in the TRES Chunk, - the real meaning of the parameters can be quite difficult to understand. - - @remark The current implementation is incorrect in the sense that it does not conform to the original game. - @todo rewrite and rethink this to better match the original implementation. - - @param str the string to draw. - @param buffer the frame buffer to draw into. - @param size the size of the frame buffer. - @param y the vertical position of the topleft corner of the string. This position may be changed if it is too low to be correctly drawn. - @param xmin the minimum horizontal position of the topleft corner of the string. - @param width the maximum width of the string. If the string is too long, it will wrap. - @param offset offset to give to the horizontal position. - - @return \c true if everything went fine, \c false otherwise - */ - bool drawStringCentered(const char *str, byte *buffer, const Point &size, int32 y, int32 xmin, int32 width, int32 offset) const; - bool drawStringWrap(const char *str, byte *buffer, const Point &size, int32 x, int32 y, int32 width) const; - bool drawStringWrapCentered(const char *str, byte *buffer, const Point &size, int32 x, int32 y, int32 width) const; - /*! @brief draw a string at an absolute position. - - @param str the string to draw. - @param buffer the frame buffer to draw into. - @param size the size of the frame buffer. - @param x the horizontal position of the topleft corner of the string. - @param y the vertical position of the topleft corner of the string. This position may be changed if it is too low to be correctly drawn. - - @return \c true if everything went fine, \c false otherwise - */ - bool drawStringAbsolute(const char *str, byte *buffer, const Point &size, int32 x, int32 y) const; -}; - -#endif diff --git a/scumm/smush/imuse_channel.cpp b/scumm/smush/imuse_channel.cpp index f857bf19c30..064b662a33e 100644 --- a/scumm/smush/imuse_channel.cpp +++ b/scumm/smush/imuse_channel.cpp @@ -24,9 +24,6 @@ #include "chunk.h" #include "chunk_type.h" -#include -#include - ImuseChannel::ImuseChannel(int32 track, int32 freq) : _track(track), _tbuffer(0), @@ -73,7 +70,7 @@ bool ImuseChannel::checkParameters(int32 index, int32 nbframes, int32 size, int3 } bool ImuseChannel::appendData(Chunk &b, int32 size) { - if(_dataSize == -1) { // First call + if(_dataSize == -1) { assert(size > 8); Chunk::type imus_type = b.getDword(); imus_type = SWAP_BYTES(imus_type); uint32 imus_size = b.getDword(); imus_size = SWAP_BYTES(imus_size); @@ -86,9 +83,9 @@ bool ImuseChannel::appendData(Chunk &b, int32 size) { if(!_tbuffer) error("imuse_channel failed to allocate memory"); b.read(_tbuffer, size); - _dataSize = -2; // even if _in_data does not get set, this won't be called again + _dataSize = -2; } else { - if(_tbuffer) { // remaining from last call + if(_tbuffer) { byte *old = _tbuffer; int32 new_size = size + _tbufferSize; _tbuffer = new byte[new_size]; @@ -223,7 +220,7 @@ bool ImuseChannel::handleSubTags(int32 &offset) { handleMap(c); } break; - case TYPE_DATA: // Sound data !!! + case TYPE_DATA: _inData = true; _dataSize = size; offset += 8; @@ -254,7 +251,6 @@ bool ImuseChannel::handleSubTags(int32 &offset) { } bool ImuseChannel::processBuffer() { - // see comments in saud_channel::processBuffer for an explanation assert(_tbuffer != 0); assert(_tbufferSize != 0); assert(_sbuffer == 0); @@ -266,7 +262,7 @@ bool ImuseChannel::processBuffer() { while(handleSubTags(offset)); _sbufferSize = _dataSize; _sbuffer = _tbuffer; - if(offset < _tbufferSize) { // there is still some unprocessed data + if(offset < _tbufferSize) { int32 new_size = _tbufferSize - offset; _tbuffer = new byte[new_size]; if(!_tbuffer) error("imuse_channel failed to allocate memory"); @@ -277,12 +273,10 @@ bool ImuseChannel::processBuffer() { _tbufferSize = 0; } if(_sbufferSize == 0) { - // this never happened yet, but who knows delete []_sbuffer; _sbuffer = 0; } } else { - // easy, swap the buffer _sbufferSize = _tbufferSize; _sbuffer = _tbuffer; _tbufferSize = 0; @@ -301,7 +295,7 @@ bool ImuseChannel::processBuffer() { _tbuffer = 0; _tbufferSize = 0; } else { - if(offset) { // maybe I should assert() this to avoid a lock... + if(offset) { byte * old = _tbuffer; int32 new_size = _tbufferSize - offset; _tbuffer = new byte[new_size]; diff --git a/scumm/smush/mixer.h b/scumm/smush/mixer.h deleted file mode 100644 index 2375c523c06..00000000000 --- a/scumm/smush/mixer.h +++ /dev/null @@ -1,58 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2002-2003 The ScummVM project - * - * This program 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 2 - * of the License, or (at your option) any later version. - - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - * - */ - -#ifndef SMUSH_MIXER_H -#define SMUSH_MIXER_H - -#include "config.h" - -#ifdef DEBUG -# ifndef NO_DEBUG_MIXER -# define DEBUG_MIXER -# endif -#else -# ifdef DEBUG_MIXER -# error DEBUG_MIXER defined without DEBUG -# endif -#endif - -class _Channel; - -class SoundRenderer; - -/*! @brief The class for the player's sound mixer - - This class is used for sound mixing. - It contains a list of current track and request them to mix. - It then sends the mixed sound samples to the sound renderer. - -*/ -class Mixer { -public: - virtual ~Mixer() {}; - virtual bool init() = 0; - virtual _Channel * findChannel(int32 track) = 0; - virtual bool addChannel(_Channel * c) = 0; - virtual bool handleFrame() = 0; - virtual bool stop() = 0; -}; - -#endif diff --git a/scumm/smush/palette.h b/scumm/smush/palette.h deleted file mode 100644 index ea9df037c0f..00000000000 --- a/scumm/smush/palette.h +++ /dev/null @@ -1,57 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2002-2003 The ScummVM project - * - * This program 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 2 - * of the License, or (at your option) any later version. - - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - * - */ - -#ifndef SMUSH_PALETTE_H -#define SMUSH_PALETTE_H - -#include "config.h" - -#include "color.h" - -/*! @brief simple class for handling a palette. - - This small class is an helper for palettes. -*/ -class Palette { -private: - Color _colors[256]; -public: - Palette() {} - Palette(byte *ptr) - { - for(int32 i = 0; i < 256; i++) { - _colors[i] = Color(ptr[3 * i + 0], ptr[3 * i + 1], ptr[3 * i + 2]); - } - - } - const Color & operator[](int32 a) const - { - assert(a >= 0 && a < 256); - return _colors[a]; - } - Color & operator[](int32 a) - { - assert(a >= 0 && a < 256); - return _colors[a]; - } -}; - -#endif diff --git a/scumm/smush/player.h b/scumm/smush/player.h deleted file mode 100644 index 60311b88f72..00000000000 --- a/scumm/smush/player.h +++ /dev/null @@ -1,109 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2002-2003 The ScummVM project - * - * This program 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 2 - * of the License, or (at your option) any later version. - - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - * - */ - -#ifndef PLAYER_H -#define PLAYER_H - -#include "config.h" - -#include "common/util.h" -#include "chunk.h" -#include "palette.h" -#include "codec1.h" -#include "codec37.h" -#include "codec44.h" -#include "codec47.h" - -class FontRenderer; -class Mixer; -class Renderer; -class StringResource; - -/*! @brief the SMUSH player class - - This class is the player itself. -*/ -class SmushPlayer { -private: - char *_fname; //!< the name of the animation file being played - int32 _version; //!< the version of the animation file being played - int32 _secondaryVersion; //!< the secondary version number of the animation file being played - int32 _soundFrequency; //!< the sound frequency of the animation file being played - int32 _nbframes; //!< the number of frames in the animation file - Mixer *_mixer; //!< the sound mixer - Palette _pal; //!< the current palette - int16 _deltaPal[768]; //!< the delta palette information set by an xpal - Renderer *_renderer; //!< pointer to the ::renderer - StringResource *_strings; //!< pointer to the string resources associated with the animation - FontRenderer *_fr[5]; //!< pointers to the fonts for the animation - Codec1Decoder _codec1; //!< the ::decoder for codec 1 and 3 - Codec37Decoder _codec37; //!< the ::decoder for codec 37 - Codec47Decoder _codec47; //!< the ::decoder for codec 47 - Codec44Decoder _codec44; //!< the ::decoder for codec 21 and 44 - Point _frameSize; //!< the current frame size of the animation - int32 _frame; //!< the current frame number of the animation - bool _outputSound; //!< should we handle sound ? - bool _wait; //!< should we synchronise the player ? - bool _alreadyInit; //!< has the player already been initialized for the current frame - bool _codec37Called; //!< has the codec 37 already been called once for this animation - bool _skipNext; //!< should the player skip the next frame object ? - bool _subtitles; //!< should the player handle subtitles ? - bool _bgmusic; //!< should the player output the background music ? - bool _voices; //!< should the player output the voice ? - bool _skips[37]; //!< mapping of frame object identifier to show or hide - byte *_curBuffer; //!< pointer to the current frame - int32 _IACTchannel; - byte _IACToutput[4096]; - int32 _IACTpos; - bool _storeFrame; - byte *_frameBuffer; - -public: - SmushPlayer(Renderer *, bool wait = true, bool output_sound = true); - virtual ~SmushPlayer(); - bool play(const char *, const char *directory); - void updatePalette(void); - void show(const char *); - void hide(const char *); -protected: - bool readString(const char *file, const char *directory, bool &); - void clean(); - void checkBlock(const Chunk &, Chunk::type, uint32 = 0); - void handleAnimHeader(Chunk &); - void handleFrame(Chunk &); - void handleNewPalette(Chunk &); - void handleFrameObject(Chunk &); - void handleSoundBuffer(int32, int32, int32, int32, int32, int32, Chunk &, int32); - void handleImuseBuffer(int32, int32, int32, int32, int32, int32, Chunk &, int32); - void handleSoundFrame(Chunk &); - void handleSkip(Chunk &); - void handleStore(Chunk &); - void handleFetch(Chunk &); - void handleImuseAction8(Chunk &, int32 flags, int32 unknown, int32 track_id); - void handleImuseAction(Chunk &); - void handleTextResource(Chunk &); - void handleDeltaPalette(Chunk &); - void decodeCodec(Chunk &, const Rect &, Decoder &); - void readPalette(Palette &, Chunk &); - void initSize(const Rect &, bool, bool); -}; - -#endif diff --git a/scumm/smush/renderer.h b/scumm/smush/renderer.h deleted file mode 100644 index 724b0eb6d11..00000000000 --- a/scumm/smush/renderer.h +++ /dev/null @@ -1,125 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2002-2003 The ScummVM project - * - * This program 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 2 - * of the License, or (at your option) any later version. - - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - * - */ - -#ifndef RENDERER_H -#define RENDERER_H - -#include "config.h" - -#include "palette.h" -#include "common/rect.h" - -using ScummVM::Point; -using ScummVM::Rect; -class Mixer; - -/*! @brief interface for general output (rendering) - - This is the interface for frame output. - Several implementations of these interface exist, each having a particular - application. -*/ -class Renderer { -public: - virtual ~Renderer() {}; - /*! @brief start of animation output - - This is called by the animation player when output is going to start. - - @param fname name of the animation being played. - @param version version number of the animation - @param nbframes total number of frames of the animation. - - @return true if initialisation was ok, false otherwise - */ - virtual bool startDecode(const char *fname, int32 version, int32 nbframes) = 0; - /*! @brief start of animation output - - This is called by the animation player when the frame size is changing. - - @param size new size of the frames. - - @return true if everything went fine, false otherwise - */ - virtual bool initFrame(const Point & size) = 0; - /*! @brief set a new palette - - This is called by the animation player when the palette is changing. - - @param pal new palette. - - @return true if everything went fine, false otherwise - */ - virtual bool setPalette(const Palette & pal) = 0; - /*! @brief lock a frame buffer - - This is called by the animation player when a frame is going to be decoded. - - @param frame the frame number. - - @return a pointer to the frame buffer to output data to. - */ - virtual byte *lockFrame(int32 frame) = 0; - /*! @brief unlock a frame buffer - - This is called by the animation player when a frame has been decoded. - - @return true if everything went fine, false otherwise - */ - virtual bool unlockFrame() = 0; - /*! @brief flip a frame buffer - - This is called by the animation player when the current frame should be shown. - - @return true if everything went fine, false otherwise - */ - virtual bool flipFrame() = 0; - /*! @brief wait for some time - - This is called by the animation player when the animation should stay idle. - - @param ms number of millisecond to wait. - - @return true if everything went fine, false otherwise - */ - virtual bool wait(int32 ms) = 0; - /*! @brief does the renderer want a premature end of the animation ? - - This is called by the animation player after each frame. - - @return true if playing should be stopped, false otherwise. - */ - virtual bool prematureClose() = 0; - /*! @brief request for a mixer - - This is called by the animation player when sound output is required by the animation. - - @return a valid pointer to an uninitialized mixer instance, or null if none is available. - */ - virtual Mixer *getMixer() = 0; - /*! @brief debugging function : do not use - - @return true if everything went fine, false otherwise - */ - virtual bool saveCurrent() { return false; }; -}; - -#endif diff --git a/scumm/smush/saud_channel.cpp b/scumm/smush/saud_channel.cpp index d49c63bc44d..3ab0f03faa8 100644 --- a/scumm/smush/saud_channel.cpp +++ b/scumm/smush/saud_channel.cpp @@ -25,9 +25,6 @@ #include "chunk.h" #include "chunk_type.h" -#include -#include - void SaudChannel::handleStrk(Chunk &b) { int32 size = b.getSize(); if(size != 14 && size != 10) { @@ -41,7 +38,8 @@ void SaudChannel::handleSmrk(Chunk &b) { void SaudChannel::handleShdr(Chunk &b) { int32 size = b.getSize(); - if(size != 4) warning("SMRK has a invalid size : %d", size); + if(size != 4) + warning("SMRK has a invalid size : %d", size); } bool SaudChannel::handleSubTags(int32 &offset) { @@ -93,12 +91,6 @@ bool SaudChannel::handleSubTags(int32 &offset) { } bool SaudChannel::processBuffer() { - // At the start of this function, we have _tbuffer[0.._tbuffersize] containing possible data... - // and _sbuffer is 0 - // At the end we have : - // if(sound data) _sbuffer[0.._sbuffer_size] contains the sound data - // the unprocessed data is kept in _tbuffer[0.._tbuffersize] (which may have changed) - // if no unprocessed data, then _tbuffer is 0 assert(_tbuffer != 0); assert(_tbufferSize != 0); assert(_sbuffer == 0); @@ -106,12 +98,11 @@ bool SaudChannel::processBuffer() { if(_inData) { if(_dataSize < _tbufferSize) { - // I can't assume that the channel is finished after data is received... (this assumption failed in realride.san) int32 offset = _dataSize; while(handleSubTags(offset)); _sbufferSize = _dataSize; _sbuffer = _tbuffer; - if(offset < _tbufferSize) { // there is still some unprocessed data + if(offset < _tbufferSize) { int new_size = _tbufferSize - offset; _tbuffer = new byte[new_size]; if(!_tbuffer) error("SaudChannel failed to allocate memory"); @@ -122,12 +113,10 @@ bool SaudChannel::processBuffer() { _tbufferSize = 0; } if(_sbufferSize == 0) { - // this never happened yet, but who knows delete []_sbuffer; _sbuffer = 0; } } else { - // easy, swap the buffer _sbufferSize = _tbufferSize; _sbuffer = _tbuffer; _tbufferSize = 0; @@ -140,17 +129,19 @@ bool SaudChannel::processBuffer() { _sbufferSize = _tbufferSize - offset; assert(_sbufferSize); _sbuffer = new byte[_sbufferSize]; - if(!_sbuffer) error("saud_channel failed to allocate memory"); + if(!_sbuffer) + error("saud_channel failed to allocate memory"); memcpy(_sbuffer, _tbuffer + offset, _sbufferSize); delete []_tbuffer; _tbuffer = 0; _tbufferSize = 0; } else { - if(offset) { // maybe I should assert() this to avoid a lock... - unsigned char *old = _tbuffer; + if(offset) { + byte *old = _tbuffer; int32 new_size = _tbufferSize - offset; _tbuffer = new byte[new_size]; - if(!_tbuffer) error("SaudChannel failed to allocate memory"); + if(!_tbuffer) + error("SaudChannel failed to allocate memory"); memcpy(_tbuffer, old + offset, new_size); _tbufferSize = new_size; delete []old; @@ -197,10 +188,14 @@ void SaudChannel::recalcVolumeTable() { int32 right_multiplier = MAX_BALANCE + _balance; volume_left = _volume * left_multiplier / (MAX_BALANCE * 2); volume_right = _volume * right_multiplier / (MAX_BALANCE * 2); - if(volume_left < 0) volume_left = 0; - if(volume_left > 128) volume_left = 128; - if(volume_right < 0) volume_right = 0; - if(volume_right > 128) volume_right = 128; + if(volume_left < 0) + volume_left = 0; + if(volume_left > 128) + volume_left = 128; + if(volume_right < 0) + volume_right = 0; + if(volume_right > 128) + volume_right = 128; for(int32 i = 0; i < 256; i++) { int16 value = volume_left * (int8)i; _voltable[0][i] = TO_BE_16(value); @@ -220,9 +215,12 @@ bool SaudChannel::setParameters(int32 nb, int32 flags, int32 volume, int32 balan } bool SaudChannel::checkParameters(int32 index, int32 nb, int32 flags, int32 volume, int32 balance) { - if(++_index != index) error("invalid index in SaudChannel::checkParameters()"); - if(_nbframes != nb) error("invalid duration in SaudChannel::checkParameters()"); - if(_flags != flags) error("invalid flags in SaudChannel::checkParameters()"); + if(++_index != index) + error("invalid index in SaudChannel::checkParameters()"); + if(_nbframes != nb) + error("invalid duration in SaudChannel::checkParameters()"); + if(_flags != flags) + error("invalid flags in SaudChannel::checkParameters()"); if(_volume != volume || _balance != balance) { _volume = volume; _balance = balance; @@ -232,13 +230,13 @@ bool SaudChannel::checkParameters(int32 index, int32 nb, int32 flags, int32 volu } bool SaudChannel::appendData(Chunk &b, int32 size) { - if(_dataSize == -1) { // First call + if(_dataSize == -1) { assert(size > 8); Chunk::type saud_type = b.getDword(); saud_type = SWAP_BYTES(saud_type); uint32 saud_size = b.getDword(); saud_size = SWAP_BYTES(saud_size); if(saud_type != TYPE_SAUD) error("Invalid Chunk for SaudChannel : %X", saud_type); size -= 8; - _dataSize = -2; // We don't get here again... + _dataSize = -2; } if(_tbuffer) { byte *old = _tbuffer; diff --git a/scumm/smush/scumm_renderer.cpp b/scumm/smush/scumm_renderer.cpp deleted file mode 100644 index 88fc9558831..00000000000 --- a/scumm/smush/scumm_renderer.cpp +++ /dev/null @@ -1,320 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2002-2003 The ScummVM project - * - * This program 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 2 - * of the License, or (at your option) any later version. - - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - * - */ - -#include -#include "common/util.h" -#include "scumm_renderer.h" -#include "channel.h" -#include "mixer.h" -#include "sound/mixer.h" -#include "scumm/scumm.h" -#include "scumm/sound.h" -#include "scumm/imuse.h" - -class ScummMixer : public Mixer { -private: - SoundMixer *_mixer; //!< pointer to the SoundMixer instance - struct { - int id; - _Channel *chan; - bool first; - int mixer_index; - } _channels[SoundMixer::NUM_CHANNELS]; //!< The map of track and channels - int _nextIndex; -public: - ScummMixer(SoundMixer *); - virtual ~ScummMixer(); - bool init(); - _Channel *findChannel(int32 track); - bool addChannel(_Channel *c); - bool handleFrame(); - bool stop(); - bool update(); - bool _silentMixer; -}; - -ScummMixer::ScummMixer(SoundMixer *m) : _mixer(m), _nextIndex(_mixer->_beginSlots) { - for(int32 i = _mixer->_beginSlots; i < SoundMixer::NUM_CHANNELS; i++) { - _channels[i].id = -1; - _channels[i].chan = 0; - _channels[i].first = true; - } -} - -ScummMixer::~ScummMixer() { -} - -bool ScummMixer::init() { - debug(9, "ScummMixer::init()"); - return true; -} - -_Channel *ScummMixer::findChannel(int32 track) { - debug(9, "scumm_mixer::findChannel(%d)", track); - for(int32 i = _mixer->_beginSlots; i < SoundMixer::NUM_CHANNELS; i++) { - if(_channels[i].id == track) - return _channels[i].chan; - } - return 0; -} - -bool ScummMixer::addChannel(_Channel *c) { - int32 track = c->getTrackIdentifier(); - int i; - - debug(9, "ScummMixer::addChannel(%d)", track); - - for(i = _mixer->_beginSlots; i < SoundMixer::NUM_CHANNELS; i++) { - if(_channels[i].id == track) - warning("mixer::addChannel(%d) : channel already exist !", track); - } - if(_nextIndex >= SoundMixer::NUM_CHANNELS) _nextIndex = _mixer->_beginSlots; - - for(i = _nextIndex; i < SoundMixer::NUM_CHANNELS; i++) { - if(_channels[i].chan == 0 || _channels[i].id == -1) { - _channels[i].chan = c; - _channels[i].id = track; - _channels[i].first = true; - _nextIndex = i + 1; - return true; - } - } - - for(i = _mixer->_beginSlots; i < _nextIndex; i++) { - if(_channels[i].chan == 0 || _channels[i].id == -1) { - _channels[i].chan = c; - _channels[i].id = track; - _channels[i].first = true; - _nextIndex = i + 1; - return true; - } - } - - fprintf(stderr, "_nextIndex == %d\n", _nextIndex); - - for(i = _mixer->_beginSlots; i < SoundMixer::NUM_CHANNELS; i++) { - fprintf(stderr, "channel %d : %p(%d, %d) %d %d\n", i, (void *)_channels[i].chan, - _channels[i].chan ? _channels[i].chan->getTrackIdentifier() : -1, - _channels[i].chan ? _channels[i].chan->isTerminated() : 1, - _channels[i].first, _channels[i].mixer_index); - } - - error("mixer::add_channel() : no more channel available"); - return false; -} - -bool ScummMixer::handleFrame() { - debug(9, "ScummMixer::handleFrame()"); - for(int i = _mixer->_beginSlots; i < SoundMixer::NUM_CHANNELS; i++) { - if(_channels[i].id != -1) { - debug(9, "updating channel %d (%p)", _channels[i].id, _channels[i].chan); - if(_channels[i].chan->isTerminated()) { - debug(9, "channel %d has terminated (%p)", _channels[i].id, _channels[i].chan); - delete _channels[i].chan; - _channels[i].id = -1; - _channels[i].chan = 0; - } else { - int32 rate; - bool stereo, is_short; - - _channels[i].chan->getParameters(rate, stereo, is_short); - int32 size = _channels[i].chan->availableSoundData(); - debug(9, "channel %d : %d, %s, %d bits, %d", _channels[i].id, rate, stereo ? "stereo" : "mono", is_short ? 16 : 8, size); - int32 flags = stereo ? SoundMixer::FLAG_STEREO : 0; - - if(is_short) { - // FIXME this is one more data copy... we could get rid of it... - short *data = new int16[size * (stereo ? 2 : 1) * 2]; - _channels[i].chan->getSoundData(data, size); - if(_channels[i].chan->getRate() == 11025) size *= 2; - size *= stereo ? 4 : 2; - - if(_silentMixer == false) { - // append to _sound - if(_channels[i].first) { - _channels[i].mixer_index = _mixer->playStream(NULL, -1, data, size, rate, flags | SoundMixer::FLAG_16BITS); - debug(5, "channel %d bound to mixer_index %d", _channels[i].id, _channels[i].mixer_index); - _channels[i].first = false; - } else { - _mixer->append(_channels[i].mixer_index, data, size, rate, flags | SoundMixer::FLAG_16BITS); - } - } - - delete []data; - } else { - int8 *data = new int8[size * (stereo ? 2 : 1) * 2]; - _channels[i].chan->getSoundData(data, size); - if(_channels[i].chan->getRate() == 11025) size *= 2; - size *= stereo ? 2 : 1; - - if(_silentMixer == false) { - // append to _sound - if(_channels[i].first) { - _channels[i].mixer_index = _mixer->playStream(NULL, -1, data, size, rate, flags | SoundMixer::FLAG_UNSIGNED); - _channels[i].first = false; - } else { - _mixer->append(_channels[i].mixer_index, data, size, rate, flags | SoundMixer::FLAG_UNSIGNED); - } - } - - delete []data; - } - } - } - } - return true; -} - -bool ScummMixer::stop() { - debug(9, "ScummMixer::stop()"); - for(int i = _mixer->_beginSlots; i < SoundMixer::NUM_CHANNELS; i++) { - if(_channels[i].id != -1) { - delete _channels[i].chan; - _channels[i].id = -1; - _channels[i].chan = 0; - } - } - return true; -} - -ScummRenderer::ScummRenderer(Scumm *scumm, uint32 speed) : - _scumm(scumm), - _smixer(0), - _insaneSpeed(speed), - _pending_updates(0) { -} - -static ScummRenderer *s_renderer; - -static void smush_handler(void *engine) { - s_renderer->update(); -} - -bool ScummRenderer::initFrame(const Point &p) { - clean(); - _width = p.getX(); - _height = p.getY(); - assert(_width && _height); - _data = _scumm->virtscr[0].screenPtr + _scumm->virtscr[0].xstart; - return true; -} - -void ScummRenderer::clean() { - _data = 0; - _width = _height = 0; -} - -byte *ScummRenderer::lockFrame(int32 frame) { - _frame = frame; - if(!_data) error("no allocated image buffer in lock_frame"); - return _data; -} - -Mixer *ScummRenderer::getMixer() { - if(_smixer == 0) { - _smixer = new ScummMixer(_scumm->_mixer); - if(!_smixer) error("unable to allocate a smush mixer"); - _smixer->_silentMixer = _scumm->_silentDigitalImuse; - s_renderer = this; - _scumm->_timer->installProcedure(&smush_handler, _insaneSpeed); - } - return _smixer; -} - -ScummRenderer::~ScummRenderer() { - clean(); - _scumm->_insaneState = false; - _scumm->exitCutscene(); - if(_smixer) { - _scumm->_timer->releaseProcedure(&smush_handler); - delete _smixer; - _smixer = 0; - } - if (_scumm->_imuseDigital) { - _scumm->_imuseDigital->pause(false); - } - _scumm->_sound->pauseBundleMusic(false); - - _scumm->_fullRedraw = 1; -} - -bool ScummRenderer::wait(int32 ms) { - // Because waitForTimer() also is the function that checks for user - // input we always want to call it at least once between frames, or - // the user may become unable to interrupt the movie. - do { - _scumm->waitForTimer(1); - } while(_pending_updates <= 0); - return true; -} - -bool ScummRenderer::startDecode(const char *fname, int32 version, int32 nbframes) { - if (_scumm->_imuseDigital) { - _scumm->_imuseDigital->pause(true); - } - _scumm->_sound->pauseBundleMusic(true); - _scumm->_videoFinished = false; - _scumm->_insaneState = true; - return true; -} - -bool ScummRenderer::setPalette(const Palette &pal) { - int i; - byte palette_colors[1024]; - byte *p = palette_colors; - - for (i = 0; i < 256; i++, p += 4) { - p[0] = pal[i].red(); - p[1] = pal[i].green(); - p[2] = pal[i].blue(); - p[3] = 0; - } - - _scumm->_system->set_palette(palette_colors, 0, 256); - _scumm->setDirtyColors(0, 255); - return BaseRenderer::setPalette(pal); // For compatibility with possible subclass... -} - -void ScummRenderer::save() { - int width = MIN(_width, _scumm->_realWidth); - int height = MIN(_height, _scumm->_realHeight); - - // In theory, this will always be true. In reality, there may be - // several pending updates because the computer wasn't fast enough to - // process them all. In that case, skip the frame to catch up. - if (--_pending_updates <= 0) { - _scumm->_system->copy_rect(_data, _width, 0, 0, width, height); - _scumm->_system->update_screen(); - } else { - warning("ScummRenderer: Skipping frame %d to catch up", getFrame()); - } - _scumm->processKbd(); -} - -bool ScummRenderer::prematureClose() { - return _scumm->_videoFinished || _scumm->_saveLoadFlag; -} - -bool ScummRenderer::update() { - _pending_updates++; - return true; -} - diff --git a/scumm/smush/scumm_renderer.h b/scumm/smush/scumm_renderer.h deleted file mode 100644 index 1432cd8af87..00000000000 --- a/scumm/smush/scumm_renderer.h +++ /dev/null @@ -1,65 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2002-2003 The ScummVM project - * - * This program 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 2 - * of the License, or (at your option) any later version. - - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * $Header$ - * - */ - -#ifndef SCUMM_RENDERER_H -#define SCUMM_RENDERER_H - -#include "config.h" - -#ifdef DEBUG -# ifndef NO_DEBUG_SCUMM_RENDERER -# define DEBUG_SCUMM_RENDERER -# endif -#else -# ifdef DEBUG_SCUMM_RENDERER -# error DEBUG_SCUMM_RENDERER defined without DEBUG -# endif -#endif - -#include "brenderer.h" - -class ScummMixer; -class Scumm; -class Mixer; - -class ScummRenderer : public BaseRenderer { -private: - Scumm *_scumm; - ScummMixer *_smixer; - uint32 _insaneSpeed; - volatile int _pending_updates; -public: - ScummRenderer(Scumm *scumm, uint32 speed); - virtual ~ScummRenderer(); - virtual bool wait(int32 ms); - bool update(); -protected: - virtual bool initFrame(const Point &size); - virtual byte *lockFrame(int32 frame); - virtual void clean(); - virtual bool startDecode(const char *fname, int32 version, int32 nbframes); - virtual bool setPalette(const Palette & pal); - virtual void save(); - virtual Mixer *getMixer(); - virtual bool prematureClose(); -}; - -#endif diff --git a/scumm/smush/smush_font.cpp b/scumm/smush/smush_font.cpp new file mode 100644 index 00000000000..2e1207be38f --- /dev/null +++ b/scumm/smush/smush_font.cpp @@ -0,0 +1,489 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2002-2003 The ScummVM project + * + * This program 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 2 + * of the License, or (at your option) any later version. + + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +#include +#include "common/util.h" +#include "common/engine.h" +#include "common/file.h" +#include "scumm/scumm.h" + +#include "smush_font.h" + +SmushFont::SmushFont(bool use_original_colors, bool new_colors) : + _nbChars(0), + _color(-1), + _new_colors(new_colors), + _original(use_original_colors) { + for(int i = 0; i < 256; i++) + _chars[i].chr = NULL; +} + +SmushFont::~SmushFont() { + for(int i = 0; i < _nbChars; i++) { + if(_chars[i].chr) + delete []_chars[i].chr; + } +} + +bool SmushFont::loadFont(const char *filename, const char *directory) { + debug(2, "SmushFont::loadFont() called"); + + File file; + file.open(filename, directory); + if (file.isOpen() == false) { + warning("SmushFont::loadFont() Can't open font file: %s/%s", directory, filename); + return false; + } + + uint32 tag = file.readUint32BE(); + if (tag != 'ANIM') { + debug(2, "SmushFont::loadFont() there is no ANIM chunk in font header"); + return false; + } + + if (_dataSrc != NULL) { + free(_dataSrc); + _dataSrc = NULL; + } + + uint32 length = file.readUint32BE(); + _dataSrc = (byte *)malloc(length); + file.read(_dataSrc, length); + file.close(); + + if (READ_BE_UINT32(_dataSrc) != 'AHDR') { + debug(2, "SmushFont::loadFont() there is no AHDR chunk in font header"); + free(_dataSrc); + _dataSrc = NULL; + return false; + } + + _nbChars = READ_LE_UINT16(_dataSrc + 10); + int32 offset = READ_BE_UINT32(_dataSrc + 4) + 8; + for (int l = 0; l < _nbChars; l++) { + if (READ_BE_UINT32(_dataSrc + offset) == 'FRME') { + offset += 8; + if (READ_BE_UINT32(_dataSrc + offset) == 'FOBJ') { + _chars[l].width = READ_LE_UINT16(_dataSrc + offset + 14); + _chars[l].height = READ_LE_UINT16(_dataSrc + offset + 16); + _chars[l].chr = new byte[_chars[l].width * _chars[l].height + 1000]; + decodeCodec(_chars[l].chr, _dataSrc + offset + 22, READ_BE_UINT32(_dataSrc + offset + 4) - 14); + offset += READ_BE_UINT32(_dataSrc + offset + 4) + 8; + } else { + debug(2, "SmushFont::loadFont(%s, %s) there is no FOBJ chunk in FRME chunk %d (offset %x)", filename, directory, l, offset); + break; + } + } else { + debug(2, "SmushFont::loadFont(%s, %s) there is no FRME chunk %d (offset %x)", filename, directory, l, offset); + break; + } + } + + free(_dataSrc); + _dataSrc = NULL; + return true; +} + +int SmushFont::getCharWidth(byte v) { + if(v >= _nbChars) + error("invalid character in SmushFont::charWidth : %d (%d)", v, _nbChars); + + return _chars[v].width; +} + +int SmushFont::getCharHeight(byte v) { + if(v >= _nbChars) + error("invalid character in SmushFont::charHeight : %d (%d)", v, _nbChars); + + return _chars[v].height; +} + +int SmushFont::getStringWidth(char *str) { + int ret = 0; + + while(*str) { + ret += getCharWidth(*str++); + } + + return ret; +} + +int SmushFont::getStringHeight(char *str) { + int ret = 0; + + for(int i = 0; str[i] != 0; i++) { + int h = getCharHeight(str[i]); + ret = MAX(ret, h); + } + + return ret; +} + +void SmushFont::decodeCodec(byte *dst, byte *src, int length) { + int size_line, num; + byte *src2 = src; + byte *dst2 = dst; + byte val; + + do { + size_line = READ_LE_UINT16(src2); + src2 += 2; + length -= 2; + + while (size_line != 0) { + num = *src2++; + val = *src2++; + memset(dst2, val, num); + dst2 += num; + length -= 2; + size_line -= 2; + if (size_line != 0) { + num = READ_LE_UINT16(src2) + 1; + src2 += 2; + memcpy(dst2, src2, num); + dst2 += num; + src2 += num; + length -= num + 2; + size_line -= num + 2; + } + } + dst2--; + + } while (length > 1); +} + +int SmushFont::drawChar(byte *buffer, int dst_width, int x, int y, byte chr) { + int w = _chars[chr].width; + int h = _chars[chr].height; + byte *src = _chars[chr].chr; + byte *dst = buffer + dst_width * y + x; + + if(_original) { + for(int32 j = 0; j < h; j++) { + for(int32 i = 0; i < w; i++) { + char value = *src++; + if(value) dst[i] = value; + } + dst += dst_width; + } + } else { + char color = (_color != -1) ? _color : 1; + if (_new_colors == true) { + for(int j = 0; j < h; j++) { + for(int i = 0; i < w; i++) { + char value = *src++; + if(value == -color) { + dst[i] = 0xFF; + } else if(value == -31) { + dst[i] = 0; + } else if(value) { + dst[i] = value; + } + } + dst += dst_width; + } + } else { + for(int j = 0; j < h; j++) { + for(int i = 0; i < w; i++) { + char value = *src++; + if(value == 1) { + dst[i] = color; + } else if(value) { + dst[i] = 0; + } + } + dst += dst_width; + } + } + } + return w; +} + +static char **split(char *str, char sep) { + char **ret = new char *[62]; + int n = 0; + const char *i = str; + char *j = strchr(i, sep); + + while(j != NULL) { + assert(n < 60); + ret[n] = new char[j - i + 1]; + memcpy(ret[n], i, j - i); + ret[n++][j - i] = 0; + i = j + 1; + j = strchr(i, sep); + } + + ret[n] = new char[strlen(i) + 1]; + memcpy(ret[n], i, strlen(i)); + ret[n++][strlen(i)] = 0; + ret[n] = 0; + + return ret; +} + +void SmushFont::drawSubstring(char *str, byte *buffer, int dst_width, int x, int y) { + for(int i = 0; str[i] != 0; i++) + x += drawChar(buffer, dst_width, x, y, str[i]); +} + +void SmushFont::drawStringAbsolute(char *str, byte *buffer, int dst_width, int x, int y) { + debug(9, "SmushFont::drawStringAbsolute(%s, %d, %d)", str, x, y); + + while(str) { + char line[256]; + char *pos = strchr(str, '\n'); + if(pos) { + memcpy(line, str, pos - str - 1); + line[pos - str - 1] = 0; + str = pos + 1; + } else { + strcpy(line, str); + str = 0; + } + drawSubstring(line, buffer, dst_width, x, y); + y += getStringHeight(line); + } +} + +void SmushFont::drawStringCentered(char *str, byte *buffer, int dst_width, int dst_height, int y, int xmin, int width, int offset) { + debug(9, "SmushFont::drawStringCentered(%s, %d, %d)", str, xmin, y); + + if ((strchr(str, '\n') != 0)) { + char *z = strchr(str, '\n'); + *z = 0; + } + char **words = split(str, ' '); + int nb_sub = 0; + + while(words[nb_sub]) + nb_sub++; + + int *sizes = new int[nb_sub]; + int i = 0, max_width = 0, height = 0, nb_subs = 0; + + for(i = 0; i < nb_sub; i++) + sizes[i] = getStringWidth(words[i]); + + char **substrings = new char *[nb_sub]; + int *substr_widths = new int[nb_sub]; + int space_width = getCharWidth(' '); + + i = 0; + while(i < nb_sub) { + int substr_width = sizes[i]; + char *substr = new char[1000]; + strcpy(substr, words[i]); + int j = i + 1; + + while(j < nb_sub && (substr_width + space_width + sizes[j]) < width) { + substr_width += sizes[j++] + space_width; + } + + for(int k = i + 1; k < j; k++) { + strcat(substr, " "); + strcat(substr, words[k]); + } + + substrings[nb_subs] = substr; + substr_widths[nb_subs++] = substr_width; + if(substr_width > max_width) + max_width = substr_width; + i = j; + height += getStringHeight(substr); + } + + delete []sizes; + for(i = 0; i < nb_sub; i++) { + delete []words[i]; + } + delete []words; + + max_width = (max_width + 1) >> 1; + int x = xmin + width / 2; + x += offset - dst_width / 2; + + if(x < max_width) x = max_width; + if(x + max_width > dst_width) { + x = dst_width - max_width; + } + + if(y + height > dst_height) { + y = dst_height - height; + } + + for(i = 0; i < nb_subs; i++) { + int substr_width = substr_widths[i]; + drawSubstring(substrings[i], buffer, dst_width, x - substr_width / 2, y); + y += getStringHeight(substrings[i]); + delete []substrings[i]; + } + + delete []substr_widths; + delete []substrings; +} + +void SmushFont::drawStringWrap(char *str, byte *buffer, int dst_width, int dst_height, int x, int y, int width) { + debug(9, "SmushFont::drawStringWrap(%s, %d, %d)", str, x, y); + + if ((strchr(str, '\n') != 0)) { + char *z = strchr(str, '\n'); + *z = 0; + } + char ** words = split(str, ' '); + int nb_sub = 0; + + while(words[nb_sub]) + nb_sub++; + + int *sizes = new int[nb_sub]; + int i = 0, max_width = 0, height = 0, nb_subs = 0, left_x; + + for(i = 0; i < nb_sub; i++) + sizes[i] = getStringWidth(words[i]); + + char **substrings = new char *[nb_sub]; + int *substr_widths = new int[nb_sub]; + int space_width = getCharWidth(' '); + + i = 0; + while(i < nb_sub) { + int substr_width = sizes[i]; + char *substr = new char[1000]; + strcpy(substr, words[i]); + int j = i + 1; + + while(j < nb_sub && (substr_width + space_width + sizes[j]) < width) { + substr_width += sizes[j++] + space_width; + } + + for(int k = i + 1; k < j; k++) { + strcat(substr, " "); + strcat(substr, words[k]); + } + + substrings[nb_subs] = substr; + substr_widths[nb_subs++] = substr_width; + i = j; + height += getStringHeight(substr); + } + + delete []sizes; + for(i = 0; i < nb_sub; i++) { + delete []words[i]; + } + delete []words; + + if(y + height > dst_height) { + y = dst_height - height; + } + + for(i = 0; i < nb_subs; i++) + max_width = MAX(max_width, substr_widths[i]); + + if(max_width + x > dst_width) + left_x = dst_width - max_width + getCharWidth(' '); + else + left_x = x; + + if(max_width + left_x > dst_height) + left_x = dst_width - max_width; + + for(i = 0; i < nb_subs; i++) { + drawSubstring(substrings[i], buffer, dst_width, left_x, y); + y += getStringHeight(substrings[i]); + delete []substrings[i]; + } + + delete []substr_widths; + delete []substrings; +} + +void SmushFont::drawStringWrapCentered(char *str, byte *buffer, int dst_width, int dst_height, int x, int32 y, int width) { + debug(9, "SmushFont::drawStringWrapCentered(%s, %d, %d)", str, x, y); + + int max_substr_width = 0; + if ((strchr(str, '\n') != 0)) { + char *z = strchr(str, '\n'); + *z = 0; + } + char **words = split(str, ' '); + int nb_sub = 0; + + while(words[nb_sub]) + nb_sub++; + + int *sizes = new int[nb_sub]; + int i = 0, height = 0, nb_subs = 0; + + for(i = 0; i < nb_sub; i++) + sizes[i] = getStringWidth(words[i]); + + char **substrings = new char *[nb_sub]; + int *substr_widths = new int[nb_sub]; + int space_width = getCharWidth(' '); + + i = 0; + width = MIN(width, dst_width); + while(i < nb_sub) { + int substr_width = sizes[i]; + char *substr = new char[1000]; + strcpy(substr, words[i]); + int j = i + 1; + + while(j < nb_sub && (substr_width + space_width + sizes[j]) < width) { + substr_width += sizes[j++] + space_width; + } + + for(int k = i + 1; k < j; k++) { + strcat(substr, " "); + strcat(substr, words[k]); + } + + substrings[nb_subs] = substr; + substr_widths[nb_subs++] = substr_width; + max_substr_width = MAX(substr_width, max_substr_width); + i = j; + height += getStringHeight(substr); + } + + delete []sizes; + for(i = 0; i < nb_sub; i++) { + delete []words[i]; + } + delete []words; + + if(y + height > dst_height) { + y = dst_height - height; + } + + x = (dst_width - max_substr_width) / 2; + + for(i = 0; i < nb_subs; i++) { + int substr_width = substr_widths[i]; + drawSubstring(substrings[i], buffer, dst_width, x + (max_substr_width - substr_width) / 2, y); + y += getStringHeight(substrings[i]); + delete []substrings[i]; + } + + delete []substr_widths; + delete []substrings; +} diff --git a/scumm/smush/smush_font.h b/scumm/smush/smush_font.h new file mode 100644 index 00000000000..39ecd939f9a --- /dev/null +++ b/scumm/smush/smush_font.h @@ -0,0 +1,67 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2002-2003 The ScummVM project + * + * This program 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 2 + * of the License, or (at your option) any later version. + + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +#ifndef SMUSH_FONT_H +#define SMUSH_FONT_H + +#include "common/scummsys.h" + +class SmushFont { +private: + + int _nbChars; + byte _color; + bool _new_colors; + bool _original; + byte *_dataSrc; + + struct { + int width; + int height; + byte *chr; + } _chars[256]; + +public: + + SmushFont(bool use_original_colors, bool new_colors); + ~SmushFont(); + +protected: + + int getCharWidth(byte c); + int getStringWidth(char *str); + int getCharHeight(byte c); + int getStringHeight(char *str); + int drawChar(byte *buffer, int dst_width, int x, int y, byte chr); + void drawSubstring(char *str, byte *buffer, int dst_width, int x, int y); + void decodeCodec(byte *dst, byte *src, int length); + +public: + + bool loadFont(const char *filename, const char *directory); + void setColor(byte c) { _color = c; } + void drawStringCentered(char *str, byte *buffer, int dst_width, int dst_height, int y, int xmin, int width, int offset); + void drawStringWrap(char *str, byte *buffer, int dst_width, int dst_height, int x, int y, int width); + void drawStringWrapCentered(char *str, byte *buffer, int dst_width, int dst_height, int x, int32 y, int width); + void drawStringAbsolute(char *str, byte *buffer, int dst_width, int x, int y); +}; + +#endif diff --git a/scumm/smush/smush_mixer.cpp b/scumm/smush/smush_mixer.cpp new file mode 100644 index 00000000000..c7ed4708b69 --- /dev/null +++ b/scumm/smush/smush_mixer.cpp @@ -0,0 +1,166 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2002-2003 The ScummVM project + * + * This program 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 2 + * of the License, or (at your option) any later version. + + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +#include +#include "common/util.h" +#include "smush_mixer.h" +#include "channel.h" +#include "sound/mixer.h" +#include "scumm/scumm.h" +#include "scumm/sound.h" +#include "scumm/imuse.h" + +SmushMixer::SmushMixer(SoundMixer *m) : + _mixer(m), + _soundFrequency(22050), + _nextIndex(_mixer->_beginSlots) { + for(int32 i = _mixer->_beginSlots; i < SoundMixer::NUM_CHANNELS; i++) { + _channels[i].id = -1; + _channels[i].chan = NULL; + _channels[i].first = true; + } +} + +SmushMixer::~SmushMixer() { +} + +SmushChannel *SmushMixer::findChannel(int32 track) { + debug(9, "SmushMixer::findChannel(%d)", track); + for(int32 i = _mixer->_beginSlots; i < SoundMixer::NUM_CHANNELS; i++) { + if(_channels[i].id == track) + return _channels[i].chan; + } + return NULL; +} + +bool SmushMixer::addChannel(SmushChannel *c) { + int32 track = c->getTrackIdentifier(); + int i; + + debug(9, "SmushMixer::addChannel(%d)", track); + + for(i = _mixer->_beginSlots; i < SoundMixer::NUM_CHANNELS; i++) { + if(_channels[i].id == track) + warning("SmushMixer::addChannel(%d) : channel already exist !", track); + } + if(_nextIndex >= SoundMixer::NUM_CHANNELS) + _nextIndex = _mixer->_beginSlots; + + for(i = _nextIndex; i < SoundMixer::NUM_CHANNELS; i++) { + if(_channels[i].chan == NULL || _channels[i].id == -1) { + _channels[i].chan = c; + _channels[i].id = track; + _channels[i].first = true; + _nextIndex = i + 1; + return true; + } + } + + for(i = _mixer->_beginSlots; i < _nextIndex; i++) { + if(_channels[i].chan == NULL || _channels[i].id == -1) { + _channels[i].chan = c; + _channels[i].id = track; + _channels[i].first = true; + _nextIndex = i + 1; + return true; + } + } + + warning("_nextIndex == %d\n", _nextIndex); + + for(i = _mixer->_beginSlots; i < SoundMixer::NUM_CHANNELS; i++) { + warning("channel %d : %p(%d, %d) %d %d\n", i, (void *)_channels[i].chan, + _channels[i].chan ? _channels[i].chan->getTrackIdentifier() : -1, + _channels[i].chan ? _channels[i].chan->isTerminated() : 1, + _channels[i].first, _channels[i].mixer_index); + } + + error("SmushMixer::add_channel() : no more channel available"); + return false; +} + +bool SmushMixer::handleFrame() { + debug(9, "SmushMixer::handleFrame()"); + for(int i = _mixer->_beginSlots; i < SoundMixer::NUM_CHANNELS; i++) { + if(_channels[i].id != -1) { + if(_channels[i].chan->isTerminated()) { + delete _channels[i].chan; + _channels[i].id = -1; + _channels[i].chan = NULL; + } else { + int32 rate; + bool stereo, is_short; + + _channels[i].chan->getParameters(rate, stereo, is_short); + int32 size = _channels[i].chan->availableSoundData(); + int32 flags = stereo ? SoundMixer::FLAG_STEREO : 0; + + if(is_short) { + short *data = new int16[size * (stereo ? 2 : 1) * 2]; + _channels[i].chan->getSoundData(data, size); + if(_channels[i].chan->getRate() == 11025) size *= 2; + size *= stereo ? 4 : 2; + + if(_silentMixer == false) { + if(_channels[i].first) { + _channels[i].mixer_index = _mixer->playStream(NULL, -1, data, size, rate, flags | SoundMixer::FLAG_16BITS); + _channels[i].first = false; + } else { + _mixer->append(_channels[i].mixer_index, data, size, rate, flags | SoundMixer::FLAG_16BITS); + } + } + + delete []data; + } else { + int8 *data = new int8[size * (stereo ? 2 : 1) * 2]; + _channels[i].chan->getSoundData(data, size); + if(_channels[i].chan->getRate() == 11025) size *= 2; + size *= stereo ? 2 : 1; + + if(_silentMixer == false) { + if(_channels[i].first) { + _channels[i].mixer_index = _mixer->playStream(NULL, -1, data, size, rate, flags | SoundMixer::FLAG_UNSIGNED); + _channels[i].first = false; + } else { + _mixer->append(_channels[i].mixer_index, data, size, rate, flags | SoundMixer::FLAG_UNSIGNED); + } + } + + delete []data; + } + } + } + } + return true; +} + +bool SmushMixer::stop() { + debug(9, "SmushMixer::stop()"); + for(int i = _mixer->_beginSlots; i < SoundMixer::NUM_CHANNELS; i++) { + if(_channels[i].id != -1) { + delete _channels[i].chan; + _channels[i].id = -1; + _channels[i].chan = NULL; + } + } + return true; +} + diff --git a/scumm/smush/config.h b/scumm/smush/smush_mixer.h similarity index 64% rename from scumm/smush/config.h rename to scumm/smush/smush_mixer.h index 6ba4341e07b..ea446a228ed 100644 --- a/scumm/smush/config.h +++ b/scumm/smush/smush_mixer.h @@ -19,24 +19,34 @@ * */ -#ifndef SMUSH_CONFIG_H -#define SMUSH_CONFIG_H - #include -#include -#ifndef NDEBUG -#define DEBUG -#endif +#include "sound/mixer.h" -#define NO_DEBUG_MIXER -#define NO_DEBUG_CHANNEL -#define NO_DEBUG_CLIPPER -#define NO_DEBUG_CODEC1 -#define NO_DEBUG_CODEC37 -#define NO_DEBUG_CODEC44 -#define NO_DEBUG_WIN32 -#define NO_DEBUG_FONT_RENDERER +class SmushChannel; +class SmushMixer { +private: -#endif + SoundMixer *_mixer; + struct { + int id; + SmushChannel *chan; + bool first; + int mixer_index; + } _channels[SoundMixer::NUM_CHANNELS]; + + int _nextIndex; + int _soundFrequency; + +public: + + SmushMixer(SoundMixer *); + virtual ~SmushMixer(); + SmushChannel *findChannel(int32 track); + bool addChannel(SmushChannel *c); + bool handleFrame(); + bool stop(); + bool update(); + bool _silentMixer; +}; diff --git a/scumm/smush/player.cpp b/scumm/smush/smush_player.cpp similarity index 56% rename from scumm/smush/player.cpp rename to scumm/smush/smush_player.cpp index 437cdbe6450..d114718d7e0 100644 --- a/scumm/smush/player.cpp +++ b/scumm/smush/smush_player.cpp @@ -22,39 +22,38 @@ #include #include "common/file.h" #include "common/util.h" -#include "common/engine.h" // for debug, warning, error +#include "common/engine.h" #include "scumm/scumm.h" +#include "scumm/sound.h" +#include "scumm/imuse.h" #include "sound/mixer.h" - -#include "player.h" - -#include "mixer.h" -#include "renderer.h" -#include "frenderer.h" +#include "smush_player.h" +#include "smush_mixer.h" +#include "smush_font.h" #include "channel.h" +#include "chunk.h" #include "chunk_type.h" -#include -#include -#include -#include -#include - -const int WAIT = 100; - -const int32 MAX_STRINGS = 200; +const int MAX_STRINGS = 200; class StringResource { private: + struct { - int32 id; + int id; char *string; } _strings[MAX_STRINGS]; - int32 _nbStrings; - int32 _lastId; + + int _nbStrings; + int _lastId; char *_lastString; + public: - StringResource() : _nbStrings(0), _lastId(-1) {}; + + StringResource() : + _nbStrings(0), + _lastId(-1) { + }; ~StringResource() { for(int32 i = 0; i < _nbStrings; i++) { delete []_strings[i].string; @@ -62,22 +61,22 @@ public: } bool init(char *buffer, int32 length) { -#ifdef DEBUG - debug(9, "parsing string resources..."); -#endif char *def_start = strchr(buffer, '#'); while(def_start != NULL) { char *def_end = strchr(def_start, '\n'); assert(def_end != NULL); + char *id_end = def_end; while(id_end >= def_start && !isdigit(*(id_end-1))) { id_end--; } + assert(id_end > def_start); char *id_start = id_end; while(isdigit(*(id_start - 1))) { id_start--; } + char idstring[32]; memcpy(idstring, id_start, id_end - id_start); idstring[id_end - id_start] = 0; @@ -120,9 +119,6 @@ public: memmove(line_end, line_start, strlen(line_start)+1); } } -#ifdef DEBUG - debug(9, "Inserting (%s)%d == \"%s\"", idstring, id, value); -#endif _strings[_nbStrings].id = id; _strings[_nbStrings].string = value; _nbStrings ++; @@ -131,7 +127,7 @@ public: return true; } - const char *get(int32 id) { + char *get(int id) { if(id == _lastId) { return _lastString; } @@ -149,85 +145,136 @@ public: } }; -void SmushPlayer::show(const char *p) { - if(strcmp(p, "subtitles") == 0) { - _subtitles = true; - } else if(strcmp(p, "bgmusic") == 0) { - _bgmusic = true; - } else if(strcmp(p, "voices") == 0) { - _voices = true; - } else { - int id = atoi(p); - if(id < 0 || id > 36) { - error("invalid parameter to show"); - } - _skips[id] = true; +static StringResource *getStrings(const char *file, const char *directory, bool is_encoded) { + debug(7, "trying to read text ressources from %s", file); + File theFile; + + theFile.open(file, directory); + if (!theFile.isOpen()) { + return 0; } + int32 length = theFile.size(); + char *filebuffer = new char [length + 1]; + assert(filebuffer); + theFile.read(filebuffer, length); + filebuffer[length] = 0; + + if(is_encoded) { + static const int32 ETRS_HEADER_LENGTH = 16; + assert(length > ETRS_HEADER_LENGTH); + Chunk::type type = READ_BE_UINT32(filebuffer); + + if(type != TYPE_ETRS) { + delete [] filebuffer; + return getStrings(file, directory, false); + } + + char *old = filebuffer; + filebuffer = new char[length - ETRS_HEADER_LENGTH + 1]; + for(int32 i = ETRS_HEADER_LENGTH; i < length; i++) { + filebuffer[i - ETRS_HEADER_LENGTH] = old[i] ^ 0xCC; + } + filebuffer[length - ETRS_HEADER_LENGTH] = '\0'; + delete []old; + length -= ETRS_HEADER_LENGTH; + } + StringResource *sr = new StringResource; + assert(sr); + sr->init(filebuffer, length); + delete []filebuffer; + return sr; } -void SmushPlayer::hide(const char *p) { - if(strcmp(p, "subtitles") == 0) { - _subtitles = false; - } else if(strcmp(p, "bgmusic") == 0) { - _bgmusic = false; - } else if(strcmp(p, "voices") == 0) { - _voices = false; - } else { - int32 id = atoi(p); - if(id < 0 || id > 36) { - error("invalid parameter to hide"); - } - _skips[id] = false; - } +SmushPlayer *player; + +void smush_callback(void *ptr) { + player->_smushProcessFrame = true; + player->parseNextFrame(); + player->_smushProcessFrame = false; } -SmushPlayer::SmushPlayer(Renderer * renderer, bool wait, bool sound) : - _version(-1), - _secondaryVersion(0), - _soundFrequency(0), - _nbframes(0), - _mixer(0), - _renderer(renderer), - _strings(0), - _frameSize(-1, -1), - _frame(0), - _outputSound(sound), - _wait(wait), - _alreadyInit(false), - _codec37Called(false), - _skipNext(false), - _subtitles(true), - _bgmusic(true), - _voices(true), - _curBuffer(0), - _IACTchannel(-1), - _IACTpos(0), - _storeFrame(false), - _frameBuffer(NULL) { - _fr[0] = _fr[1] = _fr[2] = _fr[3] = _fr[4] = 0; - assert(_renderer != 0); +SmushPlayer::SmushPlayer(Scumm *scumm, int speed, bool subtitles) { + player = this; + _version = -1; + _nbframes = 0; + _smixer = 0; + _strings = NULL; + _skipNext = false; + _data = NULL; + _storeFrame = false; + _width = 0; + _height = 0; + _frameBuffer = NULL; + _sf[0] = NULL; + _sf[1] = NULL; + _sf[2] = NULL; + _sf[3] = NULL; + _sf[4] = NULL; + _scumm = scumm; + _IACTchannel = -1, + _IACTpos = 0; + _soundFrequency = 22050; + _speed = speed; + _subtitles = subtitles; + _smushProcessFrame = false; } SmushPlayer::~SmushPlayer() { - clean(); + deinit(); } -void SmushPlayer::updatePalette(void) { - _renderer->setPalette(_pal); -} +void SmushPlayer::init() { -void SmushPlayer::clean() { - if(_strings) - delete _strings; - if(_fr[0]) delete _fr[0]; - if(_fr[1]) delete _fr[1]; - if(_fr[2]) delete _fr[2]; - if(_fr[3]) delete _fr[3]; - if(_fr[4]) delete _fr[4]; + _frame = 0; - if (_frameBuffer != NULL) { - free(_frameBuffer); + _scumm->_sound->pauseBundleMusic(true); + if (_scumm->_imuseDigital) { + _scumm->_imuseDigital->pause(true); } + _scumm->_videoFinished = false; + _scumm->_insaneState = true; + + _smixer = new SmushMixer(_scumm->_mixer); + + _scumm->setDirtyColors(0, 255); + _smixer->_silentMixer = _scumm->_silentDigitalImuse; + _scumm->_smushPlay = true; + _data = _scumm->virtscr[0].screenPtr + _scumm->virtscr[0].xstart; + _scumm->_timer->installProcedure(&smush_callback, _speed); + + _alreadyInit = false; +} + +void SmushPlayer::deinit() { + _scumm->_smushPlay = false; + _scumm->_timer->releaseProcedure(&smush_callback); + while (_smushProcessFrame) {} + + for(int i = 0; i < 5; i++) { + if (_sf[i]) { + delete _sf[i]; + _sf[i] = NULL; + } + } + + if(_strings) { + delete _strings; + _strings = NULL; + } + + if(_smixer) { + _smixer->stop(); + delete _smixer; + _smixer = NULL; + } + + _scumm->_insaneState = false; + _scumm->exitCutscene(); + if (_scumm->_imuseDigital) { + _scumm->_imuseDigital->pause(false); + } + _scumm->_sound->pauseBundleMusic(false); + _scumm->_fullRedraw = 1; } void SmushPlayer::checkBlock(const Chunk &b, Chunk::type type_expected, uint32 min_size) { @@ -235,22 +282,22 @@ void SmushPlayer::checkBlock(const Chunk &b, Chunk::type type_expected, uint32 m error("Chunk type is different from expected : %d != %d", b.getType(), type_expected); } if(min_size > b.getSize()) { - error( "Chunk size is inferior than minimum required size : %d < %d", b.getSize(), min_size); + error("Chunk size is inferior than minimum required size : %d < %d", b.getSize(), min_size); } } void SmushPlayer::handleSoundBuffer(int32 track_id, int32 index, int32 max_frames, int32 flags, int32 vol, int32 bal, Chunk &b, int32 size) { - debug(6, "smush_player::handleSoundBuffer(%d)", track_id); - if(!_voices && (flags & 128) == 128) { - return; - } - if(!_bgmusic && (flags & 64) == 64) { - return; - } - _Channel *c = _mixer->findChannel(track_id); - if(c == 0) { + debug(6, "SmushPlayer::handleSoundBuffer(%d)", track_id); +// if((flags & 128) == 128) { +// return; +// } +// if((flags & 64) == 64) { +// return; +// } + SmushChannel *c = _smixer->findChannel(track_id); + if(c == NULL) { c = new SaudChannel(track_id, _soundFrequency); - _mixer->addChannel(c); + _smixer->addChannel(c); } if(index == 0) { c->setParameters(max_frames, flags, vol, bal); @@ -263,9 +310,7 @@ void SmushPlayer::handleSoundBuffer(int32 track_id, int32 index, int32 max_frame void SmushPlayer::handleSoundFrame(Chunk &b) { checkBlock(b, TYPE_PSAD); debug(6, "SmushPlayer::handleSoundFrame()"); - if(!_outputSound) { - return; - } + int32 track_id = b.getWord(); int32 index = b.getWord(); int32 max_frames = b.getWord(); @@ -292,31 +337,27 @@ void SmushPlayer::handleSkip(Chunk &b) { } void SmushPlayer::handleStore(Chunk &b) { + debug(6, "SmushPlayer::handleStore()"); checkBlock(b, TYPE_STOR, 4); _storeFrame = true; - debug(6, "SmushPlayer::handleStore()"); } void SmushPlayer::handleFetch(Chunk &b) { - checkBlock(b, TYPE_FTCH, 6); debug(6, "SmushPlayer::handleFetch()"); - - if(_curBuffer == NULL) { - _curBuffer = _renderer->lockFrame(_frame); - } + checkBlock(b, TYPE_FTCH, 6); if (_frameBuffer != NULL) { - memcpy(_curBuffer, _frameBuffer, _frameSize.getX() * _frameSize.getY()); + memcpy(_data, _frameBuffer, _width * _height); } } void SmushPlayer::handleImuseBuffer(int32 track_id, int32 index, int32 nbframes, int32 size, int32 unk1, int32 track_flags, Chunk &b, int32 bsize) { int32 track = (track_flags << 16) | track_id; - _Channel *c = _mixer->findChannel(track); + SmushChannel *c = _smixer->findChannel(track); if(c == 0) { c = new ImuseChannel(track, _soundFrequency); - _mixer->addChannel(c); + _smixer->addChannel(c); } if(index == 0) c->setParameters(nbframes, size, track_flags, unk1); @@ -325,13 +366,22 @@ void SmushPlayer::handleImuseBuffer(int32 track_id, int32 index, int32 nbframes, c->appendData(b, bsize); } -void SmushPlayer::handleImuseAction8(Chunk &b, int32 flags, int32 unknown, int32 track_flags) { +void SmushPlayer::handleImuseAction(Chunk &b) { + checkBlock(b, TYPE_IACT, 8); + debug(6, "SmushPlayer::handleImuseAction()"); + + int code = b.getWord(); + int flags = b.getWord(); + int unknown = b.getShort(); + int track_flags = b.getWord(); + assert(flags == 46 && unknown == 0); - int32 track_id = b.getWord(); - int32 index = b.getWord(); - int32 nbframes = b.getWord(); + int track_id = b.getWord(); + int index = b.getWord(); + int nbframes = b.getWord(); int32 size = b.getDword(); int32 bsize = b.getSize() - 18; + if (g_scumm->_gameId != GID_CMI) { handleImuseBuffer(track_id, index, nbframes, size, unknown, track_flags, b, bsize); } else { @@ -382,10 +432,10 @@ void SmushPlayer::handleImuseAction8(Chunk &b, int32 flags, int32 unknown, int32 } while (--count); if (_IACTchannel == -1) { - _IACTchannel = g_scumm->_mixer->playStream(NULL, -1, output_data, 0x1000, 22050, + _IACTchannel = _scumm->_mixer->playStream(NULL, -1, output_data, 0x1000, 22050, SoundMixer::FLAG_STEREO | SoundMixer::FLAG_16BITS, -1, 200000); } else { - g_scumm->_mixer->append(_IACTchannel, output_data, 0x1000, 22050, + _scumm->_mixer->append(_IACTchannel, output_data, 0x1000, 22050, SoundMixer::FLAG_STEREO | SoundMixer::FLAG_16BITS); } @@ -419,53 +469,23 @@ void SmushPlayer::handleImuseAction8(Chunk &b, int32 flags, int32 unknown, int32 } } -void SmushPlayer::handleImuseAction(Chunk &b) { - checkBlock(b, TYPE_IACT, 8); - debug(6, "SmushPlayer::handleImuseAction()"); - if(!_outputSound) { - return; - } - int32 code = b.getWord(); - int32 flags = b.getWord(); - int32 unknown = b.getShort(); - int32 track_flags = b.getWord(); -#ifdef DEBUG - debug(5, "handleImuseAction(%d, %d, %d, %d)", code, flags, unknown, track_flags); -#endif - switch(code) { - case 8: - handleImuseAction8(b, flags, unknown, track_flags); - break; -#ifdef DEBUG - default: { - debug(9, "%5.5d %d %8.8d %4.4d", track_flags, flags, unknown); - } -#endif - } -} - void SmushPlayer::handleTextResource(Chunk &b) { - int32 pos_x = b.getShort(); - int32 pos_y = b.getShort(); - int32 flags = b.getShort(); - int32 left = b.getShort(); - int32 top = b.getShort(); - int32 width = b.getShort(); + int pos_x = b.getShort(); + int pos_y = b.getShort(); + int flags = b.getShort(); + int left = b.getShort(); + int top = b.getShort(); + int width = b.getShort(); /*int32 height =*/ b.getShort(); /*int32 unk2 =*/ b.getWord(); - const char *str; - char *string = NULL; - char *string2 = NULL; + char *str, *string = NULL, *string2 = NULL; if (b.getType() == TYPE_TEXT) { - string = (char*)malloc(b.getSize() - 16); + string = (char *)malloc(b.getSize() - 16); str = string; b.read(string, b.getSize() - 16); } else { - int32 string_id = b.getWord(); -#ifdef DEBUG - debug(6, "SmushPlayer::handleTextResource(%d)", string_id); -#endif + int string_id = b.getWord(); if(!_strings) return; str = _strings->get(string_id); @@ -475,16 +495,16 @@ void SmushPlayer::handleTextResource(Chunk &b) { if((!_subtitles) && ((flags & 8) == 8)) return; - FontRenderer *fr = _fr[0]; - int32 color = 15; + SmushFont *sf = _sf[0]; + int color = 15; while(*str == '/') { str++; // For Full Throttle text resources } - if (g_scumm->_gameId == GID_CMI) { - g_scumm->translateText((byte *)str - 1, g_scumm->_transText); + if (_scumm->_gameId == GID_CMI) { + _scumm->translateText((byte*)str - 1, _scumm->_transText); while(*str++ != '/'); - string2 = (char*)g_scumm->_transText; + string2 = (char *)_scumm->_transText; // If string2 contains formatting information there probably // wasn't any translation for it in the language.tab file. In @@ -499,7 +519,7 @@ void SmushPlayer::handleTextResource(Chunk &b) { { int id = str[3] - '0'; str += 4; - fr = _fr[id]; + sf = _sf[id]; } break; case 'c': @@ -512,18 +532,16 @@ void SmushPlayer::handleTextResource(Chunk &b) { error("invalid escape code in text string"); } } - assert(fr != 0); - fr->setColor(color); - if(!_curBuffer) { - _curBuffer = _renderer->lockFrame(_frame); - } - if (g_scumm->_gameId != GID_CMI) { - string2 = (char *)str; + assert(sf != NULL); + sf->setColor(color); + + if (_scumm->_gameId != GID_CMI) { + string2 = str; } - if (g_scumm->_gameId == GID_CMI) { + if (_scumm->_gameId == GID_CMI) { if (string2[0] == 0) { - string2 = (char *)str; + string2 = str; } } @@ -534,28 +552,28 @@ void SmushPlayer::handleTextResource(Chunk &b) { // bit 3 - wrap around 8 switch (flags) { case 0: - fr->drawStringAbsolute(string2, _curBuffer, _frameSize, pos_x, pos_y); + sf->drawStringAbsolute(string2, _data, _width, pos_x, pos_y); break; case 1: - fr->drawStringCentered(string2, _curBuffer, _frameSize, MAX(pos_y, top), left, width, pos_x); + sf->drawStringCentered(string2, _data, _width, _height, MAX(pos_y, top), left, width, pos_x); break; case 4: - fr->drawStringAbsolute(string2, _curBuffer, _frameSize, pos_x, pos_y); + sf->drawStringAbsolute(string2, _data, _width, pos_x, pos_y); break; case 5: - fr->drawStringCentered(string2, _curBuffer, _frameSize, MAX(pos_y, top), left, width, pos_x); + sf->drawStringCentered(string2, _data, _width, _height, MAX(pos_y, top), left, width, pos_x); break; case 8: - fr->drawStringWrap(string2, _curBuffer, _frameSize, pos_x, MAX(pos_y, top), width); + sf->drawStringWrap(string2, _data, _width, _height, pos_x, MAX(pos_y, top), width); break; case 9: - fr->drawStringCentered(string2, _curBuffer, _frameSize, MAX(pos_y, top), left, width, pos_x); + sf->drawStringCentered(string2, _data, _width, _height, MAX(pos_y, top), left, width, pos_x); break; case 12: - fr->drawStringWrap(string2, _curBuffer, _frameSize, pos_x, MAX(pos_y, top), width); + sf->drawStringWrap(string2, _data, _width, _height, pos_x, MAX(pos_y, top), width); break; case 13: - fr->drawStringWrapCentered(string2, _curBuffer, _frameSize, pos_x, MAX(pos_y, top), width); + sf->drawStringWrapCentered(string2, _data, _width, _height, pos_x, MAX(pos_y, top), width); break; default: warning("SmushPlayer::handleTextResource. Not handled flags: %d\n", flags); @@ -566,92 +584,79 @@ void SmushPlayer::handleTextResource(Chunk &b) { } } -void SmushPlayer::readPalette(Palette &out, Chunk &in) { - byte buffer[768]; - in.read(buffer, 768); - out = Palette(buffer); +bool SmushPlayer::readString(const char *file, const char *directory) { + const char *i = strrchr(file, '.'); + if(i == NULL) { + error("invalid filename : %s", file); + } + char fname[260]; + memcpy(fname, file, i - file); + strcpy(fname + (i - file), ".trs"); + if((_strings = getStrings(fname, directory, false)) != 0) { + return true; + } + + if((_strings = getStrings("digtxt.trs", directory, true)) != 0) { + return true; + } + return false; +} + +void SmushPlayer::readPalette(byte *out, Chunk &in) { + in.read(out, 0x300); +} + +static byte delta_color(byte org_color, int16 delta_color) { + int16 t; + t = (((int32)(org_color) << 7) + org_color + delta_color) >> 7; + if (t > 255) + t = 255; + if (t < 0) + t = 0; + return (byte)t; } void SmushPlayer::handleDeltaPalette(Chunk &b) { checkBlock(b, TYPE_XPAL); debug(6, "SmushPlayer::handleDeltaPalette()"); - if(b.getSize() == 768 * 3 + 4) { - int32 unk1, num; - unk1 = b.getWord(); - num = b.getWord(); - for(int32 i = 0; i < 768; i++) { + + if(b.getSize() == 0x300 * 3 + 4) { + + b.getWord(); + b.getWord(); + + for(int i = 0; i < 0x300; i++) { _deltaPal[i] = b.getWord(); } readPalette(_pal, b); - updatePalette(); + setPalette(_pal); } else if(b.getSize() == 6) { - int32 unk1, num, unk2; - unk1 = b.getWord(); - num = b.getWord(); - unk2 = b.getWord(); - for(int32 i = 0; i < 256; i++) { - _pal[i].delta(_deltaPal + 3 * i); + + b.getWord(); + b.getWord(); + b.getWord(); + + for(int i = 0; i < 0x300; i++) { + _pal[i] = delta_color(_pal[i], _deltaPal[i]); } - updatePalette(); + setPalette(_pal); } else { - error("wrong size for DeltaPalette"); + error("SmushPlayer::handleDeltaPalette() Wrong size for DeltaPalette"); } } void SmushPlayer::handleNewPalette(Chunk &b) { - checkBlock(b, TYPE_NPAL, 768); + checkBlock(b, TYPE_NPAL, 0x300); debug(6, "SmushPlayer::handleNewPalette()"); + readPalette(_pal, b); - updatePalette(); + setPalette(_pal); } -void SmushPlayer::decodeCodec(Chunk &src, const Rect &r, Decoder &codec) { - assert(_curBuffer); - - int32 chunk_size = src.getSize() - 14; - byte *chunk_buffer = (byte *)malloc(chunk_size); - assert(chunk_buffer); - src.read(chunk_buffer, chunk_size); - codec.decode((byte *)_curBuffer, chunk_buffer, chunk_size); - free(chunk_buffer); - - if (_storeFrame == true) { - if (_frameBuffer == NULL) { - _frameBuffer = (byte *)malloc(_frameSize.getX() * _frameSize.getY()); - } - memcpy(_frameBuffer, _curBuffer, _frameSize.getX() * _frameSize.getY()); - _storeFrame = false; - } +void SmushPlayer::initCodecs() { } -void SmushPlayer::initSize(const Rect &r, bool always, bool transparent) { - if(_codec37Called) _alreadyInit = true; - - if(!_alreadyInit || _frameSize.getX() < r.right() || _frameSize.getY() < r.bottom() || always) { - if(_curBuffer) { - _renderer->unlockFrame(); - _curBuffer = 0; - } - _frameSize = r.bottomRight(); - _renderer->initFrame(_frameSize); - } - - if(_curBuffer) { - _renderer->unlockFrame(); - _curBuffer = 0; - } - - _curBuffer = _renderer->lockFrame(_frame); - if(!_alreadyInit && transparent) { - memset(_curBuffer, 0, _frameSize.getX() * _frameSize.getY()); - } - - _codec1.initSize(_frameSize, r); - _codec37.initSize(_frameSize, r); - _codec47.initSize(_frameSize, r); - _codec44.initSize(_frameSize, r); - _alreadyInit = true; -} +extern void smush_decode_codec1(byte *dst, byte *src, int height); void SmushPlayer::handleFrameObject(Chunk &b) { checkBlock(b, TYPE_FOBJ, 14); @@ -659,53 +664,75 @@ void SmushPlayer::handleFrameObject(Chunk &b) { _skipNext = false; return; } + int codec = b.getWord(); - debug(6, "SmushPlayer::handleFrameObject(%d)", codec); - uint16 left = b.getWord(); - uint16 top = b.getWord(); - uint16 width = b.getWord(); - uint16 height = b.getWord(); - Rect r(left, top, left + width, top + height); - uint16 data[2]; - data[1] = b.getWord(); - data[0] = b.getWord(); -#ifdef DEBUG - debug(5, "Frame pos : %d, %d", left, top); - debug(5, "Frame size : %dx%d", width, height); - debug(5, "Codec : %d", codec); -#endif + b.getWord(); // left + b.getWord(); // top + int width = b.getWord(); + int height = b.getWord(); + + // hack for spontanic changing resolution + // differ than width scumm screen, and pass only one width 384x242 + if((height != _scumm->_realHeight) && (height != 242)) + return; + if (height == 242) + return; + if((width != _scumm->_realWidth) && (width != 384)) + return; + if (width == 384) + return; + + if(_alreadyInit == false) { + _codec37.init(width, height); + _codec47.init(width, height); + _alreadyInit = true; + } + + _width = width; + _height = height; + b.getWord(); + b.getWord(); + + + int32 chunk_size = b.getSize() - 14; + byte *chunk_buffer = (byte *)malloc(chunk_size); + assert(chunk_buffer); + b.read(chunk_buffer, chunk_size); + switch (codec) { - case 3: case 1: - initSize(r, false, true); - decodeCodec(b, r, _codec1); + case 3: + smush_decode_codec1(_data, chunk_buffer, _height); break; case 37: - initSize(r, true, false); - decodeCodec(b, r, _codec37); - _codec37Called = true; + _codec37.decode(_data, chunk_buffer); break; case 47: - initSize(r, true, false); - decodeCodec(b, r, _codec47); - _codec37Called = true; - break; - case 21: - case 44: - initSize(r, true, true); - decodeCodec(b, r, _codec44); + _codec47.decode(_data, chunk_buffer); break; default: - error("Invalid codec for frame object : %d", (int32)codec); + error("Invalid codec for frame object : %d", (int)codec); } + + if (_storeFrame == true) { + if (_frameBuffer == NULL) { + _frameBuffer = (byte *)malloc(_width * _height); + } + memcpy(_frameBuffer, _data, _width * _height); + _storeFrame = false; + } + + free(chunk_buffer); } void SmushPlayer::handleFrame(Chunk &b) { checkBlock(b, TYPE_FRME); debug(6, "SmushPlayer::handleFrame(%d)", _frame); - _alreadyInit = false; _skipNext = false; + uint32 start_time, curr_time, start_update, end_update; + start_time = _scumm->_system->get_msecs(); + while(!b.eof()) { Chunk *sub = b.subBlock(); if(sub->getSize() & 1) b.seek(1); @@ -745,188 +772,126 @@ void SmushPlayer::handleFrame(Chunk &b) { } delete sub; } - if(_curBuffer) { - _renderer->unlockFrame(); - _curBuffer = 0; + + curr_time = _scumm->_system->get_msecs(); + + _smixer->handleFrame(); + + start_update = _scumm->_system->get_msecs(); + if (curr_time < (start_time + _speed / 1000)) { + updateScreen(); + } else { + warning("SmushPlayer: skipping update frame %d", _frame); } - if(_outputSound) - _mixer->handleFrame(); -#ifdef DEBUG - debug(5, "===================END OF FRAME========================"); -#endif - _renderer->flipFrame(); - if(_wait) - _renderer->wait(WAIT); + end_update = _scumm->_system->get_msecs(); + debug(0, "Smush stats: FRME( %03d ),GFX_update( %03d ),FRME+GFX+SFX( %03d ),Limit(%d)", + curr_time - start_time, end_update - start_update, + end_update - start_time, _speed / 1000); + _frame++; } void SmushPlayer::handleAnimHeader(Chunk &b) { - checkBlock(b, TYPE_AHDR, 774); + checkBlock(b, TYPE_AHDR, 0x300 + 6); debug(6, "SmushPlayer::handleAnimHeader()"); + _version = b.getWord(); _nbframes = b.getWord(); b.getWord(); - _renderer->startDecode(_fname, _version, _nbframes); readPalette(_pal, b); - updatePalette(); - if(_version == 2) { - _secondaryVersion = b.getDword(); - b.getDword(); - if(_secondaryVersion != 10 && _secondaryVersion != 0 && _secondaryVersion != 12 && _secondaryVersion != 15 && _secondaryVersion != 14) { - error("Wrong secondary version number for SMUSH animation"); - } - } else if(_version > 2) { - error("Wrong primary version number for SMUSH animation"); - } - if(_outputSound) { - _soundFrequency = 22050; - _mixer = _renderer->getMixer(); - if(_mixer) { - _mixer->init(); - } else { - _outputSound = false; - } - } + setPalette(_pal); } -static StringResource *getStrings(const char *file, const char *directory, bool is_encoded) { - debug(7, "trying to read text ressources from %s", file); - File theFile; +void SmushPlayer::setupAnim(const char *file, const char *directory) { + _base = new FileChunk(file, directory); + Chunk *sub = _base->subBlock(); + checkBlock(*sub, TYPE_AHDR); + handleAnimHeader(*sub); - theFile.open(file, directory); - if (!theFile.isOpen()) { - return 0; - } - int32 length = theFile.size(); - char *filebuffer = new char [length + 1]; - assert(filebuffer); - theFile.read(filebuffer, length); - filebuffer[length] = 0; + readString(file, directory); - if(is_encoded) { - static const int32 ETRS_HEADER_LENGTH = 16; - assert(length > ETRS_HEADER_LENGTH); - Chunk::type type = READ_BE_UINT32(filebuffer); - - if(type != TYPE_ETRS) { - delete [] filebuffer; - return getStrings(file, directory, false); + if (_scumm->_gameId == GID_FT) { + _sf[0] = new SmushFont(true, false); + _sf[2] = new SmushFont(true, false); + _sf[0]->loadFont("scummfnt.nut", directory); + _sf[2]->loadFont("titlfnt.nut", directory); + } else if (_scumm->_gameId == GID_DIG) { + for(int i = 0; i < 4; i++) { + char file_font[11]; + sprintf((char *)&file_font, "font%d.nut", i); + _sf[i] = new SmushFont(i != 0, false); + _sf[i]->loadFont(file_font, directory); } - - char *old = filebuffer; - filebuffer = new char[length - ETRS_HEADER_LENGTH + 1]; - for(int32 i = ETRS_HEADER_LENGTH; i < length; i++) { - filebuffer[i - ETRS_HEADER_LENGTH] = old[i] ^ 0xCC; + } else if (_scumm->_gameId == GID_CMI) { + for(int i = 0; i < 5; i++) { + char file_font[11]; + sprintf((char *)&file_font, "font%d.nut", i); + _sf[i] = new SmushFont(false, true); + _sf[i]->loadFont(file_font, directory); } - filebuffer[length - ETRS_HEADER_LENGTH] = '\0'; - delete []old; - length -= ETRS_HEADER_LENGTH; - } - StringResource *sr = new StringResource; - assert(sr); - sr->init(filebuffer, length); - delete []filebuffer; - return sr; + } else { + error("SmushPlayer::init() Unknown font setup for game"); + } + + delete sub; } -bool SmushPlayer::readString(const char *file, const char *directory, bool &ft) { - const char *i = strrchr(file, '.'); - if(i == NULL) { - error("invalid filename : %s", file); - } - char fname[260]; - memcpy(fname, file, i - file); - strcpy(fname + (i - file), ".trs"); - if((_strings = getStrings(fname, directory, false)) != 0) { - ft = true; - return true; +void SmushPlayer::parseNextFrame() { + if (_scumm->_smushPlay == false) + return; + + Chunk *sub = _base->subBlock(); + if (_base->eof()) { + _scumm->_videoFinished = true; + return; } - if((_strings = getStrings("digtxt.trs", directory, true)) != 0) { - ft = false; - return true; - } - return false; -} - -static FontRenderer *loadFont(const char *file, const char *directory, bool original = false) { -#ifdef DEBUG - debug(5, "loading font from \"%s\"", file); -#endif - FontRenderer *fr = new FontRenderer(original); - SmushPlayer p(fr, false, false); - p.play(file, directory); - return fr; -} - -bool SmushPlayer::play(const char *file, const char *directory) { -#ifdef DEBUG - debug(5, "start of animation : %s", file); -#endif - clean(); - - if(_wait) { - bool isFullthrottle = false; - if(!readString(file, directory, isFullthrottle)) { -#ifdef DEBUG - debug(2, "unable to read text information for \"%s\"", file); -#endif - } - if((_strings) || (g_scumm->_gameId == GID_CMI)) { - if(isFullthrottle) { - _fr[0] = loadFont("scummfnt.nut", directory, true); - _fr[2] = loadFont("titlfnt.nut", directory, true); - } else { - for(int i = 0; i < 4; i++) { - char file_font[11]; - sprintf((char *)&file_font, "font%d.nut", i); - _fr[i] = loadFont(file_font, directory, i != 0); - } - } - } - if(g_scumm->_gameId == GID_CMI) { - for(int i = 0; i < 5; i++) { - char file_font[11]; - sprintf((char *)&file_font, "font%d.nut", i); - _fr[i] = loadFont(file_font, directory, false); - } - } - } - - File test; - test.open(file, directory); - if (!test.isOpen()) { - warning("Missing smush file %s", file); - return true; - } - test.close(); - - FileChunk base = FileChunk(file, directory); - - checkBlock(base, TYPE_ANIM); - - while(!base.eof()) { - Chunk *sub = base.subBlock(); - switch(sub->getType()) { - case TYPE_AHDR: - handleAnimHeader(*sub); - break; - case TYPE_FRME: - handleFrame(*sub); - break; - default: - error("Unknown Chunk found : %d, %d", sub->getType(), sub->getSize()); - } - delete sub; - if(_renderer->prematureClose()) { + switch(sub->getType()) { + case TYPE_FRME: + handleFrame(*sub); break; - } + default: + error("Unknown Chunk found : %d, %d", sub->getType(), sub->getSize()); } -#ifdef DEBUG - debug(5, "end of animation"); -#endif - if(_outputSound) { - _mixer->stop(); - } - return true; + delete sub; +} + +void SmushPlayer::setPalette(byte *palette) { + byte palette_colors[1024]; + byte *p = palette_colors; + byte *data = palette; + + for (int i = 0; i != 256; i++, data += 3, p += 4) { + p[0] = data[0]; // red + p[1] = data[1]; // green + p[2] = data[2]; // blue + p[3] = 0; + } + + _scumm->_system->set_palette(palette_colors, 0, 256); +} + +void SmushPlayer::updateScreen() { + int width = MIN(_width, _scumm->_realWidth); + int height = MIN(_height, _scumm->_realHeight); + + _scumm->parseEvents(); + _scumm->_system->copy_rect(_data, _width, 0, 0, width, height); + _scumm->_system->update_screen(); +} + +void SmushPlayer::play(const char *filename, const char *directory) { + setupAnim(filename, directory); + init(); + + while (true) { + _scumm->processKbd(); + _scumm->_system->delay_msecs(10); + if (_scumm->_videoFinished == true) + break; + if (_scumm->_saveLoadFlag) + break; + }; + + deinit(); } diff --git a/scumm/smush/smush_player.h b/scumm/smush/smush_player.h new file mode 100644 index 00000000000..73aefb56644 --- /dev/null +++ b/scumm/smush/smush_player.h @@ -0,0 +1,105 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2002-2003 The ScummVM project + * + * This program 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 2 + * of the License, or (at your option) any later version. + + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +#ifndef SMUSH_PLAYER_H +#define SMUSH_PLAYER_H + +#include "common/util.h" +#include "chunk.h" +#include "codec37.h" +#include "codec47.h" + +class SmushFont; +class SmushMixer; +class StringResource; + +class SmushPlayer { +private: + + Scumm *_scumm; + int _version; + int32 _nbframes; + SmushMixer *_smixer; + int16 _deltaPal[0x300]; + byte _pal[0x300]; + StringResource *_strings; + SmushFont *_sf[5]; + Codec37Decoder _codec37; + Codec47Decoder _codec47; + int dst_width, dst_height; + FileChunk *_base; + byte *_frameBuffer; + + bool _codec37Called; + bool _skipNext; + bool _subtitles; + bool _skips[37]; + int32 _frame; + + int _IACTchannel; + byte _IACToutput[4096]; + int32 _IACTpos; + bool _storeFrame; + int _soundFrequency; + bool _alreadyInit; + int _speed; + bool _outputSound; + +public: + + int _width, _height; + byte *_data; + bool _smushProcessFrame; + + SmushPlayer(Scumm *, int, bool); + ~SmushPlayer(); + void updatePalette(void); + void parseNextFrame(); + void init(); + void deinit(); + void setupAnim(const char *file, const char *directory); + void initCodecs(); + void updateScreen(); + void play(const char *filename, const char *directory); + void setPalette(byte *palette); + +protected: + + bool readString(const char *file, const char *directory); + void clean(); + void checkBlock(const Chunk &, Chunk::type, uint32 = 0); + void handleAnimHeader(Chunk &); + void handleFrame(Chunk &); + void handleNewPalette(Chunk &); + void handleFrameObject(Chunk &); + void handleSoundBuffer(int32, int32, int32, int32, int32, int32, Chunk &, int32); + void handleImuseBuffer(int32, int32, int32, int32, int32, int32, Chunk &, int32); + void handleSoundFrame(Chunk &); + void handleSkip(Chunk &); + void handleStore(Chunk &); + void handleFetch(Chunk &); + void handleImuseAction(Chunk &); + void handleTextResource(Chunk &); + void handleDeltaPalette(Chunk &); + void readPalette(byte *, Chunk &); +}; + +#endif